if(a<901)是否比if(a<=900)快?
与这个简单示例中的情况不同,但循环复杂代码的性能略有变化。我想这需要对生成的机器代码进行一些处理,以防它是真的。
if(a<901)是否比if(a<=900)快?
与这个简单示例中的情况不同,但循环复杂代码的性能略有变化。我想这需要对生成的机器代码进行一些处理,以防它是真的。
当前回答
TL;DR答案
对于架构、编译器和语言的大多数组合,<不会比<=快。
完整答案
其他答案都集中在x86架构上,我不太了解ARM架构(您的示例汇编程序似乎是这样),无法对生成的代码进行具体评论,但这是一个非常特定于架构的微优化示例,很可能是反优化,也可能是优化。
因此,我认为这种微优化是货物崇拜编程的一个例子,而不是最佳软件工程实践。
反例
可能有一些架构是优化的,但我知道至少有一种架构可能是相反的。古老的Transputer体系结构只有等于和大于或等于的机器代码指令,因此所有比较都必须从这些原语构建。
即使如此,在几乎所有的情况下,编译器都可以以这样的方式对求值指令进行排序,即在实践中,没有任何比较比任何其他比较都有任何优势。但最坏的情况是,它可能需要添加反向指令(REV)来交换操作数堆栈上的前两项。这是一个单字节指令,它需要一个周期才能运行,因此开销最小。
总结
像这样的微优化是优化还是反优化取决于您正在使用的特定架构,因此养成使用特定架构的微优化的习惯通常是一个坏主意,否则您可能会在不合适时本能地使用微优化,看起来这正是您正在阅读的书所倡导的。
其他回答
也许那本无名书的作者读到a>0比a>=1跑得更快,并认为这是普遍正确的。
但这是因为涉及0(因为CMP可以根据体系结构,例如用OR替换),而不是因为<。
即使有差异,你也不应该注意到。此外,在实践中,除非你要使用一些神奇的常数,否则你必须做一个额外的a+1或a-1来使条件成立,这无论如何都是一个非常糟糕的实践。
您可以说这行在大多数脚本语言中都是正确的,因为额外的字符会导致代码处理稍慢。然而,正如上面的答案所指出的,它在C++中应该没有任何影响,而使用脚本语言所做的任何事情都可能不太关心优化。
对于浮点代码,甚至在现代体系结构上,<=比较可能确实会慢一些(一条指令)。这是第一个函数:
int compare_strict(double a, double b) { return a < b; }
在PowerPC上,首先执行浮点比较(更新条件寄存器cr),然后将条件寄存器移动到GPR,将“比较小于”位移位到位,然后返回。它需要四个指令。
现在考虑一下这个函数:
int compare_loose(double a, double b) { return a <= b; }
这需要与上面的compare_strict相同的工作,但现在有两个有趣的位:“小于”和“等于”。这需要一个额外的指令(cror-condition寄存器逐位OR)将这两个位组合为一。因此,compare_sloose需要五条指令,而compare_sstrict需要四条指令。
您可能认为编译器可以这样优化第二个函数:
int compare_loose(double a, double b) { return ! (a > b); }
然而,这将错误地处理NaN。NaN1<=NaN2和NaN1>NaN2都需要评估为假。
仅当计算路径依赖于数据时:
a={1,1,1,1,1000,1,1,1,1}
while (i<=4)
{
for(j from 0 to a[i]){ do_work(); }
i++;
}
将计算250倍以上的时间(i<4)
真实世界的例子是计算曼德布洛特集合。如果包含一个迭代1000000次的像素,它将导致延迟,但与<=使用概率的重合度太低。