2017-05-26 125 views
0

我想知道是否有人知道更多關於大型嵌套循環崩潰原因的出價嗎? 含義我想比較雜注性能OpenMP崩潰vs大型嵌套循環不崩潰

omp parallel for private(i,j,k) collapse(3) schedule(static)

omp parallel for private(i,j,k) schedule(static)

嵌套的循環結構類似

for(int i=0; i<i_max; i++){ 
    for(int j=0; j<j_max; j++){ 
    for(int k=0; k<k_max; k++){ 
    A[i][j][k]=B[i][j][k]+C[i][j][k]; 
           } 
          } 
          } 

其中最大電流,j_max和k_max都是什麼比可用的線數多5至10倍。

如果我理解了正確的崩潰原因,openmp會將3個迴路摺疊成一個大小爲i_max*j_max*k_max的迴路,如果是(i_max*j_max*k_max) mod #threads = 0,我會假設最佳性能。

是不是沒有崩潰導致openmp只會把i循環並行?如果是的話,我的下一個假設是獲得i_max mod #threads = 0的最佳性能,我期望這兩個編譯指示都具有可比較的性能。

正如你所看到的,我在這裏非常猜測。有沒有人真的測試這兩種編譯指示的性能?

+0

你的猜測很好。你*測試了兩種情況下的表現嗎? – Zulan

+1

對於具有這種小體的循環,由於更好地實現了內部循環,當線程數量將「i_max」分開時,非摺疊版本可能會更快(多少?_it depends_)。摺疊環路可能會抑制其矢量化。 –

+0

@Zulan我做了一些測試,但不知道如何解釋我的結果。在一臺服務器上,崩潰版本更快,而在另一臺服務器上則是非崩潰版本。來這裏做一些澄清,因爲我沒有服務器容量來擴展性地測試它,而不禁止一些模擬。 – LeBo

回答

2

當您摺疊循環時,OpenMP會將它們變成一個大循環。該循環的迭代空間然後被分成塊,並根據有效的循環調度在線程之間進行拆分。根據線程數量的個別循環迭代的可分性,您可能會在塊包含不完整的內部循環的情況下結束。一個示例情況是i_maxj_maxk_max中的任何一個都可以被線程數整除,但i_max * j_max * k_max是。而且,不同的塊可能包含不完整循環的不同部分。然後這一切都取決於運行時可配置的線程數量。因此編譯器無法可靠地對循環的矢量化進行建模並評估其是否有益,因此矢量化器可能會受到抑制。當循環迭代次數不能被向量長度整除或數據未對齊時,它還必須創建串行循環來處理這種情況。

當只有外部循環並行時,編譯器可以自由地轉換內部循環,因爲它認爲合適,例如,它可以安全地引導這些循環。這是否會比以前的情況更快尚不清楚。 Vectorisation提高了計算性能,但同時也給內存子系統帶來更多壓力。這些比例決定是否會有好處。

在另一方面,假設ABC都是i_max X j_max X k_max(和x <= x_max是一個錯字,應該實際上是x < x_max),一個真正聰明的編譯器會發現,你在所有迭代可能指數和基本上求和兩個1 d矢量,並打開摺疊環成類似

#pragma omp parallel schedule(static) 
for (z = 0; z < i_max * j_max * k_max; z++) 
    A_lin[z] = B_lin[z] + C_lin[z]; 

其中X_lin[]是後面X[][][]數據的線性化1-d圖。這裏的矢量化有很大的潛力,所以它確實取決於編譯器能夠執行多少分析。

沒有銀彈解決方案,沒有一種算法在許多類型的硬件中執行同樣好的功能。這就是OpenMP提供大量可通過環境變量設置的可調參數的原因。還要注意,比較服務器CPU和臺式機CPU的性能時,應該記住,服務器CPU通常具有更大的最後一級緩存和更多的內存通道以及更高的主內存帶寬,因此矢量化代碼在大量數據的。

+0

是的<='是錯別字! 謝謝您的詳盡答案! – LeBo