2013-07-08 11 views
7

Wersja krótka

W kolejnym wierszu:Czy procesorzy faktycznie obliczają mnożenie przez zero lub jeden? Czemu?

aData[i] = aData[i] + (aOn * sin(i)); 

Jeśli aOn jest 0 lub 1, czy procesor wykonują mnożenie, czy też warunkowo wypracowania wyniku (0 dla 0, inne -wartość dla 1)?

The Long Version

szukam do algorytmu konsystencji wydajności, co częściowo wiąże się zajrzeć do skutku Branch Prediction.

Przypuszcza się, że ten kod:

for (i = 0; i < iNumSamples; i++) 
    aData[i] = aData[i] + (aOn * sin(i)); 

zapewnia bardziej stabilne wyniki niż kod (gdzie przewidywania rozgałęzień mogą destabilizować wydajności)

for (i = 0; i < iNumSamples; i++) 
{ 
    if (aOn) 
     aData[i] = aData[i] + sin(i); 
} 

z aOn jest albo 0 lub 1, i może przełączać podczas wykonywania pętli przez inny wątek.

W kalkulacji warunkowy (+ sin(i) w powyższym przykładzie) obejmuje więcej przetwarzania i jeśli warunek musi znajdować się w pętli (istnieje mnogość warunkach, nie tylko jednego, jak w przykładzie powyżej, również zmiany aOn powinny efekt natychmiast, a nie na pętlę).

Zignorowanie spójności wydajności, kompromis pomiędzy dwiema opcjami jest w czasie niezbędnym do wykonania instrukcji if i mnożenia.

Bez problemu można zauważyć, że jeśli procesor nie wykonałby faktycznego mnożenia dla wartości takich jak 1 i 0, pierwsza opcja mogłaby być rozwiązaniem wygrywa-wygrana (bez przewidywania rozgałęzień, lepsza wydajność).

+0

Jest wielce prawdopodobne, że kompilator by zoptymalizować te na zewnątrz. – iamnotmaynard

+0

Mam sprawdzanie zi bez optymalizacji i nie ma wpływu na względną wydajność między mnożnikami "0", "1" i dowolnymi innymi liczbami (optymalizacja nieznacznie poprawia wydajność dla wszystkich przypadków). Jak dokładnie optymalizacja odnosi się do tego, czy procesor dokonuje multiplikacji? – Izhaki

+0

@iamnotmaynard Kompilator nie może go zoptymalizować, chyba że aOn jest stałą, ale OP nie daje żadnego wskazania, że ​​tak jest. –

Odpowiedz

6

Procesory wykonują regularne mnożenie z 0 s oraz 1 s.

Powód jest taki, że jeśli procesor sprawdzi przed 0 i 1 przed każdym obliczeniem, wprowadzenie warunku zajmie więcej cykli. Podczas gdy uzyskasz wydajność dla mnożników 0 i 1, stracisz wydajność dla dowolnych innych wartości (które są o wiele bardziej prawdopodobne).

Prosty program może okazać się w ten sposób:

#include <iostream> 
#include "cycle.h" 
#include "time.h" 

void Loop(float aCoefficient) 
{ 
    float iSum = 0.0f; 

    clock_t iStart, iEnd; 

    iStart = clock(); 
    for (int i = 0; i < 100000000; i++) 
    { 
     iSum += aCoefficient * rand(); 
    } 
    iEnd = clock(); 
    printf("Coefficient: %f: %li clock ticks\n", aCoefficient, iEnd - iStart); 
} 

int main(int argc, const char * argv[]) 
{ 
    Loop(0.0f); 
    Loop(1.0f); 
    Loop(0.25f); 

    return 0; 
} 

dla którego wyjście jest:

Coefficient: 0.000000: 1380620 clock ticks 
Coefficient: 1.000000: 1375345 clock ticks 
Coefficient: 0.250000: 1374483 clock ticks 
+0

Jaki poziom optymalizacji użyłeś, jaki kompilator, i czy wypróbowałeś go z wydrukiem wynikowego 'iSum' - co ważniejsze, być może używając czegoś trochę mniej intensywnego niż' rand() ', które samo w sobie robi garść dość skomplikowana matematyka i mogłaby ukrywać wynik (a ponieważ kompilator ma nazywać 'rand()', ponieważ 'rand()' ma efekty uboczne - modyfikuje stan wewnętrzny), nie może tego zoptymalizować, bez względu na wszystko. –

+0

Świetne punkty. Względna wydajność pozostaje taka sama niezależnie od poziomu optymalizacji (od braku do '-Os'); Kompilatorem jest LLVM C++; bez 'rand()' drukowania 'iSum' jest potrzebne, aby zapobiec optymalizacji pomijania pętli; próbowanie wariacji bez 'rand()', na przykład zastąpienie go 'sin (i)' nadal daje podobne wyniki dla wszystkich 3 mnożników. – Izhaki

+0

Myślę, że jest to możliwe, aby uzyskać scenariusz, w którym kompilator wstępnie oblicza 0.0 lub 1.0 na "nie pomnażaj", ale jednocześnie jest to możliwe tylko wtedy, gdy kompilator może zobaczyć wartość współczynnika jako stałą. I w zależności od rodzaju procesora [i przewidywalności wartości podczas biegu - innymi słowy, jak często się zmienia], może być lub nie być lepiej mieć 'if' vs. zwykłe mnożenie. ... ciąg dalszy ... –

Powiązane problemy