2013-10-05 126 views
0

我試圖並行化代碼。我的代碼看起來像這樣 -在OpenMP中使用#pragma parallel並行共享的嵌套循環

#pragma omp parallel private(i,j,k) 
    #pragma omp parallel for shared(A) 
    for(k=0;k<100;<k++) 
    for(i=1;i<1024;<i++) 
     for(j=0;j<1024;<j++) 
     A[i][j+1]=<< some expression involving elements of A[i-1][j-1] >> 

在執行此代碼時,我從循環的串行執行中獲得了不同的結果。 我無法理解我做錯了什麼。

我也試過崩潰()

#pragma omp parallel private(i,j,k) 
    #pragma omp parallel for collapse(3) shared(A) 
    for(k=0;k<100;<k++) 
    for(i=1;i<1024;<i++) 
     for(j=0;j<1024;<j++) 
     A[i][j+1]=<< some expression involving elements of A[][] >> 

另一件事我想是有每個循環,而不是崩潰前()OMP並行的#pragma。

這個問題,我認爲是數據依賴。任何想法如何在數據依賴的情況下並行化?

回答

0

如果這實際上是您的用例,那麼只需對外部循環進行並行化即可,這應該足以滿足您在常見體系結構上的適度並行性。

如果你想要更多,你必須重新編寫你的循環,以便你有一個不具有依賴性的內部部分。在你的例子中,這是相對容易的,你必須通過「對角線」(外部循環,順序)進行處理,然後在對角線內獨立處理。

for (size_t d=0; d<nDiag(100); ++d) { 
    size_t nPoints = somefunction(d); 
#pragma omp parallel 
    for (size_t p=0; p<nPoints; ++p) { 
     size_t x = coX(p, d); 
     size_t y = coY(p, d); 
     ... your real code ... 
    } 

} 

這部分可以自動完成,但我不認爲這樣的工具已經很容易在每一天的OMP中實現。這是一個積極的研究。

還要注意以下

  • int是很少的指標是一個好主意,特別是如果你訪問矩陣。如果你必須自己計算一個條目的絕對位置(並且你在這裏看到的可能是這個),這很容易溢出。 int通常是32位寬,在這32箇中,你甚至會爲這個符號浪費一個。在C中,對象大小是用size_t來計算的,大部分時間是64位寬,並且在任何情況下都是由平臺設計人員選擇的正確類型。
  • 使用局部變量作爲循環索引和其他臨時對象,如你所見,編寫OMP編譯指令變得容易得多。局部性是並行性的關鍵之一。通過正確表達這一點,幫助自己和編譯器。
0

你只是並行化外部'k'for循環。每個並行線程都執行'i'和'j'循環,並且它們都寫入相同的'A'結果。由於他們都在讀取和寫入A中的相同位置,因此最終的結果將是非確定性的。

從你的問題來看,並不清楚任何並行性是可能的,因爲每一步似乎都取決於前面的每一步。