哪个循环有更好的性能?我从一些地方学到了第二个更好的地方。但想知道原因。
for(int i=0;i<=10;i++)
{
/*This is better ?*/
}
for(int i=10;i>=0;i--)
{
/*This is better ?*/
}
答案 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/1018783和https://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)
同样,所有微观绩效问题的答案都是衡量,在使用环境中衡量 ,并且不会推断到其他情境。
在相当长的时间内,如果没有非凡的复杂性,就无法计算指令执行时间。
处理器和内存速度之间的不匹配以及引入缓存以隐藏部分延迟(但不是带宽)使得一组指令的执行对内存访问模式非常敏感。这是你仍然可以通过相当高水平的思考来优化的东西。但是,这也意味着,如果不考虑内存访问模式,那么显然会更糟糕的事情一旦完成就会更好。
然后超标量(处理器可以同时执行多项操作)和乱序执行(处理器可以在流中的前一个之前执行指令的事实)使得基本计数毫无意义,即使您忽略内存访问。您必须知道需要执行哪些指令(因此忽略部分结构并不明智)以及如果您希望获得良好的先验估计,处理器可以如何对指令进行分组。