2011-02-04 104 views
0

我在VS2008下面的代碼:OpenMP的for循環忽略num_threads子句

int i,j; 
bool pr = false; 
#pragma omp parallel for private(pr) num_threads(2) 
for(i=0;i<PIC_X;i++) 
{ 
    int rank = omp_get_thread_num(); 
    int count = omp_get_num_threads(); 
    if (!pr) 
    { 
     printf_s("Hello from thread %d of %d\n", rank, count); 
     pr = true; 
    } 
    for(j=0;j<PIC_Y;j++) 
    { 
     // do stuff 
    } 
} 

(不試圖使一個嵌套的OpenMP循環中,如果你想知道)。問題是,num_threads子句沒有任何效果:我只輸出了「來自線程0的Hello」。我也嘗試使用omp_set_num_threads(2),無濟於事。是什麼賦予了?

+1

退房http://software.intel.com/en-us/articles/32-openmp-traps-for-c-developers/ - 它真的幫助我 – 2011-02-04 17:29:55

回答

4

您已將pr設置在並行區域之外,然後通過將其置於私有子句中使其成爲私有。這意味着每個線程都有一個pr,但私有pr變量不會被初始化。對pr使用firstprivate而不是private,以便私有變量被初始化。

但是,您對循環計數器默認情況下是不正確的。工作共享(或規範)(即變量i)的循環計數器是私有的(OMP V2.0規範的構造部分2.4.1節)。但是「j」不是。見的OpenMP V2.0規範(這是微軟在VS2008支持),第2.7.2數據共享屬性子句:

如果遇到一個平行或工作共享結構,當一個變量是可見的, 該變量未在共享屬性子句或threadprivate 指令中指定,則該變量是共享的。在並行區域的動態 範圍內聲明的靜態變量是共享的。堆分配內存(例如,使用C或C++中的 malloc()或C++中的新操作符)。 (但是,指向此 內存的指針可以是私有的,也可以是共享的。)具有在並行區域的動態範圍內聲明的自動存儲器的持續時間的變量是私有的。

至於omp_get_num_threads()返回1,我能想到的是,你沒有編譯這個啓用OpenMP標誌。

1

如果OpenMP將外循環拆分爲2(即一個進程獲得0..PIC_X/2),而另一個獲得後半部分,則只有一個進程會看到i == 0。

如果你的圖像像我看到的所有圖像一樣組織起來,那麼外層循環應該是Y,內層循環應該是X,內層循環應該是OpenMP的,因爲這就是圖像通常在內存中組織的方式。

+0

+1,即使OP編輯帖子以刪除`if(i == 0)`code xcramps was original correct。 – 2011-02-04 16:45:47