1 vs x> = 0,是否有性能差异

我听说有一位老师放弃了这一次,从那以后一直困扰着我。 假设我们想检查整数x是否大于或等于0.有两种方法可以检查:

if (x > -1){
    //do stuff
}

if (x >= 0){
    //do stuff
} 

根据这位老师, >会稍快,那么>= 。 在这种情况下,它是Java,但根据他的说法,这也适用于C,C ++和其他语言。 这个陈述有没有道理?


在任何现实世界中都没有区别。

让我们来看看各种编译器为不同目标生成的代码。

  • 我假设一个signed int操作(这看起来是OP的意图)
  • 我对C和编译器的调查受到了限制,我很快就会收到(确实是一个非常小的样本 - GCC,MSVC和IAR)
  • 启用基本优化( -O2用于GCC, /Ox用于MSVC, -Oh用于IAR)
  • 使用以下模块:

    void my_puts(char const* s);
    
    void cmp_gt(int x) 
    {
        if (x > -1) {
            my_puts("non-negative");
        }
        else {
            my_puts("negative");
        }
    }
    
    void cmp_gte(int x) 
    {
        if (x >= 0) {
            my_puts("non-negative");
        }
        else {
            my_puts("negative");
        }
    }
    
  • 以下是他们为比较操作生成的每一项内容:

    针对ARM的MSVC 11:

    // if (x > -1) {...
    00000        |cmp_gt| PROC
      00000 f1b0 3fff    cmp         r0,#0xFFFFFFFF
      00004 dd05         ble         |$LN2@cmp_gt|
    
    
    // if (x >= 0) {...
      00024      |cmp_gte| PROC
      00024 2800         cmp         r0,#0
      00026 db05         blt         |$LN2@cmp_gte|
    

    针对x64的MSVC 11:

    // if (x > -1) {...
    cmp_gt  PROC
      00000 83 f9 ff     cmp     ecx, -1
      00003 48 8d 0d 00 00                  // speculative load of argument to my_puts()
        00 00        lea     rcx, OFFSET FLAT:$SG1359
      0000a 7f 07        jg  SHORT $LN5@cmp_gt
    
    // if (x >= 0) {...
    cmp_gte PROC
      00000 85 c9        test    ecx, ecx
      00002 48 8d 0d 00 00                  // speculative load of argument to my_puts()
        00 00        lea     rcx, OFFSET FLAT:$SG1367
      00009 79 07        jns     SHORT $LN5@cmp_gte
    

    针对x86的MSVC 11:

    // if (x > -1) {...
    _cmp_gt PROC
      00000 83 7c 24 04 ff   cmp     DWORD PTR _x$[esp-4], -1
      00005 7e 0d        jle     SHORT $LN2@cmp_gt
    
    
    // if (x >= 0) {...
    _cmp_gte PROC
      00000 83 7c 24 04 00   cmp     DWORD PTR _x$[esp-4], 0
      00005 7c 0d        jl  SHORT $LN2@cmp_gte
    

    GCC 4.6.1定位到x64

    // if (x > -1) {...
    cmp_gt:
        .seh_endprologue
        test    ecx, ecx
        js  .L2
    
    // if (x >= 0) {...
    cmp_gte:
        .seh_endprologue
        test    ecx, ecx
        js  .L5
    

    针对x86的GCC 4.6.1:

    // if (x > -1) {...
    _cmp_gt:
        mov eax, DWORD PTR [esp+4]
        test    eax, eax
        js  L2
    
    // if (x >= 0) {...
    _cmp_gte:
        mov edx, DWORD PTR [esp+4]
        test    edx, edx
        js  L5
    

    针对ARM的GCC 4.4.1:

    // if (x > -1) {...
    cmp_gt:
        .fnstart
    .LFB0:
        cmp r0, #0
        blt .L8
    
    // if (x >= 0) {...
    cmp_gte:
        .fnstart
    .LFB1:
        cmp r0, #0
        blt .L2
    

    针对ARM Cortex-M3的IAR 5.20:

    // if (x > -1) {...
    cmp_gt:
    80B5 PUSH     {R7,LR}
    .... LDR.N    R1,??DataTable1  ;; `?<Constant "non-negative">`
    0028 CMP      R0,#+0
    01D4 BMI.N    ??cmp_gt_0
    
    // if (x >= 0) {...
    cmp_gte:
     80B5 PUSH     {R7,LR}
     .... LDR.N    R1,??DataTable1  ;; `?<Constant "non-negative">`
     0028 CMP      R0,#+0
     01D4 BMI.N    ??cmp_gte_0
    

    如果你仍然和我在一起,下面是在评估(x > -1)(x >= 0)之间出现的任何音符的差异:

  • 针对(x > -1) MSVC目标ARM使用cmp r0,#0xFFFFFFFF ,对于(x >= 0) cmp r0,#0 。 第一条指令的操作码长两个字节。 我想这可能会带来一些额外的时间,所以我们称这为(x >= 0)
  • 针对x86的MSVC使用cmp ecx, -1对于(x > -1)test ecx, ecx (x > -1) test ecx, ecx对于(x >= 0) test ecx, ecx 。 第一条指令的操作码长一个字节。 我想这可能会带来一些额外的时间,所以我们称这为(x >= 0)
  • 请注意,GCC和IAR为两种比较生成了相同的机器码(可能的例外是使用哪个寄存器)。 所以根据这项调查,似乎(x >= 0)有一个“更快”的机会。 但是无论什么优势,最小的操作码字节编码可能会有(并且我强调可能会有)会被其他因素完全掩盖。

    如果您发现Java或C#的jitted输出有任何不同,我会感到惊讶。 我怀疑你会发现任何不同的音符,即使是像8位AVR这样的非常小的目标。

    总之,不要担心这种微观优化。 我认为我在这里写的已经花费了更多的时间,而不会花费在这些表达式的性能差异上,而这些表达式在我一生中执行它们的所有CPU上积累的性能有所差异。 如果您有能力测量性能差异,请将您的努力应用到更重要的事情上,如研究亚原子粒子的行为或其他内容。


    它非常依赖于底层架构,但任何区别都很小。

    如果有的话,我期望(x >= 0)稍快一些,因为与某些指令集(如ARM)上的0进行比较是免费的。

    当然,任何明智的编译器都会选择最佳的实现方式,而不管源代码中包含哪个变体。


    你的老师一直在阅读一些真正的旧书。 过去,一些体系结构缺乏greater than or equal指令的评估>所需的机器周期少于>= ,但这些平台目前很少见。 我建议去可读性,并使用>= 0

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

    上一篇: 1 vs x >= 0, is there a performance difference

    下一篇: What is faster (x < 0) or (x ==