C#中的循环反转加速应用程序

Ais*_*war 14 c# optimization performance loops

我们正在使用EmguCV开发视频处理应用程序,最近不得不做一些像素级操作.我最初编写循环来遍历图像中的所有像素,如下所示:

for (int j = 0; j < Img.Width; j++ )
{
    for (int i = 0; i < Img.Height; i++)
    {
        // Pixel operation code
    }
}
Run Code Online (Sandbox Code Playgroud)

执行循环的时间非常糟糕.然后我发布在EmguCV论坛上并得到一个建议切换这样的循环:

for (int j = Img.Width; j-- > 0; )
{
    for (int i = Img.Height; i-- > 0; )
    {
        // Pixel operation code
    }
}
Run Code Online (Sandbox Code Playgroud)

我很惊讶地发现代码执行的时间是一半!

我唯一能想到的是每次访问一个属性时在循环中进行的比较,它不再需要.这是加速的原因吗?或者还有其他什么?我很高兴看到这种改善.如果有人能澄清其原因,我会很高兴.

Joh*_*ler 14

所不同的是没有分支的成本,那就是你获取对象属性的事实Img.Width,并Img.Height在内部循环.优化器无法知道这些是用于该循环的常量.

这样做你应该获得相同的性能加速.

const int Width = Img.Width;
const int Height = Img.Height;
for (int j = 0; j < Width; j++ )
{
    for (int i = 0; i < Height; i++)
    {
        // Pixel operation code
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

正如Joshua建议的那样,将Width放在内部循环中会让你顺序遍历内存,这将是更好的缓存一致性,并且可能更快.(取决于你的位图有多大).

const int Width = Img.Width;
const int Height = Img.Height;
for (int i = 0; i < Height; i++)
{
    for (int j = 0; j < Width; j++ )
    {
        // Pixel operation code
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 而且,几乎在宽度之外的高度上方循环.你的L1缓存会感谢你. (2认同)

Mic*_*tum 13

我假设您正在使用System.Drawing.Image类?看看.Width和.Height的实现我看到他们对gDI +(gdiplus文件中的GdipGetImageHeight和GdipGetImageWidth)执行函数调用,这看起来相当昂贵.

通过向后移动,您可以进行一次调用,而不是每次迭代.