我有一个简单的代码:
double eps;
A[N][N][N];
...
for(i=1; i<=N-2; i++)
for(j=1; j<=N-2; j++)
for(k=1; k<=N-2; k++)
{
A[i][j][k] = (A[i-1][j][k]+A[i+1][j][k])/2.;
}
for(i=1; i<=N-2; i++)
for(j=1; j<=N-2; j++)
for(k=1; k<=N-2; k++)
{
A[i][j][k] = (A[i][j-1][k]+A[i][j+1][k])/2.;
}
for(i=1; i<=N-2; i++)
for(j=1; j<=N-2; j++)
for(k=1; k<=N-2; k++)
{
double e;
e=A[i][j][k];
A[i][j][k] = (A[i][j][k-1]+A[i][j][k+1])/2.;
eps=Max(eps,fabs(e-A[i][j][k]));
}
我需要使用MPI制作并行代码。
好的,我理解,如何处理eps
- 它是全局变量,我需要在任何地方进行计算。所以,我创建局部变量,计算它并从每个节点返回结果。或者减少。
但是如何处理矩阵A
?它必须由每个节点共享。
如何同步每个三for
构造? (如果使用,请参阅,当前A[i][j][k]
- 元素是使用他的邻居计算的 - 左右A[i-1][][] A[i+1][][]
或上下A[][j+1][] A[][j-1][]
或前后A[][][k-1] A[][][k+1]
)
谢谢!
第一版:
我的第一个解决方案是替换for
构造以最小化对索引的依赖,例如:
for(j=1; j<=N-2; j++)
for(k=1; k<=N-2; k++)
//MPI here, Send processor (j,k) - coordinates of vector to compute next statement
for(i=1; i<=N-2; i++)
{
A[i][j][k] = (A[i-1][j][k]+A[i+1][j][k])/2.;
}
等等:
for(i=1; i<=N-2; i++)
for(k=1; k<=N-2; k++)
for(j=1; j<=N-2; j++)
//here (i,k) is free dimensions, dependency only from j. send vector(i,k) to every processor
{
A[i][j][k] = (A[i][j-1][k]+A[i][j+1][k])/2.;
}
for(i=1; i<=N-2; i++)
for(j=1; j<=N-2; j++)
for(k=1; k<=N-2; k++)
//dependency only from k, (i,j) are free. send it to processor
{
double e;
e=A[i][j][k];
A[i][j][k] = (A[i][j][k-1]+A[i][j][k+1])/2.;
eps=Max(eps,fabs(e-A[i][j][k]));
}
答案 0 :(得分:3)
您的算法表现出数据依赖性,非常类似于3D FFT算法。无论您如何选择分发数据,它都不是其中一个循环的最佳分布。例如。如果沿k
轴分布,则第一个和第二个循环可以并行运行,但不能运行到最后一个循环。
解决方案是在最后一个循环之前转置矩阵。分布式矩阵的全局转置通常使用全部操作来完成,MPI_ALLTOALL
或MPI_ALLTOALLV
,这取决于矩阵是否划分为相同大小的间隙(通常取决于是否矩阵大小可以被MPI过程的数量整除(或不)。看看Jonathan Dursi的this excellent answer。它适用于2D情况,但也可以轻松扩展到3D。