循环展开是帮助编译器优化性能的常用方法.我想知道是否以及在多大程度上性能增益受到循环体内的影响:
报告数量
函数调用次数
使用复杂的数据类型,虚拟方法等
动态(de)分配内存
你用什么规则来决定是否要解除性能关键循环?在这些情况下,您还考虑了哪些其他优化?
通常,手动展开循环是不值得的.编译器更好地了解目标体系结构的工作原理,并在有益的情况下展开循环.
有些代码路径在Pentium-M型CPU的展开时会受益,但是对Core2没有好处.如果我手动展开,编译器就不能再做出决定了,我最终可能会得到不太理想的代码.就像我试图实现的完全相反.
在某些情况下,我会手动展开性能关键循环,但是如果我知道编译器在手动展开后能够使用架构特定功能(如SSE或MMX指令),我就会这样做.然后,我才这样做.
顺便说一句 - 现代CPU在执行可预测的分支方面非常有效.这正是一个循环.这些循环开销如此之小,以至于它很少有所作为.然而,由于代码大小的增加而可能发生的内存延迟效应会产生影响.
这是一个优化问题,因此只有一个经验法则:测试性能,并且只有在您的测试证明您需要时才尝试循环展开优化.首先考虑破坏性较小的优化.
根据我的经验,循环展开,以及在以下情况下所需的工作是有效的:
循环中只有几个语句.
语句只涉及少量不同的变量而没有函数调用
您的操作适用于已分配的内存(例如,就地图像转换)
对于80%的增益,部分展开通常较少.因此,不是循环N×M图像(N M次迭代)的所有像素,其中N总是可被8整除,在8个像素的每个块上循环(N M/8)次.如果您正在执行某些使用某些相邻像素的操作,则此功能尤其有效.
我已经有非常好的结果手工优化像素操作到MMX或SSE指令(一次8或16像素)但我也花了几天时间优化一些东西只是为了找出编译器优化的版本运行快了十倍.
顺便说一句,对于循环展开的最(美丽)的例子,请查看Duffs设备