2013-01-17 39 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。这给了我需要的答案。 –