2014-01-09 51 views
-3

我的代碼如下:優化元件的總和在陣列

double a,b; //These variable are inputs to the function 
double *inArr; //This is also an iput to the function whose size is NumElements 
double *arr = new double[numElements]; //NumElements is ~ 10^6 
double sum = 0.0; 
for(unsigned int i=0;i<numElements;++i) 
{ 
    double k = a*inArr[i] + b; //This doesn't take any time 
    double el = arr[i]; //This doesn't take any time 
    el *= k; //This doesn't take any time 
    sum += el; //This takes a long time!!! 
} 

此代碼越過每個時間計算的值k,對於每個元件它增加了k次該元素來總結數組的元素。我將代碼分成了很多步驟,以便當我的分析器告訴我哪一行需要很長時間時,我將確切知道哪個計算是罪魁禍首。我的配置文件告訴我,將el加總是什麼會減慢我的程序速度(這看起來有點奇怪,簡單的加法會很慢,但我稱這個函數爲數百次,每次執行數百萬次計算)。我唯一的理論是,因爲總和在不同的範圍,使用它的操作需要更長的時間。所以我編輯的代碼是:

double a,b; //These variable are inputs to the function 
double *inArr; //This is also an iput to the function whose size is NumElements 
double *arr = new double[numElements]; //NumElements is ~ 10^6 
double sum = 0.0; 
for(unsigned int i=0;i<numElements;++i) 
{ 
    double k = a*inArr[i] + b; //This doesn't take any time 
    double el = arr[i]; //This doesn't take any time 
    el *= k; //This doesn't take any time 
    double temp = sum + el; //This doesn't take any time 
    sum = el; //This takes a long time!!! 
} 

現在sum操作花費很少的時間,即使它訪問sum變量。這項任務現在需要很長時間。我的理論是否正確,發生這種情況的原因是分配給不在當前範圍內的變量需要更長的時間?如果是這樣,爲什麼這是真的?有什麼辦法可以快速完成這項任務嗎?我知道我可以使用並行化來優化這個,我想知道我是否可以順序地做得更好。我使用VS 2012以發行模式運行,我使用VS性能分析器作爲分析器。

編輯:

一旦我刪除了原來的訪問inArr是什麼是最耗時的優化。

+3

你爲什麼不使用'std :: accumulate(std :: begin(arr),std :: end(arr),0.0,[](auto sum,auto elem){return sum + elem * someQuickCaclc();});'?這應該會給你高度優化的代碼。 – TemplateRex

+0

您是否嘗試禁用優化(/ O1,/ O2)標誌?這可以模仿一些分析。 –

+0

*您認爲每條迭代所需的時間*「很長時間」*多長時間?飛秒?小時?天? – Roddy

回答

2

是有限制的什麼分析器可以做。如果你已經編譯 與優化,編譯器可能已經重新安排一個公平 位的代碼,因此分析器不一定能分辨出哪行 號碼與任何一個特定的指令相關。而 編譯器和硬件都將允許一個很好的協議的 重疊;在很多情況下,硬件只是去到 下一條指令,即使前一個還沒有完成, 留在管道中的一些操作(和編譯器 將安排代碼,使硬件可以做這最有效地) )。因此,例如,子表達inArr[i] 涉及的存儲器訪問,這可能比什麼都顯著較慢 。但執行並不等待它;執行不會等到實際需要結果爲止。 (如果 編譯器是真聰明,它可以說此話arr[i] 訪問未初始化的內存,這是不確定的行爲,所以它 可以跳過訪問,給你任何舊的隨機值。)

在你的情況下,編譯大概只能做全 優化內環路,所以執行只是拖延 的流水線操作,當你寫 外循環的變量來完成。因此,剖析器始終將 歸入此編寫。

(我已經大大簡化:對於更多的細節,我必須知道 更多實際的處理器,並查看生成的代碼 有和沒有優化。)

+0

謝謝,這很明顯。所以你說這個簡單的代碼實際上不適合優化。這個速度和它的速度一樣快,而且在這一點上profiler是非常沒用的。 –

+0

也許吧。我不會說特定的機器不能做得更快,而且剖析器也沒有用。分析器不會指出你需要調整哪一行,但它仍然可以告訴你一個變化是否改善了函數的整體性能。至於在功能上做了哪些改變,你或多或少都要猜測和試驗。並且請注意,改善機器性能的改變可能會降低另一臺機器上的代碼速度。 (我沒有看到你可以做什麼來改善性能。) –

4

我的理論是正確的,這種情況發生的原因是分配給不在當前範圍內的變量需要更長的時間?

你探查是騙你的,並查明延遲的錯誤來源。沒有任何someQuickCalc的知識,此代碼不能進行有意義的優化。所有其他的操作都非常簡單。

+0

那麼延遲的真正來源在哪裏呢? –

+2

@BenjyKessler不可能從你發佈的代碼中說出來。 –

+0

好的,我會把someQuickCalc() –