哪个循环有更好的性能?增加还是减少?

时间:2012-01-23 08:24:27

标签: c performance

  

可能重复:
  Is it faster to count down than it is to count up?

哪个循环有更好的性能?我从一些地方学到了第二个更好的地方。但想知道原因。

  for(int i=0;i<=10;i++)
      {
               /*This is better ?*/
      }


  for(int i=10;i>=0;i--)
      {
               /*This is better ?*/
      }

6 个答案:

答案 0 :(得分:18)

第二个“可能”会更好,因为将i与0进行比较比将i与10进行比较更容易,但我认为您可以使用其中任何一个,因为编译器会优化它们。

答案 1 :(得分:7)

认为两个循环的性能之间存在很大差异。

我想,当循环看起来像这样时,它会变成另一种情况。

for(int i = 0; i < getMaximum(); i++)
{
}

for(int i = getMaximum() - 1; i >= 0; i--)
{
}

因为getMaximum()函数被调用一次或多次(假设它不是内联函数)

答案 2 :(得分:5)

如果在硬件中优化针对零的测试,则递减循环降至零有时会更快。但这是一个微观优化,你应该分析一下它是否真的值得做。编译器通常会为你进行优化,并且假设减量循环可以说是更糟糕的意图表达,那么你通常会更好地坚持使用“正常”方法。

答案 3 :(得分:2)

递增和递减(INC和DEC,当转换为汇编程序命令时)具有相同的1 CPU周期速度。

然而,在某些(例如SPARC)架构中,第二个理论上可以更快,因为不必从内存(或缓存)获取10:大多数架构都有处理的指令与特殊值0进行比较时的优化方式(通常有一个特殊的硬连线0寄存器用作操作数,因此不必为了每次迭代的比较而“浪费”寄存器来存储10

智能编译器(特别是如果目标指令集是RISC)本身会检测到这个并且(如果你的计数器变量没有在循环中使用)应用第二个“递减downto 0”表单。

有关详细信息,请参阅答案https://stackoverflow.com/a/2823164/1018783https://stackoverflow.com/a/2823095/1018783

答案 4 :(得分:1)

编译器应该将两个代码优化到同一个程序集,因此它没有什么区别。两者都需要同一时间。

更有效的讨论是

  for(int i=0;i<10;++i)  //preincrement
  {
  }

会比

更快
  for(int i=0;i<10;i++)  //postincrement
  {
  }

因为理论上,后增量会执行额外的操作(返回对旧值的引用)。但是,即使这样也应该优化到同一个组件。

如果没有优化,代码将如下所示:

   for ( int i = 0; i < 10 ; i++ )
0041165E  mov         dword ptr [i],0 
00411665  jmp         wmain+30h (411670h) 
00411667  mov         eax,dword ptr [i] 
0041166A  add         eax,1 
0041166D  mov         dword ptr [i],eax 
00411670  cmp         dword ptr [i],0Ah 
00411674  jge         wmain+68h (4116A8h) 

   for ( int i = 0; i < 10 ; ++i )
004116A8  mov         dword ptr [i],0 
004116AF  jmp         wmain+7Ah (4116BAh) 
004116B1  mov         eax,dword ptr [i] 
004116B4  add         eax,1 
004116B7  mov         dword ptr [i],eax 
004116BA  cmp         dword ptr [i],0Ah 
004116BE  jge         wmain+0B2h (4116F2h) 

   for ( int i = 9; i >= 0 ; i-- )
004116F2  mov         dword ptr [i],9 
004116F9  jmp         wmain+0C4h (411704h) 
004116FB  mov         eax,dword ptr [i] 
004116FE  sub         eax,1 
00411701  mov         dword ptr [i],eax 
00411704  cmp         dword ptr [i],0 
00411708  jl          wmain+0FCh (41173Ch) 

所以即使在这种情况下,速度也是一样的。

答案 5 :(得分:0)

同样,所有微观绩效问题的答案都是衡量,在使用环境中衡量 ,并且不会推断到其他情境。

在相当长的时间内,如果没有非凡的复杂性,就无法计算指令执行时间。

处理器和内存速度之间的不匹配以及引入缓存以隐藏部分延迟(但不是带宽)使得一组指令的执行对内存访问模式非常敏感。这是你仍然可以通过相当高水平的思考来优化的东西。但是,这也意味着,如果不考虑内存访问模式,那么显然会更糟糕的事情一旦完成就会更好。

然后超标量(处理器可以同时执行多项操作)和乱序执行(处理器可以在流中的前一个之前执行指令的事实)使得基本计数毫无意义,即使您忽略内存访问。您必须知道需要执行哪些指令(因此忽略部分结构并不明智)以及如果您希望获得良好的先验估计,处理器可以如何对指令进行分组。