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

C 哪个循环的性能更好?增加还是减少?,c,performance,C,Performance,可能重复: 哪个循环的性能更好?我从一些地方学到了第二个更好的方法。但我想知道原因 for(int i=0;i<=10;i++) { /*This is better ?*/ } for(int i=10;i>=0;i--) { /*This is better ?*/ } for(int i=0;i=0;i--) { /*这更好吗*/ } 编译器应该将两个代码

可能重复:

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

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


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

编译器应该将两个代码优化到同一个程序集,这样就不会有什么区别。两者都需要相同的时间

更有效的讨论是

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

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

如果在硬件中优化针对零的测试,递减循环下降到零的速度有时会更快。但这是一个微观优化,您应该根据看看是否真的值得这样做。编译器通常会为您进行优化,并且考虑到递减循环可以说是一种更糟糕的意图表达,您最好还是坚持使用“正常”方法。

我认为两个循环的性能没有太大差异

我想,当循环看起来像这样时,情况就不同了

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

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

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

递增和递减(INC和DEC,在转换为汇编命令时)的速度与1个CPU周期相同

然而,在某些(例如SPARC)体系结构上,第二种指令理论上可以更快,因为不必从内存(或缓存)中提取任何
10
:大多数体系结构在与特殊值
0
(通常有一个特殊的硬连线0寄存器用作操作数,因此不必“浪费”寄存器来存储每次迭代比较的
10

智能编译器(特别是当目标指令集是RISC时)本身会检测到这一点,并且(如果循环中未使用计数器变量)应用第二种“递减到0”形式


请参阅答案和了解更多详细信息。

同样,所有微观性能问题的答案都是测量,在使用上下文中测量,不要推断到其他上下文

在相当长的一段时间里,如果不具备非凡的复杂性,计算指令执行时间是不可能的

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


然后,超标量(处理器可以一次做几件事的事实)和无序执行(处理器可以在流中的前一条指令之前执行一条指令的事实)使得即使忽略内存访问,基本计数也变得毫无意义。你必须知道哪些指令需要执行(因此忽略部分结构是不明智的)如果你想得到一个好的先验估计,处理器如何对指令进行分组。

你测试过其中任何一个吗?你的循环有不同的界限:第一次运行0到9,第二次运行10到1。应该优化到同一个程序集……如果循环中使用了
i
,会怎么样?@Benoit我的意思是相同数量的指令。为什么比较
i
和0要比比较10容易些?+1让新手放松了一些,因为他的答案是正确的,因为大多数处理器都有比较零的指令,所以他们不需要加载
i
和10,减去它们然后比较零,但只需立即将
i
和零进行比较。+1因为他是蜜蜂n-1ed,无reason@funnyGraphicsThingy-因为将零检测为算术或逻辑结果通常不需要显式比较-CPU零标志已经设置。这和许多指令集提供循环/重复操作,可将寄存器自动倒计时为零。+1表示一条指令的执行时间在超标量架构上没有意义。桌面处理器在过去15年中一直是超标量的(1993年的奔腾是超标量的)。并非所有现代硬件都是流水线的。嵌入式处理器将与这种微优化有更大的相关性。此外,OP问题并没有特别针对现代桌面处理器,所以我认为答案应该是通用的,也应该是20年前的处理器设计(通常仍用作嵌入式CPU)问题是答案是它取决于。它取决于处理器ISA是否对一种或另一种有更好的支持。它取决于微体系结构是否能够利用ISA支持。编译器是否也能够利用(并且不能采取反措施,例如将10保存在寄存器中,看到循环以已知的少量时间执行并完全展开,或使用辅助递减计数器)。变量太多了。度量和上下文中的度量是唯一的答案,它对所有应用程序都有效。你是对的。但是,考虑到没有指定硬件类型、编译器类型或版本的组合,我宁愿指出一些通用的方法,这种方法对于极少数这样的组合更快(虽然速度较慢,但没有),而不是专注于这样一个事实:毫无疑问,首先做这些断章取义的微基准毫无意义。
   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) 
for(int i = 0; i < getMaximum(); i++)
{
}

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