我今天早上与同事讨论了关于for-loop-optimization的讨论。这几乎是this question中描述的情况,但是代码是C ++ / CLI,并且该方法从不同的程序集中调用属性。我知道在这种情况下,编译器不能通过内联函数来优化循环。然而,主题是图像处理,所谓的属性是图像的宽度和高度,即:
for (unsigned int y = 0; y < image.Height; ++y) {
for (unsigned int x = 0; x < image.Width; ++x) {
// Do something with pixel x,y
}
}
对于5M灰度图像,该循环花费大约450毫秒,而在执行循环之前将宽度和高度保存到局部变量时,时间消耗大约为10毫秒! (这些数字仅用于显示差异的大小。)
当然,我们现在正在寻找局部变量解决方案,但我想知道上面给出的天真for循环是否真的是糟糕的设计?在编写这样的代码时,我不希望任何真正的编译器优化,但是调用平凡的属性,如图像的宽度和高度,我希望能够更快地返回它们的值。由于图像库作者设计不好,问题不是整个问题吗?当使用琐碎的属性时,我不应该提供可读性吗?
答案 0 :(得分:0)
我同意设计决定有点奇怪,至少在事物的表面上。 System.Drawing
中的许多基础数据类型映射到本机GDI(?)类型,这将减慢简单的事情。
最有可能的是,一旦你真的想要将图像绘制到屏幕上,它会加快速度,因为在实际绘制图像时没有额外的映射到本机类型。
例如,Image.Height
;
public int Height {
get {
int height;
int status = SafeNativeMethods.Gdip.GdipGetImageHeight(new HandleRef(this, nativeImage), out height);
if (status != SafeNativeMethods.Gdip.Ok)
throw SafeNativeMethods.Gdip.StatusException(status);
return height;
}
}
内联此方法不一定会提高性能,大部分时间很可能花在获取实际高度的本机调用上,这就是为什么一次取出Height
而不是在循环中取({in this案例设计)使事情变得更快。