循环递减比增量更有效吗?

ret*_*n 0 3 c++ loops processor

可能重复:
倒计时比计数更快?

例如,

for (int i = 0; i < max; i++)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

for (int i = max-1; i >= 0; i--)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

这两个循环基本相同,并假设循环不包含任何数组操作.但是,对于第一种情况,每次迭代都需要将max加载到处理器中的寄存器中,然后在i和max之间进行比较..另一方面,后一种情况不需要将0加载到寄存器中,因为0已经是在寄存器中,所以只有后一个循环的比较.如果我错了,请纠正我,如果我是对的,请详细说明.谢谢.

Ed *_* S. 5

由省略号表示的代码几乎肯定会将任何实际的性能差异归结为仅仅是噪声.但是,在所有假设中,你都不正确.

每次迭代都需要将max加载到处理器的寄存器中,然后在i和max之间进行比较

也许,但可能不是.这取决于您的代码,但任何理智的优化编译器都能够检测计数器是否在迭代之间发生变化.

我不确定你的想法在哪里,但它们有点被误导,并没有考虑优化编译器的工作原理.看看你的反汇编,看看你真正的区别是什么.哦,到底是什么,我会做的(无论如何都很有趣):

该计划是:

int main(int argc, char *argv[]){   
    int max = 10;
    for (int i = max-1; i >= 0; i--)
    {
        cout << i;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

生成的程序集(VS2010发布,评论我自己)是:

int main(int argc, char *argv[]){   
00341000  push        esi  
    int max = 10;
    for (int i = max-1; i >= 0; i--)
00341001  mov         esi,9               ; move a static 9 into esi
00341006  jmp         main+10h (341010h)  
00341008  lea         esp,[esp]           ; load the address of whatever
0034100F  nop                             ; esp points to in memory 
    {                                     ; (not a memory fetch, just address calculation)
        cout << i;
00341010  mov         ecx,dword ptr [__imp_std::cout (342048h)]  
00341016  push        esi  
00341017  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (342044h)]  
0034101D  dec         esi                 ; decrement counter
0034101E  jns         main+10h (341010h)  ; jump if not signed
    }
Run Code Online (Sandbox Code Playgroud)

对于更惯用的版本......

int main(int argc, char *argv[]){   
00AC1000  push        esi  
    int max = 10;
    for (int i = 0; i < max; i++)
00AC1001  xor         esi,esi  
    {
        cout << i;
00AC1003  mov         ecx,dword ptr [__imp_std::cout (0AC2048h)]  
00AC1009  push        esi  
00AC100A  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0AC2044h)]  
00AC1010  inc         esi               ; increment esi
00AC1011  cmp         esi,0Ah           ; compare to 10 (0Ah)
00AC1014  jl          main+3 (0AC1003h) ; if less, jump to top 
    }
Run Code Online (Sandbox Code Playgroud)

所以是的,第一个版本使用jns指令(如果没有签名则跳转),因此比较被简化了一点(比较为0).它还包含一些指令,但没有比较.

但请注意,在第二版中进行的比较也是静态的.它知道max整个循环不会改变,所以它可以相应地优化该位.

我强烈重申,这不可能产生可观的性能优势.即使我的Windows PC上的高性能计时器也无法在两者之间给出一个很好的统计差异,因为调用cout需要比循环指令更长的时间.