可能是重复问题:
倒数比正数循环更快吗?
哪种循环性能更好?我从某个地方学到第二种循环更好但想知道原因。
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<=10;i++)
{
/*This is better ?*/
}
for(int i=10;i>=0;i--)
{
/*This is better ?*/
}
第二种方法“可能”更好,因为与0比较i比与10比较i更容易,但我认为您可以使用任何一种方法,因为编译器会对它们进行优化。
i
与0进行比较比与10进行比较更容易? - 一二三我认为两个循环的性能差别不大。
但是,当循环像这样时,情况就不同了。
for(int i = 0; i < getMaximum(); i++)
{
}
for(int i = getMaximum() - 1; i >= 0; i--)
{
}
假设getMaximum()
函数不是内联函数,因为它会被调用一次或多次
如果硬件进行了优化,将递减循环计数器直到零有时可能更快。但这只是微小的优化,你应该进行性能分析,看看是否值得这样做。编译器通常会为您进行优化,而且由于递减循环可能表达意图更差,因此您通常最好坚持使用“正常”的方法。
在汇编指令中,递增和递减(翻译为INC和DEC)的速度相同,都是1个CPU周期。
然而,在一些体系结构(例如SPARC)上,理论上第二种方法可以更快,因为不需要从内存(或高速缓存)中获取10:大多数体系结构都有能够以优化方式处理与特殊值0进行比较的指令(通常有一个特殊的硬连线0寄存器用作操作数,因此不必为每个迭代的比较存储10),
聪明的编译器(特别是目标指令集为RISC时)会自行检测这一点,并且(如果您的计数器变量未在循环中使用)应用第二个“递减到0”的形式。
有关详细信息,请参见答案https://dev59.com/53E85IYBdhLWcg3wViA4#2823164和https://dev59.com/53E85IYBdhLWcg3wViA4#2823095。
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)
因此,即使在这种情况下,速度也是相同的。
再次强调,所有微性能问题的答案都是测量,在使用环境的情况下进行测量,不要推广到其他环境。
很长一段时间以来,计算指令执行时间一直需要非常复杂的技术才能实现。
处理器和内存速度之间的不匹配以及缓存的引入(但不包括带宽)使得一组指令的执行非常敏感于内存访问模式。这意味着您仍然可以通过相当高级的思考来优化,但也意味着如果不考虑内存访问模式,则表面上更糟糕的东西一旦考虑到这一点就可能更好。
然后超标量(处理器可以同时执行多个操作)和乱序执行(处理器可以在流程中先于前一个指令执行指令)使基本计数即使忽略内存访问也毫无意义。如果您想获得良好的先验估计,您必须知道哪些指令需要执行(因此忽略部分结构是不明智的)以及处理器如何分组指令。