pragma omp for inside pragma omp master或single

And*_*hou 3 c++ openmp

我正坐在这里尝试使孤儿工作,并通过减少调用来减少开销#pragma omp parallel.我正在尝试的是:

#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
Run Code Online (Sandbox Code Playgroud)

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]);
} 
Run Code Online (Sandbox Code Playgroud)

我希望这可以通过某种方式实现,我只是不确定如何.所以我能得到的任何帮助都非常感谢(如果你告诉我这是不可能的话).顺便说一句,我正在使用open mp 3.0,gcc编译器和sun studio编译器.

Wal*_*ter 6

原始代码中的外部并行区域仅包含一个序列片段(#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);
Run Code Online (Sandbox Code Playgroud)

请注意,j如果任何线程仍在处理当前线程,则隐式同步可确保没有线程进入下一个线程j.

替代方案

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

应该效率较低,因为它在每次迭代时创建一个新的线程团队,而不仅仅是同步.