2017-01-09 71 views
6

Jeśli masz wartość boolean b i int i, który z dwóch przykładów jest lepszy?Najszybszy sposób określania wartości na podstawie wartości boolowskiej C++

int x = i-1; 
if(!b)x--; 

lub

int x; 
if(b)x = i-1;else x = i-2; 

W obu przykładach jeśli b prawda x jest i-1, inny x jest i-2. Czy należy zadeklarować x jako i-1 i zmniejszyć, jeśli b ma wartość false lub użyć drugiego przykładu?

+9

Wersja bez branchless to 'x = i - 2 + b;' –

+4

Istnieje duża szansa, że ​​jeśli skompilujesz w wydaniu, kompilator wypisze ten sam kod w dowolny sposób – user

+1

Dlaczego pytasz? Mikro optymalizacje są nieważne. –

Odpowiedz

10

Byłbym zaskoczony, gdyby kompilatory nie zoptymalizowały obu wersji do tego samego optymalnego zespołu. Nie marnuj czasu dzięki tym mikrooptymalizacjom, chyba że udowodnisz, że są istotne przy użyciu profilera.

Aby odpowiedzieć na pytanie: nie ma to znaczenia. Oto porównanie "generowanego zestawu" na stronie gcc.godbolt.org z -Ofast.


volatile int state0; 
volatile void f0(volatile int i, volatile bool b) 
{ 
    int x; 
    if(b)x = i-1;else x = i-2; 
    state0 = x; 
} 

... pobiera skompilowany do ...

f0(int, bool):        # @f0(int, bool) 
     mov  dword ptr [rsp - 4], edi 
     mov  byte ptr [rsp - 5], sil 
     movzx eax, byte ptr [rsp - 5] 
     or  eax, -2 
     add  eax, dword ptr [rsp - 4] 
     mov  dword ptr [rip + state0], eax 
     ret 

volatile int state1; 
volatile void f1(volatile int i, volatile bool b) 
{ 
    int x = i-1; 
    if(!b)x--; 
    state1 = x; 
} 

... pobiera skompilowany do ...

f1(int, bool):        # @f1(int, bool) 
     mov  dword ptr [rsp - 4], edi 
     mov  byte ptr [rsp - 5], sil 
     mov  eax, dword ptr [rsp - 4] 
     movzx ecx, byte ptr [rsp - 5] 
     or  ecx, -2 
     add  ecx, eax 
     mov  dword ptr [rip + state1], ecx 
     ret 

Jak widać, różnica jest minimalna i bardzo prawdopodobne, że zniknie, gdy kompilator może zoptymalizować bardziej agresywnie, usuwając volatile.


Oto podobne porównanie w formie graficznej, korzystając -Ofast -march=native -ffast-math:

Godbolt comparison

+0

Proszę wspomnieć, które flagi użyłeś (-O3?) –

+0

@IvanRubinson: to jest na łączu godbolt, użyłem '-Ofast'. –

+0

Dzięki!Pytałem tylko dlatego, że byłem ciekawy. – theo2003

5

Sprawdź kod montażowej, ponieważ optymalizator optymalizacji, ewentualnie obie swoje rozwiązania do tego samego rozwiązania.

I pewnie wdrożyć go jako:

int x = (b) ? i - 1 : i - 2; 

dla czytelności i wysokie prawdopodobieństwo, optymalizator będzie to równe jako drugiego rozwiązania.

+3

Chciałbym napisać 'int x = i - b? 1: 2; 'nie wspominając' i' dwa razy – Slava

+1

Napisałbym 'const int x = i - 2 + !! b', aby nie mieć żadnego rozgałęzienia. –

+0

Czy 'int x = i - 2 + b' działa? – theo2003