2013-01-17 56 views
3

我在這裏坐着一些嘗試使孤兒工作的東西,並通過減少#pragma omp parallel的調用來減少開銷。 我想要是一樣的東西:pragma omp for inside pragma omp master or single

#pragma omp parallel default(none) shared(mat,mat2,f,max_iter,tol,N,conv) private(diff,k) 
{ 
#pragma omp master // I'm not against using #pragma omp single or whatever will work 
{ 
while(diff>tol) { 
    do_work(mat,mat2,f,N); 
    swap(mat,mat2); 
    if(!(k%100)) // Only test stop criteria every 100 iteration 
     diff = conv[k] = do_more_work(mat,mat2); 
    k++; 
} // end while 
} // end master 
} // end parallel 

do_work取決於先前迭代這樣的while循環是有運行順序。 但是我想能夠運行'do_work'平行的,所以它看起來是這樣的:

void do_work(double *mat, double *mat2, double *f, int N) 
{ 
int i,j; 
double scale = 1/4.0; 
#pragma omp for schedule(runtime) // Just so I can test different settings without having to recompile 
for(i=0;i<N;i++) 
    for(j=0;j<N;j++) 
     mat[i*N+j] = scale*(mat2[(i+1)*N+j]+mat2[(i-1)*N+j] + ... + f[i*N+j]); 
} 

我希望這可以實現一些方法,我只是不知道如何。所以我能得到的任何幫助都非常感謝(如果你告訴我這是不可能的)。順便說一句我正在打開mp 3.0,gcc編譯器和sun studio編譯器。

回答

5

原始代碼中的外部平行區域只包含一個連續片段(#pragma omp master),這在沒有意義的情況下會導致純串行執行(無並行)。由於do_work()取決於以前的迭代,但您想要並行運行它,您必須使用同步。 openmp工具是一個(顯式或隱式)同步屏障。

例如(代碼類似於你):

#pragma omp parallel 
for(int j=0; diff>tol; ++j) // must be the same condition for each thread! 
#pragma omp for    // note: implicit synchronisation after for loop 
    for(int i=0; i<N; ++i) 
    work(j,i); 

注意,隱式同步確保沒有線程進入下一j如果任何線程仍然在當前j工作。

替代

for(int j=0; diff>tol; ++j) 
#pragma omp parallel for 
    for(int i=0; i<N; ++i) 
    work(j,i); 

應不太有效的,因爲它在每次迭代創建線程的一個新的團隊,而不是僅僅同步。

+0

與我在代碼中'k ++'之後放置屏障有很大區別嗎? 另外,您的示例中的障礙是否必要? '#pragma omp for'之後沒有隱含的屏障嗎? –

+0

@AndersSchou 1)**是的,它有很大的不同**:在你的代碼中,根本沒有並行性,因爲並行區域只包含一個「主」區域,它只能由主線程執行(嵌套並行通常被忽略)。 2)是的,**有一個隱含的障礙**。所以,額外的障礙是多餘的,編譯器應該優化它。無論如何,留下至少一條關於隱含屏障的評論是有幫助的(參見編輯)。 – Walter

+0

謝謝:D。這給了我需要的答案。 –