0

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

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

作者提到

使用托管数组而不是指针的性能成本是多少?使用托管数组不会比使用指针慢吗?这可能会让您感到惊讶,但根据我的测试,答案是否定的。在我的测试中,发现数组方法比指针方法至少快 10%。

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

我没有尝试过文章中描述的方法,但有人可以支持吗?或者也许它只是在某些条件下更快?

4

2 回答 2

3

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

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

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

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

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


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

于 2012-08-04T18:47:06.500 回答
1

10% 的性能差异没有统计学意义。由于添加了越界检查,托管代码中的数组访问往往会变慢。这可以通过抖动优化掉,但是对于您作为一维数组访问的二维结构来说,这并不容易。指针是不安全的,主要是因为它们在没有这种检查的情况下使用。

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

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

于 2012-08-04T19:01:04.607 回答