2013-07-08 21 views
7

短版本

在下面的行:處理器是否真的計算乘以零或一個?爲什麼?

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

如果aOn01,莫非處理器實際執行乘法,或者它有條件地計算出的結果(00,其他價值爲1)?

長版本

我尋找到算法性能一致性,這部分包括進去一看的Branch Prediction效果。

的假設是,這樣的代碼:

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

將提供比此碼(其中,分支預測可能破壞性能)更穩定的性能:

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

aOn是要麼01,並且可以在另一個線程的循環執行期間切換。

實際條件的計算(+ sin(i)在上面的例子中)涉及更多的處理和如果條件必須是在循環中(有大量的情況下,不只是一個象在上面的例子;另外,改變aOn應具有立即生效,而不是每循環)。

忽略性能一致性,這兩個選項之間的性能權衡是在執行if語句和乘法語句所花費的時間。無論如何,很容易發現,如果處理器不會像10這樣的值執行實際乘法運算,那麼第一個選項可能是雙贏的解決方案(無分支預測,性能更好)。

+0

這可能是因爲編譯器會優化這些了。 – iamnotmaynard

+0

我檢查了是否進行了優化,它對'0','1'和其他任何數字的乘法器之間的相對性能沒有任何影響(儘管對於所有情況,優化都略微提高了性能)。那麼究竟優化與處理器是否執行乘法有關? – Izhaki

+0

@iamnotmaynard編譯器不能優化它,除非aOn是一個常量,但OP沒有給出任何指示。 –

回答

6

處理器與0 s和1 s執行常規乘法運算。

原因是,如果處理器在每次計算之前檢查01,則條件的引入將花費更多的週期。儘管您可以獲得01乘法器的性能,但您將失去其他任何值的性能(這可能性更大)。

一個簡單的程序可以證明這一點:

#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; 
} 

對於其輸出是:

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

你使用了什麼樣的優化級別,編譯器是什麼,你是否用它打印了一個結果'iSum',更重要的是,可能使用一些比'rand()'少的密集函數,它本身就有一堆相當複雜的數學,並且可能隱藏結果(並且由於rand()有副作用,所以編譯器不得不調用'rand()',它會修改內部狀態),所以無論如何都不能優化它。 –

+0

偉大的觀點。不管優化級別如何(從none到'-Os'),相對性能都保持不變。編譯器是LLVM C++;沒有'rand()'print'iSum'來防止優化器完全跳過循環;嘗試不用'rand()'的變體,例如用「sin(i)」代替它,仍然對所有3個乘法器產生類似的結果。 – Izhaki

+0

我認爲在編譯器將0.0或1.0預先計算爲「不要乘法」的情況下是可行的,但同時,只有在編譯器可以將係數值看作常量的情況下才有可能。根據處理器的類型(以及運行期間值的可預測性 - 換句話說,它多久更換一次),對於簡單乘法,可能會或可能不會更好。 ...繼續... –

相關問題