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

<更便宜(快)比<= ,同样, >更便宜(快)比>=

免责声明:我知道我可以测量,但这只会在我的机器上,我不确定答案可能是“具体实现”还是类似的。


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

现在,对于大多数架构而言,执行分支需要比不执行分支更长的时间,这是因为必须刷新并重新填充管道。 一些分支预测等可以帮助解决这个问题。

现在一些体系结构的指令大小可能会有所不同,比较gpr0和gpr1与比较gpr0和中间数字1234,可能需要更大的指令,例如x86中会看到很多。 所以虽然这两种情况可能是一个分支,如果少于你如何编码,取决于哪些寄存器碰巧保持什么值会导致性能差异(当然,x86会做很多流水线处理,大量缓存等来弥补这些问题)。 另一个类似的例子是mips和or32,其中r0总是零,它不是一个真正的通用寄存器,如果你写它,它不会改变,它是硬连线到零,所以比较,如果等于0可能会花费你如果需要额外的指令或两个指令来填充gpr以使比较可能发生,最坏的情况是必须将寄存器驱​​逐到堆栈或存储器,释放注册立即在那里,以便可以发生比较。

一些体系结构会像arm一样执行条件执行,因为您可以在每个指令的基础上执行全臂(而非拇指)指令,因此如果您有代码

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

arm的伪代码将会是

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

没有实际的分支,所以没有管线问题让你飞快地通过,非常快。

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

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

循环1的减法还会设置标志,如果循环中的内容足够简单,则可以使整个事情有条件,因此可以节省单独的比较和分支指令,并节省流水线代价。 Mips通过比较解决了这一点,并且分支是一条指令,并且它们在分支之后执行一条指令以在管道中保存一点。

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


TL; DR

四个操作员之间看起来几乎没有区别,因为他们都在大约相同的时间执行(在不同的系统上可能会有所不同)。 所以,如果有疑问,只需使用对情况最有意义的运算符(特别是在使用C ++时)。

所以,不要紧张,这是一个长久的解释:

假设整数比较:

就组件生成而言,结果取决于平台。 在我的电脑(Apple LLVM Compiler 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 <time.h>
#include <stdio.h>

#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: %lun", __FUNCTION__, clock() - start);
}

void testLE()
{
    clock_t start = clock();

    v = 0;

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

    printf("%s: %lun", __FUNCTION__, clock() - start);
}

void testG()
{
    clock_t start = clock();

    v = 0;

    for (int i = 0; i < ITERS; i++) {
        v = i > v;
    }

    printf("%s: %lun", __FUNCTION__, clock() - start);
}

void testGE()
{
    clock_t start = clock();

    v = 0;

    for (int i = 0; i < ITERS; i++) {
        v = i >= v;
    }

    printf("%s: %lun", __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

我会争辩说,这些运营商之间的差异充其量是微不足道的,并且在现代计算机世界中并不占重要地位。

链接地址: http://www.djcxy.com/p/31567.html

上一篇: Which operator is faster (> or >=), (< or <=)?

下一篇: Which is more performant: <= 0 or <1?