2010-11-03 41 views
3

並行化兩個嵌套的for-loops,我遇到了我無法解釋的行爲。我已經在i7 860和Xeon E5540上嘗試了三種使用OpenMP的並行化,我期望代碼在兩個平臺上的行爲或多或少相同,這意味着其中一個平臺在所有三種不同情況下都應該更快我測試過了。但是,這不是這種情況:使用OpenMP在i7和Xeon上出現意外的結果

  • 對於情況1,至強是〜10%的速度,
  • 對於情況2中,I7是通過因子2和
  • 更快殼體3,至強再次快於因子1,5

你知道什麼可能導致這種情況嗎?

請註明您何時需要更多信息或澄清!

爲了進一步澄清,我的問題是更一般的。如果我在i7和xeon系統上運行相同的代碼,那麼不應該使用OpenMP來獲得可比較的結果嗎?

僞代碼:

for 1:4 
    for 1:1000 
     vector_multiplication 
    end 
end 

的情況下:

殼體1: 沒有pramga OMP沒有parallelzation

殼體2: 編譯OMP對於第一for循環

case 3:第二for循環

結果

這裏 編譯OMP是從time命令的實際數字:

殼體1

Time Xeon  i7 
real 11m14.120s 12m53.679s 
user 11m14.030s 12m46.220s 
sys  0m0.080s 0m0.176s 

殼體2

Time Xeon  i7 
real 8m57.144s 4m37.859s 
user 71m10.530s 29m07.797s 
sys  0m0.300s 0m00.128s 

殼體3

Time Xeon  i7 
real 2m00.234s 3m35.866s 
user 11m52.870s 22m10.799s 
sys  0m00.170s 0m00.136s 

[更新]

感謝所有的提示。我仍在研究可能的原因。

+0

這些單插座系統還是雙插座系統?你打開了超線程嗎?你能告訴我們更多關於'vector_multiplication'的信息嗎 - 這是一個標量向量積,一個點積,一個外積或者一列數字c [i] = a [i] * b [i]的乘法? – 2010-11-03 21:24:30

回答

0

可能影響openMP效率的事情是例如計算迭代邊界。確保這些是在手之前計算的,並且迭代變量儘可能在本地。如果你有C99做這樣的事情

#pragma omp parallel for 
for (size_t i = start, is = stop; i < is; ++i) ... 

,以確保表達式startstop在開始評估。 (或使用_Pragma,請參閱我的其他答案。)

然後,看看這是否真的成功的唯一方法是查看彙編代碼(通常選項-S)。

如果不查看其他編譯器選項。 gcc的選項爲-march=native,可以針對實際架構進行最佳編譯。其他平臺可能有類似的選項。首先搜索案例1的最佳體系結構選項。

+0

您好Jens,非常感謝您爲進一步改進OpenMP的使用所做的努力。但我的問題意味着更一般。如果我在i7和xeon系統上運行相同的代碼,不應該使用OpenMP導致可比較的(propotional)結果嗎? – Framester 2010-11-03 15:44:01

+0

@Framester,沒有「應該」。這些事情很大程度上取決於微觀優化,這些優化取決於您的特定編譯器如何能夠處理您的特定處理器和代碼。它們具有不同數量的寄存器,例如,因此循環體可以很好地適合寄存器,而不會溢出一個設置而不會溢出另一個設置。除了這些本地優化決策之外,您還需要打開MP,然後執行運行時決策,以決定如何將循環切換爲並行執行。 – 2010-11-03 16:12:59

0

這是比解答更多的評論。

這是不完全清楚你有什麼測量。爲了更大的確定性,我想:

  1. 插入時序語句在我的代碼點報告執行時間。這樣我就知道我正在測量什麼,比Linux時間命令給我的更確定。

  2. 使用2個不同的編譯器,以確保我測量OpenMP的某些內容,而不是其中一個實現的方面。

所有這一切,我傾向於同意,您的初步結果需要進一步調查。

的事情之一,我建議你嘗試正在崩潰,你的兩個循環,在這裏讓OpenMP的時間表4000環,而不是4個或1000

2

還有的是很好的答案,關於可能的變化與彙編的影響,等等,這是相當正確;但還有其他原因可能會導致差異。像這樣的相當簡單的(例如,低算術強度)計算往往對存儲器帶寬非常敏感;並且每個線程可用的內存帶寬量取決於您運行的線程數。兩個系統上的內存設置是否相同?

它看起來像i7 860有更高的時鐘速度,但E5540具有更高的總內存帶寬。由於情況2只能使用4個線程,而情況3可以使用更多,所以認爲在4線程情況下時鐘速度獲勝並非瘋狂,但在8線程情況下增加的存儲器爭用( 8個線程試圖拉入/拉出值)將手伸向更高帶寬的Xeon。

使這可能更復雜的是,它看起來像你正在運行8個線程 - 是這些雙插槽系統還是你正在使用超線程?這使情況變得更加複雜,因爲超線程實際上有助於在另一個線程等待內存時通過切換線程來隱藏一些內存爭用。 (b)* cos(b)乘以exp(sin(a)) )或其他)來確保問題是計算受限的,在您嘗試深入到底層時排除一個變量。通過優化特定機器(使用-march或-xHost或您有什麼)來編譯每個系統上的代碼可消除另一個變量。如果超線程處於打開狀態,關閉它(或僅將OMP_NUM_THREADS設置爲物理內核的數量)可以消除另一個變量。一旦你理解了這個簡化情況下發生的事情,放鬆一個接一個的限制應該可以幫助你更好地理解正在發生的事情。

+0

噢,還有一件事 - 它也可以用於在OMP_NUM_THREADS設置爲1的情況2和3下獲得OpenMP編號,以區分單個線程的影響和開銷的影響(可能由於已知優化)OpenMP。 – 2010-11-04 01:34:02