我只是偶然发现了一个似乎具有违反直觉性能影响的变化.任何人都可以为这种行为提供可能的解释吗?
原始代码:
for (int i = 0; i < ct; ++i) { // do some stuff... int iFreq = getFreq(i); double dFreq = iFreq; if (iFreq != 0) { // do some stuff with iFreq... // do some calculations with dFreq... } }
在“性能传递”期间清理此代码时,我决定在if块中移动dFreq的定义,因为它仅在if中使用.有几个涉及dFreq的计算,所以我没有完全消除它,因为它确实节省了从int到double的多个运行时转换的成本.我预计没有任何性能差异,或者如果有的话,可以忽略不计的改进.然而,性能下降了近10%.我已经多次测量过,这确实是我做过的唯一改变.上面显示的代码片段在几个其他循环内执行.我在运行中获得非常一致的时序,并且可以肯定地确认我所描述的变化会使性能降低约10%.我希望性能提高,因为int到double的转换只会在iFreq!= 0时发生.
中断代码:
for (int i = 0; i < ct; ++i) { // do some stuff... int iFreq = getFreq(i); if (iFreq != 0) { // do some stuff with iFreq... double dFreq = iFreq; // do some stuff with dFreq... } }
有谁能解释一下?我使用VC 9.0和/ O2.我只是想了解我在这里没有考虑的问题.
解决方法
在使用iFreq进行计算之前,您应该立即将转换放入if()中的dFreq.如果指令在代码中更远,则转换可以与整数计算并行执行.一个好的编译器可能能够将它推得更远,而一个不那么好的编译器可能会把它放在它落到的地方.由于您将其移动到整数计算之后,它可能无法与整数代码并行运行,从而导致速度减慢.如果它确实并行运行,那么取决于cpu(发出FP指令,其结果从未使用过,对原始版本影响不大)可能几乎没有任何改进.
如果你真的想要提高性能,许多人已经做了基准测试并按以下顺序对以下编译器进行排名:
1)ICC – 英特尔编译器
2)海湾合作委员会 – 一个很好的第二名
3)MSVC生成的代码与其他代码相比可能非常差.
如果有的话,您可能还想尝试-O3.