c - 使用 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 做到这一点?
解决方案
你是对的,@安德烈亚斯。默认情况下,在大多数实现中,omp parallel
将根据需要创建尽可能多的线程来利用机器中的可用并行性。omp for
然后将整个循环迭代分配给线程(具体如何取决于选择的计划)。因此它们不会从循环内部拆分单个语句并将每个语句作为单独的并行任务执行。
但是,OTOH,“你为什么要把自己限制在四个线程?” 这段代码是否如此不重要
- 没有其他人会使用它吗?
- 你会在得到更好的机器之前把它扔掉吗?
请注意,您所说的(在单独的线程中执行每个语句)没有意义,因为语句之间存在依赖关系。最后的声明
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];
}
}
}