哪个运算符更快(>或> =),(<或<=)?

<更便宜(更快)而不是<= ,同样地, >>=更便宜(更快)?

免责声明:我知道我可以测量,但这只会在我的机器上,我不确定答案是否可以是“特定于实现”或类似的东西。

它有所不同,首先从检查不同的指令集开始,以及编译器如何使用这些指令集。 以openrisc 32为例,这显然是mips的启发,但条件不同。 对于or32,有比较和设置标志指令,如果小于或等于无符号则比较这两个寄存器然后设置标志,如果相等则设置标志比较这两个寄存器。 然后有两个条件分支指令分支在标志集和分支标志清除。 编译器必须遵循其中一个路径,但是,少于,小于或等于,大于等都将使用相同数量的指令,相同的条件分支执行时间和相同的执行时间不执行条件分支。

现在,对于大多数体系结构而言,由于必须刷新并重新填充管道,执行分支所花费的时间比不执行分支要长。 有些人做分支预测等来帮助解决这个问题。

现在一些指令大小的架构可能会有所不同,比较gpr0和gpr1与比较gpr0和立即数1234,可能需要更大的指令,例如,你会看到很多用x86。 所以尽管这两种情况都可能是一个分支,如果你的编码方式少于你编码的数量,这取决于什么样的寄存器可以保持什么值可以产生性能差异(确保x86做了大量的流水线操作,大量的缓存等来弥补这些问题)。 另一个类似的例子是mips和or32,其中r0总是为零,它实际上不是通用寄存器,如果你写它没有改变,它硬连线到零,所以比较如果等于0 MIGHT花费你如果一个额外的指令或两个需要一个额外的指令来填充一个gpr,以便比较可以发生,最坏的情况是必须将一个寄存器驱逐到堆栈或内存,以释放注册以将直接放在那里以便比较可以发生。

有些架构像arm一样有条件执行,因为你可以在每个指令的基础上执行完整的arm(非拇指)指令,所以如果你有代码

 if(i==7) j=5; else j=9; 

arm的伪代码就是

 cmp i,#7 moveq j,#5 movne j,#7 

没有实际的分支,所以没有管道问题你飞得很快,非常快。

一个架构到另一个,如果这是一个有趣的比较,如上所述,mips,或32,你必须专门执行某种比较的指令,其他像x86,msp430和绝大多数alu操作改变旗帜,arm和比如改变标志,如果你告诉它改变标志,否则不要如上所示。 所以a

 while(--len) { //do something } 

循环减去1也设置标志,如果循环中的东西足够简单,你可以使整个事件有条件,所以你保存在单独的比较和分支指令上,你节省了管道惩罚。 Mips通过比较解决了这个问题,并且branch是一条指令,并且它们在分支之后执行一条指令以在管道中保存一点。

一般的答案是你不会看到差异,指令的数量,执行时间等对于各种条件是相同的。 特殊情况,例如小的immediates vs big immediates等可能会对角落情况产生影响,或者编译器可能只是根据你做的比较选择不同的方式。 如果您尝试重新编写算法以使其给出相同的答案但使用小于而不是大于等于,则可以更改代码以获得不同的指令流。 同样,如果执行过于简单的性能测试,编译器可以/将优化比较完成并生成结果,这可能会因测试代码的不同而导致执行不同。 所有这一切的关键是反汇编你想要比较的东西,看看指令的不同之处。 这将告诉您是否应该看到任何执行差异。

TL; DR

四个运营商之间几乎没有差别,因为它们几乎在同一时间对我来说( 在不同的系统上可能会有所不同! )。 因此,如果有疑问,只需使用对情况最有意义的运算符(特别是在使用C ++时)。

所以,不用多说,这是一个很长的解释:

假设整数比较:

就生成程序集而言,结果取决于平台。 在我的计算机(Apple LLVM编译器4.0,x86_64)上,结果(生成的程序集如下):

 a < b (uses 'setl'): movl $10, -8(%rbp) movl $15, -12(%rbp) movl -8(%rbp), %eax cmpl -12(%rbp), %eax setl %cl andb $1, %cl movzbl %cl, %eax popq %rbp ret a <= b (uses 'setle'): movl $10, -8(%rbp) movl $15, -12(%rbp) movl -8(%rbp), %eax cmpl -12(%rbp), %eax setle %cl andb $1, %cl movzbl %cl, %eax popq %rbp ret a > b (uses 'setg'): movl $10, -8(%rbp) movl $15, -12(%rbp) movl -8(%rbp), %eax cmpl -12(%rbp), %eax setg %cl andb $1, %cl movzbl %cl, %eax popq %rbp ret a >= b (uses 'setge'): movl $10, -8(%rbp) movl $15, -12(%rbp) movl -8(%rbp), %eax cmpl -12(%rbp), %eax setge %cl andb $1, %cl movzbl %cl, %eax popq %rbp ret 

这并没有真正告诉我什么。 所以,我们跳到一个基准:

女士们,先生们,结果是,我创建了以下测试程序(我知道’时钟’不是计算这样结果的最好方法,但现在必须要做)。

 #include  #include  #define ITERS 100000000 int v = 0; void testL() { clock_t start = clock(); v = 0; for (int i = 0; i < ITERS; i++) { v = i < v; } printf("%s: %lu\n", __FUNCTION__, clock() - start); } void testLE() { clock_t start = clock(); v = 0; for (int i = 0; i < ITERS; i++) { v = i <= v; } printf("%s: %lu\n", __FUNCTION__, clock() - start); } void testG() { clock_t start = clock(); v = 0; for (int i = 0; i < ITERS; i++) { v = i > v; } printf("%s: %lu\n", __FUNCTION__, clock() - start); } void testGE() { clock_t start = clock(); v = 0; for (int i = 0; i < ITERS; i++) { v = i >= v; } printf("%s: %lu\n", __FUNCTION__, clock() - start); } int main() { testL(); testLE(); testG(); testGE(); } 

哪个,在我的机器上(用-O0编译)给了我这个(5个单独的运行):

 testL:337848
 testLE:338237
 testG:337888
 testGE:337787

 testL:337768
 testLE:338110
 testG:337406
 testGE:337926

 testL:338958
 testLE:338948
 testG:337705
 testGE:337829

 testL:339805
 testLE:339634
 testG:337413
 testGE:337900

 testL:340490
 testLE:339030
 testG:337298
 testGE:337593

我认为这些运算符之间的差异充其量是微不足道的,并且在现代计算世界中并没有太大的重要性。