托管的像素数组比使用指针更快?

时间:2012-08-04 18:38:31

标签: c#

我最近看到了这篇文章,同时探讨了在像素级处理图像的各种方法。

http://www.codeproject.com/Articles/16403/Fast-Pointerless-Image-Processing-in-NET

作者提到

  

使用托管数组而不是指针的性能成本是多少?使用托管数组不会比使用指针慢吗?它可能会给你带来惊喜,但根据我的测试,答案是否定的。在我的测试中,发现数组方法比指针方法快至少10%。

我在像素级别处理图像的第一次尝试是使用GetPixel / SetPixel方法,这非常慢。然后我被引导到this link并且速度要快得多。

我没有尝试过文章中描述的方法,但有人可以支持吗?或者在某些情况下它可能只会更快?

2 个答案:

答案 0 :(得分:3)

这在很大程度上取决于您如何访问阵列。

如果在循环中使用数组的长度,编译器会识别出这一点,并且知道它不必检查索引的边界,因为循环本身使得索引不可能不在界限。这种访问数组的方式与使用指针的性能相近。

如果使用任意索引访问数组,编译器必须添加检查索引边界的代码,这将为每个访问添加一些指令。这种访问数组的方式比使用指针慢。

它还取决于使用指针的代码的效率。最后,即使您使用索引访问数组,也始终使用指针访问数组数据,因此始终可以编写指针代码,该代码至少与通过索引访问数组的代码一样高效。

此外,这取决于您正在进行多少处理。使用编组将数据移入和移动到图像意味着您已经移动了所有数据两次。如果您进行的处理很少,那就永远不会像访问数据那么快。


注意:用于编组文章中数据的方法仅在Stride值为正时才有效。如果图像上下颠倒存储在内存中(常见于位图文件),则Stride值为负值,计算出的数据大小为负值。

答案 1 :(得分:1)

10%的Perf差异无统计学意义。由于添加了越界检查,托管代码中的数组访问往往更慢。这可以通过抖动进行优化,但是使用二维结构可以将其作为单维数组进行访问。指针是不安全的,主要是因为它们在没有这种检查的情况下使用。

但是当您开始处理大量RAM时,代码速度变得毫无意义,例如存储非平凡大小的位图所需的数量。这种代码的性能受到存储器总线带宽的限制。这比处理器消耗数据的速率慢很多倍。现在开始变得重要的一件事是,您以优化L1处理器缓存使用的方式访问数据。这是访问位图像素的自然方式,您需要按列(X)顺序,而不是行顺序。换句话说,X变量需要是内循环,Y需要是外循环。

很有可能,你已经尽可能快地去了,特别是如果你复制带有这样声明的代码。证明它的唯一方法是实际编写使用指针的代码,这需要C#,并进行比较。