我正坐在这里试图让孤儿工作,并通过减少#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编译器。
答案 0 :(得分: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);
应该效率较低,因为它在每次迭代时创建一个新的线程团队,而不仅仅是同步。