4

我在这里坐了一些东西,试图使孤儿工作,并通过减少对#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

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]);
} 

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

4

1 回答 1

7

原始代码中的外部并行区域仅包含一个串行片段 ( #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);

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

于 2013-01-17T18:01:08.100 回答