2017-01-09 136 views
0

背景:OpenMP的V4 +英特爾的編譯器ICC]並行「任務的內線已經並行for循環OpenMP中

我想並行化已經是一個並行循環內的任務。我看見科目接近這一個,例如:

但是在嘗試它時,除了編譯時錯誤消息,我無法得到明確的答案。

代碼:

#pragma omp parallel for private(a,bd) reduction(+:sum) 
    for (int i=0; i<128; i++) { 
     a = i%2; 
     for (int j=a; j<128; j=j+2) { 
      u_n = 0.25 * (u[ i*128 + (j-3) ]+ 
          u[ i*128 + (j+3) ]+ 
          u[ (i-1)*128 + j ]+ 
          u[ (i+1)*128 + j ]); 
      // #pragma omp single nowait 
      // { 
      // #pragma omp task shared(sum1) firstprivate(i,j) 
      // sum1 = (u[i*128+(j-3)]+u[i*128+(j-2)] + u[i*128+(j-1)])/3; 
      // #pragma omp task shared(sum2) firstprivate(i,j) 
      // sum2 = (u[i*128+(j+3)]+u[i*128+(j+2)]+u[i*128+(j+1)])/3; 
      // #pragma omp task shared(sum3) firstprivate(i,j) 
      // sum3 = (u[(i-1)*128+j]+u[(i-2)*128+j]+u[(i-3)*128+j])/3; 
      // #pragma omp task shared(sum4) firstprivate(i,j) 
      // sum4 = (u[(i+1)*128+j]+u[(i+2)*128+j]+u[(i+3)*128+j])/3; 
      // } 
      // #pragma omp taskwait 
      // { 
      // u_n = 0.25*(sum1+sum2+sum3+sum4); 
      // } 
      bd = u_n - u[i*128+ j]; 
      sum += diff * diff; 
      u[i*128+j]=u_n; 
     }  
    } 

在上面的代碼中,我試圖替換u_n = 0.25 *(...);符合15註釋行,不僅嘗試通過2個for循環來paralllelize迭代,而且還acheive一定程度在涉及數組u[]的4次計算(sum1sum4)中的每一次計算上都是並行性的。

編譯錯誤是相當明確的:

error: the OpenMP "single" pragma must not be enclosed by the "parallel for" pragma

有沒有解決的辦法,所以我可以進一步優化該計算使用OpenMP?

回答

1

標準禁止在循環工作共享結構中的單個工作共享構造,但您不需要它。

通常parallel - >single - >task設置的任務是要確保你有一個線程組設置爲您的任務(parallel),但後來只產卵每個任務一次(single)。你不需要parallel for上下文中的後者,因爲每次迭代只能執行一次。所以你可以直接在循環中產生任務。這似乎在gnu和Intel編譯器上都有預期的行爲,即已完成自己的循環迭代的線程確實幫助其他線程執行其任務。

但是,在你的情況下這是一個壞主意。與產卵任務的開銷相比,像sum1之類的微小計算本身會更快。

刪除除parallel for以外的所有編譯指示,這是非常合理的並行化。 之前進一步優化計算,你應該措施!尤其是,您對所有可用線程是否總是在計算某些內容感興趣,或者某些線程是否提前完成並等待其他線程(負載不均衡)。要衡量,您應該爲您的平臺尋找並行性能分析工具。如果是這樣的話,你可以用調度策略來解決它,或者可能通過內部循環中的嵌套並行。

關於代碼性能的完整討論比較複雜,需要一個minimal, complete and verifiable example,詳細的系統描述和實際測量的性能數字。

+0

謝謝佐蘭。Yr解釋肯定會擊敗編譯時錯誤信息。根據你的指針,我將在我的集羣上查看測量儀器。乾杯, – Cbhihe