真正的不安全代码性能

时间:2011-03-21 07:18:18

标签: c# performance unsafe

我理解不安全的代码更适合访问Windows API之类的东西并进行不安全的类型转换,而不是编写更高性能的代码,但我想问你是否注意到在实际应用程序中有任何显着的性能提升与安全的c#代码相比,使用它。

6 个答案:

答案 0 :(得分:23)

一些效果指标

性能优势并不像您想象的那么大。

我对C#中的不安全指针进行了一些正常托管数组访问的性能测量。


使用.NET在Visual Studio 2010,.NET 4之外的构建运行的结果 任何CPU |发布基于以下PC规范:基于x64的PC,1个四核处理器。 Intel64 Family 6 Model 23 Stepping 10 GenuineIntel~2833 Mhz

Linear array access
 00:00:07.1053664 for Normal
 00:00:07.1197401 for Unsafe *(p + i)

Linear array access - with pointer increment
 00:00:07.1174493 for Normal
 00:00:10.0015947 for Unsafe (*p++)

Random array access
 00:00:42.5559436 for Normal
 00:00:40.5632554 for Unsafe

Random array access using Parallel.For(), with 4 processors
 00:00:10.6896303 for Normal
 00:00:10.1858376 for Unsafe

请注意,不安全的*(p++)成语实际上运行速度较慢。我的猜测打破了编译器优化,即在安全版本中组合了循环变量和(编译器生成的)指针访问。

github上提供的源代码。

答案 1 :(得分:15)

正如其他帖子中所述,您可以在非常专业的环境中使用不安全的代码,以获得显着的性能提升。其中一种情况是迭代值类型的数组。使用不安全的指针算法比使用for-loop / indexer的常用模式要快得多。

struct Foo
{
    int a = 1;
    int b = 2;
    int c = 0;
}

Foo[] fooArray = new Foo[100000];

fixed (Foo* foo = fooArray)  // foo now points to the first element in the array...
{
    var remaining = fooArray.length;
    while (remaining-- > 0)
    {
        foo->c = foo->a + foo->b;
        foo++;  // foo now points to the next element in the array...
    }
}

这里的主要好处是我们完全删除了数组索引检查。

虽然性能非常高,但这种代码很难处理,可能非常危险(不安全),并且破坏了一些基本的指导原则(可变结构)。但是有一些情况确实适合......

答案 2 :(得分:14)

一个很好的例子是图像处理。通过使用指向其字节的指针(需要不安全的代码)来修改像素要快得多。

示例:http://www.gutgames.com/post/Using-Unsafe-Code-for-Faster-Image-Manipulation.aspx

话虽如此,对于大多数情况来说,差异并不明显。因此,在使用不安全的代码之前,请对应用程序进行概要分析,以查看性能瓶颈的位置,并测试不安全的代码是否真的是使其更快的解决方案。

答案 3 :(得分:1)

好吧,我建议你阅读这篇博文:MSDN blogs: Array Bounds Check Elimination in the CLR

这阐明了如何在C#中完成边界检查。此外,Thomas Bratts测试似乎对我没用(查看代码),因为JIT在他的'save'循环中删除了绑定检查。

答案 4 :(得分:0)

我正在使用不安全的代码来处理视频操作代码。 在这样的代码中,您希望它尽可能快地运行,而无需对值进行内部检查等。如果没有不安全的属性,我可能无法以30fps或60 fps跟上视频流。 (取决于使用过的相机)。

但由于速度,它被编码图形的人广泛使用。

答案 5 :(得分:0)

对于所有正在寻找这些答案的人,我想指出的是,即使答案非常好,但许多罪恶已经改变,答案已经发布。

请注意,.net发生了很大变化,现在还可以访问新数据类型,例如向量,Span,ReadOnlySpan以及特定于硬件的库和类,例如核心System.Runtime.Intrinsics中的类3.0

请查看此blog帖子,以了解如何使用硬件优化的循环,以及在没有最佳硬件的情况下使用此blog how to fallback的安全方法。

相关问题