我是在C中使用OpenMP的初学者。我正在尝试并行化四个嵌套循环。我读过,建议仅并行化外循环,但这会花费很长时间。

并行执行以下操作的最佳方法是什么

int nt=2500, nx=400; nz=200; nh=50;

#pragma omp parallel for
for(it=0; it<nt; it++)
for(ix=0; ix<nx; ix++)
for(iz=0; iz<nz; iz++)
for(ih=-nh; ih<=nh; ih++) {
  if (ix+ih<nx && ix+ih>=0 && ix-ih<nx && ix-ih>=0 ) {
    dR[it][ix+ih][iz] += ii[ih+nh][ix][iz]*us[it][ix-ih][iz];
    dS[it][ix-ih][iz] += ii[ih+nh][ix][iz]*ur[it][ix+ih][iz];
  }
}

最佳答案

就数据争用而言,以一种导致两个不同线程访问同一内存位置且至少一次访问为写操作的方式并行化循环是不安全的。

您永远不会读写同一变量,因此并行处理每个循环应该是安全的。 (虽然不一定更有效)



您的实际循环也可以重写。

您的if条件可以在逻辑上写为0 <= ix+ih < nx && 0 <= ix-ih < nx,换句话说,您只想在0nx之间编写。

如果我们可以证明ix+ihix-ih的范围大于0nx,我们可以取消检查并手动循环这些范围。

检查循环,我们看到0 < ix < nx-nh < ih < nh允许我们找到ix+ihix-ih的范围。

ix+ih的范围从-nhnx + nhix-ih的范围从-nhnx+nh。只要0,nx为正,这两个范围都大于nh,因此我们根本不需要进行检查。我们可以从0循环到nx

omp_set_nested(1);

#pragma omp parallel for
for(it=0; it<nt; it++) {

    #pragma omp parallel for
    for (iy = 0; iy < nx; iy++) {

        #pragma omp parallel for
        for(iz=0; iz<nz; iz++) {

            dR[it][iy][iz] += ii[ih+nh][ix][iz] * us[it][ix-ih][iz]  ;
            dS[it][iy][iz] += ii[ih+nh][ix][iz] * ur[it][ix+ih][iz]  ;
         }
      }
  }

关于c - 在C中使用OpenMP并行化的最佳方法是什么,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49968132/

10-12 22:32