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)
Mic*_*tum 13
我假设您正在使用System.Drawing.Image类?看看.Width和.Height的实现我看到他们对gDI +(gdiplus文件中的GdipGetImageHeight和GdipGetImageWidth)执行函数调用,这看起来相当昂贵.
通过向后移动,您可以进行一次调用,而不是每次迭代.