Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 真正的不安全代码性能_C#_Performance_Unsafe - Fatal编程技术网

C# 真正的不安全代码性能

C# 真正的不安全代码性能,c#,performance,unsafe,C#,Performance,Unsafe,我知道不安全代码更适合访问Windows API之类的东西,并进行不安全类型转换,而不是编写性能更高的代码,但是我想问你,与安全的c#代码相比,你是否注意到在现实世界的应用程序中使用它有任何显著的性能改进。图像处理就是一个很好的例子。通过使用指向像素字节的指针(这需要不安全的代码)修改像素要快得多 例如: 尽管如此,在大多数情况下,差异不会那么明显。因此,在使用不安全代码之前,请分析应用程序以了解性能瓶颈所在,并测试不安全代码是否真的是提高速度的解决方案 正如在其他帖子中所述,您可以在非常专业的

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

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

例如:


尽管如此,在大多数情况下,差异不会那么明显。因此,在使用不安全代码之前,请分析应用程序以了解性能瓶颈所在,并测试不安全代码是否真的是提高速度的解决方案

正如在其他帖子中所述,您可以在非常专业的环境中使用不安全的代码,以获得显著的性能改进。其中一个场景是迭代值类型的数组。使用不安全的指针算法比使用for循环/索引器的常规模式快得多

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...
    }
}
这里的主要好处是,我们完全取消了数组索引检查


这种代码虽然性能很好,但很难处理,可能非常危险(不安全),并且违反了一些基本准则(可变结构)。但在某些情况下,这是适当的…

一些性能度量值

性能优势并没有您想象的那么大

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


使用 任何CPU版本均基于以下PC规格:基于x64的PC,1个四核处理器。Intel64系列6型23步进10 GenuineIntel~2833 Mhz

请注意,不安全的
*(p++)
习惯用法实际上运行得较慢。我猜这打破了编译器优化,在安全版本中将循环变量和(编译器生成的)指针访问结合在一起


源代码可在上获得。

好吧,我建议您阅读以下博文:


这澄清了如何在C#中进行边界检查。此外,Thomas Bratts测试在我看来似乎毫无用处(查看代码),因为JIT在他的“保存”循环中删除了绑定检查。

我使用不安全的代码来处理视频代码。 在这样的代码中,您希望它在没有对值等进行内部检查的情况下尽可能快地运行。如果没有不安全的属性,my将无法以30fps或60fps的速度跟上视频流。(取决于使用的摄像机)


但是,由于速度的原因,它被编写图形代码的人广泛使用。

对于所有看到这些答案的人,我想指出的是,尽管答案非常优秀,但答案已经发布,这已经改变了很多

请注意,.net已经发生了很大的变化,现在还可以访问新的数据类型,如vectors、Span、ReadOnlySpan以及特定于硬件的库和类,如core 3.0中的库和类


看看这篇文章,看看如何使用硬件优化的循环,如果没有优化的硬件,这是安全的方法

p/Invoke与
unsafe
。。。我不确定原因是什么。。。此外:你有没有衡量过你在这里做的事情是否有用?安全或不安全都不应该比事实上更有效。总体性能取决于您在代码中实现的算法。我现在没有使用不安全的代码。我只是想了解是否值得将代码的关键部分更改为不安全的代码。为什么您认为“不安全”意味着“更好的性能”?只有在一些特殊情况下才是如此。在考虑
不安全的问题之前,请确保您知道如何有效地使用C。避免过度创建临时对象。何时使用结构数组,以及需要注意的问题<代码>缓冲区.块复制
。JIT优化数组外边界检查的条件。(我不是专家,只是说说我的想法。)谷歌C#高性能和C#性能提示。安全的图像处理也可以相当快。特别是如果可以编写算法来消除边界奇点。我只使用不安全的代码将数据从位图复制到数组中并返回。如果你使用
byte[]
你甚至可以避免这种情况,只需使用
封送
函数。@Botz3000:这是一个很好的链接(期待阅读网站的其余部分),但结论并不可靠。使用
GetPixel
SetPixel
确实很慢,但使用
int[]
与使用指针差不多快,没有缺点。@CodeInChaos:我不得不同意。我得出的结论是,唯一受益的领域是复制位图数据。不过,我还没有尝试使用
封送处理
。我在那篇文章中看到了很多代码问题。在内部循环中迭代y意味着不按顺序访问内存。另外,从C#properties访问诸如height之类的原语,而不是首先将该原语复制到局部变量,这意味着大量昂贵的堆获取操作正在发生。第三,使用函数调用GetPixel而不是将指针算法内联到循环中涉及大量开销。使用本文中的代码,您将看到大约100倍的性能损失。这是如何使用不安全代码的一个可怕的例子。@Botz3000正如我上面所说的,您将看到大约100倍的性能损失(基于我自己所做的测试)。当然,它会比使用Graphics.GetPixel更快,但我的I7也比我车库里的commodore快。一篇关于使用不安全代码来加快计算速度的文章在我看来不应该有太多的错误。这种代码的另一个大缺点是C语言的比例不高
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