x > -1 vs x >=0, er der en præstationsforskel

x > -1 vs x >=0, er der en præstationsforskel

Det er meget afhængigt af den underliggende arkitektur, men enhver forskel vil være minimal.

Hvis noget, ville jeg forvente (x >= 0) at være lidt hurtigere sammenlignet med 0 kommer gratis på nogle instruktionssæt (såsom ARM).

Selvfølgelig vil enhver fornuftig compiler vælge den bedste implementering, uanset hvilken variant der er i din kilde.


Der er ingen forskel i den virkelige verden.

Lad os tage et kig på noget kode genereret af forskellige compilere til forskellige mål.

  • Jeg antager en underskrevet int-operation (hvilket synes hensigten med OP)
  • Jeg har ved undersøgelse begrænset til C og til kompilatorer, som jeg har lige ved hånden (ganske vist et ret lille udsnit - GCC, MSVC og IAR)
  • grundlæggende optimeringer aktiveret (-O2 for GCC, /Ox for MSVC, -Oh for IAR)
  • ved hjælp af følgende modul:

    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");
        }
    }
    

Og her er, hvad hver af dem producerede til sammenligningsoperationerne:

MSVC 11 målrettet mod ARM:

// if (x > -1) {...
00000        |cmp_gt| PROC
  00000 f1b0 3fff    cmp         r0,#0xFFFFFFFF
  00004 dd05         ble         |[email protected]_gt|


// if (x >= 0) {...
  00024      |cmp_gte| PROC
  00024 2800         cmp         r0,#0
  00026 db05         blt         |[email protected]_gte|

MSVC 11 målretning x64:

// 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 [email protected]_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 [email protected]_gte

MSVC 11 målretning x86:

// if (x > -1) {...
_cmp_gt PROC
  00000 83 7c 24 04 ff   cmp     DWORD PTR _x$[esp-4], -1
  00005 7e 0d        jle     SHORT [email protected]_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 [email protected]_gte

GCC 4.6.1 målretning 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

GCC 4.6.1 målretning x86:

// 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

GCC 4.4.1 målrettet mod ARM:

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

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

IAR 5.20 rettet mod en ARM Cortex-M3:

// 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

Hvis du stadig er med mig, her er forskellene på enhver note mellem at evaluere (x > -1) og (x >= 0) der dukker op:

  • MSVC-målretning ARM bruger cmp r0,#0xFFFFFFFF for (x > -1) vs cmp r0,#0 for (x >= 0) . Den første instruktions opkode er to bytes længere. Jeg formoder, at det kan give lidt ekstra tid, så vi kalder dette en fordel for (x >= 0)
  • MSVC-målretning x86 bruger cmp ecx, -1 for (x > -1) vs test ecx, ecx for (x >= 0) . Den første instruktions opkode er en byte længere. Jeg formoder, at det kan give lidt ekstra tid, så vi kalder dette en fordel for (x >= 0)

Bemærk, at GCC og IAR genererede identisk maskinkode til de to slags sammenligninger (med den mulige undtagelse af hvilket register der blev brugt). Så ifølge denne undersøgelse ser det ud til, at (x >= 0) har en aldrig så lille chance for at blive 'hurtigere'. Men uanset hvilken fordel den minimalt kortere opcode byte-kodning måtte have (og jeg understreger kan have ) vil helt sikkert blive overskygget af andre faktorer.

Jeg ville blive overrasket, hvis du fandt noget anderledes for det nervøse output fra Java eller C#. Jeg tvivler på, at du vil finde nogen bemærkelsesværdig forskel selv for et meget lille mål som en 8 bit AVR.

Kort sagt, du skal ikke bekymre dig om denne mikro-optimering. Jeg tror, ​​at mit indlæg heroppe allerede har brugt mere tid, end der vil blive brugt af nogen forskel i ydeevnen af ​​disse udtryk akkumuleret på tværs af alle de CPU'er, der udfører dem i mit liv. Hvis du har evnen til at måle forskellen i ydeevne, så brug din indsats på noget vigtigere som at studere subatomære partiklers opførsel eller noget.


Din lærer har læst nogle rigtig gamle bøger. Det plejede at være tilfældet med nogle arkitekturer, der mangler greater than or equal instruktion, der evaluerer > krævede færre maskincyklusser end >= , men disse platforme er sjældne i disse dage. Jeg foreslår at gå efter læsbarhed og bruge >= 0 .