2010-02-07 196 views
6

我對OpenMP相當陌生,我試圖啓動一個單獨的線程來處理2D數組中的每個項目。在OpenMP中爲每個內部循環啓動線程

所以基本上,這樣的:

for (i = 0; i < dimension; i++) { 
    for (int j = 0; j < dimension; j++) { 
     a[i][j] = b[i][j] + c[i][j]; 

我在做什麼是這樣的:

#pragma omp parallel for shared(a,b,c) private(i,j) reduction(+:diff) schedule(dynamic) 
    for (i = 0; i < dimension; i++) { 
     for (int j = 0; j < dimension; j++) { 
      a[i][j] = b[i][j] + c[i][j]; 

這是否實際上是啓動一個線程用於每個2D項目或沒有?我將如何測試?如果它是錯誤的,那麼正確的方法是什麼?謝謝!

注意:代碼已被大大簡化

+0

可能要與你所使用的語言來標記它,雖然您必須移除其中一個現有標籤。 – 2010-02-07 03:45:48

+0

好點mmyers - 參考它看起來像他正在使用c/c + +(openMP是c/c + +和fortran只) – 2010-02-07 03:59:25

回答

7

只有外部循環在您的代碼示例中是並行的。您可以在內部循環中打印omp_get_thread_num()進行測試,您會看到,對於給定的i,線程編號是相同的(當然,由於不同的運行會給出不同的結果,因此該測試是示範性的而不是確定性的)。例如,對於:

#include <stdio.h> 
#include <omp.h> 
#define dimension 4 

int main() { 
    #pragma omp parallel for 
    for (int i = 0; i < dimension; i++) 
     for (int j = 0; j < dimension; j++) 
      printf("i=%d, j=%d, thread = %d\n", i, j, omp_get_thread_num()); 
    } 

我得到:

i=1, j=0, thread = 1 
i=3, j=0, thread = 3 
i=2, j=0, thread = 2 
i=0, j=0, thread = 0 
i=1, j=1, thread = 1 
i=3, j=1, thread = 3 
i=2, j=1, thread = 2 
i=0, j=1, thread = 0 
i=1, j=2, thread = 1 
i=3, j=2, thread = 3 
i=2, j=2, thread = 2 
i=0, j=2, thread = 0 
i=1, j=3, thread = 1 
i=3, j=3, thread = 3 
i=2, j=3, thread = 2 
i=0, j=3, thread = 0 

至於你的代碼的其餘部分,你可能想要把更多的細節在一個新的問題(這是很難由小樣本告訴),但例如,當j僅在稍後聲明時,不能放private(j)。它在我上面的示例中是自動隱私的。我猜diff是我們在樣本中看不到的變量。此外,循環變量i是自動私人(從version 2.5 spec - 在3.0規範相同)

的循環迭代變量在 for循環的一個爲或平行於 構建體是在 構建私人。

編輯:上述所有內容對您和我所展示的代碼都是正確的,但您可能對以下內容感興趣。對於OpenMP版本3.0(例如gcc version 4.4,但不包含版本4.3),有collapse子句,您可以在其中編寫代碼,但要與 #pragma omp parallel for collapse (2)並行化兩個for循環(請參閱the spec)。

編輯:OK,我下載了GCC 4.5.0和運行上面的代碼,但使用collapse (2)得到下面的輸出,顯示出內環現在並行:

i=0, j=0, thread = 0 
i=0, j=2, thread = 1 
i=1, j=0, thread = 2 
i=2, j=0, thread = 4 
i=0, j=1, thread = 0 
i=1, j=2, thread = 3 
i=3, j=0, thread = 6 
i=2, j=2, thread = 5 
i=3, j=2, thread = 7 
i=0, j=3, thread = 1 
i=1, j=1, thread = 2 
i=2, j=1, thread = 4 
i=1, j=3, thread = 3 
i=3, j=1, thread = 6 
i=2, j=3, thread = 5 
i=3, j=3, thread = 7 

評論here(搜索「變通方法」)也適用於版本2.5中的變通方法,如果要並行化兩個循環,但上面引用的2.5版規範非常明確(請參閱章節A.35中的不合格示例)。

+0

謝謝,崩潰是我正在尋找的把戲! – achinda99 2010-02-08 13:28:51

0

你可以嘗試使用嵌套的omp parallel fors(在調用omp_set_nested(1)之後),但它們在所有openmp實現中都不被支持。

所以我想做出一些2D網格並啓動所有線程從單一的網格(例如用於固定的4x4線網格):

#pragma omp parallel for 
for(k = 0; k < 16; k++) 
{ 
    int i,j,i_min,j_min,i_max,j_max; 
    i_min=(k/4) * (dimension/4); 
    i_max=(k/4 + 1) * (dimension/4); 
    j_min=(k%4) * (dimension/4); 
    j_max=(k%4 + 1) * (dimension/4); 

    for(i=i_min;i<i_max;i++) 
     for(j=j_min;j<j_max;j++) 
     f(i,j); 

}