2013-03-21 4 views
14

Bardzo częstym wzorcem w programowaniu jest maksymalne ograniczenie wartości po jakiejś aktualizacji. Co chciałbym wiedzieć, jest, jeśli istnieje różnica pomiędzy następującymi dwoma kawałkami kodu, a jeśli trzeba być preferowane:W C++, czy lepiej jest ograniczyć wartość przy użyciu std :: min lub oddziału?

value += increment; 
value = std::min(value, valueMax); 

vs

value += increment; 

if (value > valueMax) 
    value = valueMax; 

Moje myślenie jest to, że przychodzi do tego, czy procesory mają instrukcje do pobierania dwóch wartości i tworzenia minimum. Jeśli tak, wywołanie std :: min powinno skutkować tą instrukcją i uniknąć niepotrzebnej gałęzi. Jeśli nie, druga wersja unika niepotrzebnego przypisania, gdy wartość < = valueMax.

Nie jestem zbyt dobry w tego typu sprawach, ale jestem pewien, że są to hakerzy ze starej szkoły, którzy o tym wiedzą. Zapytam ich: co jest lepsze?

+2

Spróbuj i spójrz na zestaw ... – Mysticial

+0

Powiedziałbym, że pierwsza wersja zawsze będzie wykonywać co najmniej * oraz drugą wersję, więc nie ma powodu, aby jej nie używać. Pierwsza wersja może * również * być szybsza, chociaż nie ma na to żadnych gwarancji. –

+0

Jak sugeruje Mysticial, zależy to od implementacji std :: min (http://en.cppreference.com/w/cpp/algorithm/min). – DavidA

Odpowiedz

10

Nowoczesne kompilatory są wystarczająco inteligentne, aby wygenerować ten sam kod w obu przypadkach. Na przykład 32-bitowy GCC generuje:

addl %esi, %edi 
cmpl %edx, %edi 
movl %edi, %eax 
cmovgl %edx, %eax 

64-bitowy szczęk:

%1 = add nsw i32 %increment, %value 
%2 = icmp sgt i32 %1, %valueMax 
%value = select i1 %2, i32 %valueMax, i32 %1 
+0

+1. Czy mógłbyś tutaj dodać adnotacje do zgromadzenia? Czy jest oddział? – voltrevo

+2

@ Mozza314 Nie ma tu oddziału. Kompilator działał tak dobrze, jak można to zrobić - jest to użycie warunkowego ruchu. – Mysticial

4

Na VC10 dopuszczonego do następnego kodu, że ma następujący zestaw:

int main(int argc, char *argv[]) 
{ 
    int dummyValue = 0, valueMax = 3000, value = valueMax + 1; 

    cin >> valueMax; 
    cin >> value; 

    dummyValue = std::min(value, valueMax); 

    cout << dummyValue; 
    cin >> valueMax; 
    cin >> value; 

    if (value > valueMax) 
    dummyValue = valueMax; 

    cout << dummyValue; 
    return 0; 
} 

Wygenerowano :

24: dummyValue = std::min(value, valueMax); 
00E112AF mov   eax,dword ptr [valueMax] 
00E112B2 cmp   eax,dword ptr [value] 
00E112B5 lea   edx,[value] 
00E112B8 lea   ecx,[valueMax] 
00E112BB cmovge  ecx,edx  // <-- this is our conditional assignment 
00E112BE mov   esi,dword ptr [ecx] 

i

if (value > valueMax) 
    dummyValue = valueMax 
00E112ED mov   eax,dword ptr [valueMax] 
00E112F0 cmp   dword ptr [value],eax 
00E112F3 mov   ecx,dword ptr ds:[0E13038h] 
00E112F9 cmovg  esi,eax 

Więc oba przypadki zoptymalizowany zarówno cmovge lub cmovg instrukcji.

Nadal będę z std::min, ponieważ pokazuje intencję lepiej niż oświadczenie if. Jest zoptymalizowany i jest bardziej czytelny.

+0

Gdy podajesz wartości stałe do zmiennych dla prostych algorytmów takich jak min (który jest narysowany przez większość czasu). Podczas kompilacji kompilator może ustalić minimalną wartość. Pętla nie zostanie wykonana, więc otrzymujesz '0'. Spróbuj wygenerować wartości przekazane do min w czasie wykonywania, a uzyskasz poprawny pomiar. –

+0

W każdym przypadku twój test jest łamany na kilka sposobów. 1) Rzeczywiście nie robi nic. Tak więc kompilator może zoptymalizować obie pętle. Można to naprawić za pomocą wyniku pętli. 2) Cała pierwsza pętla zostanie zoptymalizowana do 'dummyValue = 3001'. A cała druga pętla byłaby zoptymalizowana do 'value = 3001'. – Mysticial

0

Odpowiedź zależy od rodzaju wartości. Kod może być skutecznie zoptymalizowany, jeśli wszystkie operacje są w pełni przezroczyste dla optymalizatora kodu, co miałoby miejsce, gdyby wartość była zwykłą liczbą całkowitą. Ale twój kod również by się skompilował, jeśli wartość jest std :: string, a druga wersja może być potencjalnie szybsza, ponieważ przypisanie jest warunkowe.

Powiązane problemy