使用 OpenMP 进行并行化

Parallelization with OpenMP

我有这个代码:

 for (i=1; i<=imax-1; i++) {
        for (j=1; j<=jmax; j++) {
            /* only if both adjacent cells are fluid cells */
            if ((flag[i][j] & C_F) && (flag[i+1][j] & C_F)) {
                du2dx = ((u[i][j]+u[i+1][j])*(u[i][j]+u[i+1][j])+
                    gamma*fabs(u[i][j]+u[i+1][j])*(u[i][j]-u[i+1][j])-
                    (u[i-1][j]+u[i][j])*(u[i-1][j]+u[i][j])-
                    gamma*fabs(u[i-1][j]+u[i][j])*(u[i-1][j]-u[i][j]))
                    /(4.0*delx);
                duvdy = ((v[i][j]+v[i+1][j])*(u[i][j]+u[i][j+1])+
                    gamma*fabs(v[i][j]+v[i+1][j])*(u[i][j]-u[i][j+1])-
                    (v[i][j-1]+v[i+1][j-1])*(u[i][j-1]+u[i][j])-
                    gamma*fabs(v[i][j-1]+v[i+1][j-1])*(u[i][j-1]-u[i][j]))
                    /(4.0*dely);
                laplu = (u[i+1][j]-2.0*u[i][j]+u[i-1][j])/delx/delx+
                    (u[i][j+1]-2.0*u[i][j]+u[i][j-1])/dely/dely;

                f[i][j] = u[i][j]+del_t*(laplu/Re-du2dx-duvdy);
            }
            else {
                f[i][j] = u[i][j];
            }
        }
    }

我想创建 4 个线程。一个用于计算 du2dx、duvdy、laplu 和 f[i][j]。有没有办法用 OpenMP 做到这一点?

您可以使用

#pragma omp parallel for private(i)

就在您最初的 for 之前,如本文所述tutorial

注意:还有其他非常酷的功能,您可能需要检查一下。

你是对的,@Andreas。默认情况下,在大多数实现中,omp parallel 将创建尽可能多的线程来利用机器中可用的并行性。 omp for 然后将整个循环迭代分配给线程(具体如何取决于所选的计划)。因此他们将不会从循环内部拆分单独的语句并将每个语句作为单独的并行任务执行。

但是,OTOH,“为什么要将自己限制为四个线程?” 这段代码不重要吗

  1. 没有其他人会使用它吗?
  2. 你会在得到更好的机器之前就把它扔掉吗?

请注意,您所说的要执行的操作(在单独的线程中执行每个语句)没有任何意义,因为语句之间存在依赖关系。最后声明

f[i][j] = u[i][j]+del_t*(laplu/Re-du2dx-duvdy);

取决于前面所有的。

因此,您最好的选择是使用简单的 OpenMP 并行化,尽管这样的方法可能效果最好

#pragma omp parallel for collapse(2), \
     schedule(nonmonotonic:dynamic),\
     shared(flag,u,gamma,Re,imax,jmax),\
     private(i,j,du2dx,duvdy,laplu)
for (i=1; i<=imax-1; i++) {
        for (j=1; j<=jmax; j++) {
            /* only if both adjacent cells are fluid cells */
            if ((flag[i][j] & C_F) && (flag[i+1][j] & C_F)) {
                du2dx = ((u[i][j]+u[i+1][j])*(u[i][j]+u[i+1][j])+
                    gamma*fabs(u[i][j]+u[i+1][j])*(u[i][j]-u[i+1][j])-
                    (u[i-1][j]+u[i][j])*(u[i-1][j]+u[i][j])-
                    gamma*fabs(u[i-1][j]+u[i][j])*(u[i-1][j]-u[i][j]))
                    /(4.0*delx);
                duvdy = ((v[i][j]+v[i+1][j])*(u[i][j]+u[i][j+1])+
                    gamma*fabs(v[i][j]+v[i+1][j])*(u[i][j]-u[i][j+1])-
                    (v[i][j-1]+v[i+1][j-1])*(u[i][j-1]+u[i][j])-
                    gamma*fabs(v[i][j-1]+v[i+1][j-1])*(u[i][j-1]-u[i][j]))
                    /(4.0*dely);
                laplu = (u[i+1][j]-2.0*u[i][j]+u[i-1][j])/delx/delx+
                    (u[i][j+1]-2.0*u[i][j]+u[i][j-1])/dely/dely;

                f[i][j] = u[i][j]+del_t*(laplu/Re-du2dx-duvdy);
            }
            else {
                f[i][j] = u[i][j];
            }
        }
    }