目录
我们将在本节和下一节中介绍MPI并行程序设计的两种主要模式,对等模式和主从模式。大部分MPI的程序都是这两种模式之一或二者的组合。
本节我们通过一个典型的例子-Jacobi迭代来介绍MPI对等模式程序设计,并且将每一种具体的实现和特定的MPI增强功能相结合,既介绍并行程序设计方法,又讲解MPI特定功能调用。
一、雅克比(Jacobi迭代)
雅克比迭代法是一种求解线性方程组的迭代算法,我们之前在椭圆型偏微分方程算法中进行过介绍,包括其基本概念和理论推导,感兴趣的小伙伴可参考下面链接:
偏微分方程算法之迭代法(番外篇)_迭代法解偏微分方程-CSDN博客https://blog.csdn.net/L_peanut/article/details/138302224
Jacobi迭代的功能是使得到的新值是原来旧值点相邻数值点的平均。Jacobi迭代的局部性很好,可以获得很高的并行性。将参加迭代的数据块分割后,各块之间除了相邻的元素需要通信外,各块内部可以完全独立并行计算。实验表明,随着计算规模增大,通信的开销相对于计算来说比例会降低,将更有利于提高并行效果。
...
REAL A(N+1, N+1), B(N+1, N+1)
...
DO K=1, STEP
DO J=1, N
DO I=1, N
B(I, J)=0.25*(A(I-1,J)+A(I+1,J)+A(I,J-1)+A(I,J+1))
ENDDO
ENDDO
DO J=1, N
DO I=1, N
A(I, J)=B(I, J)
ENDDO
ENDDO
ENDDO
二、MPI程序Jacobi实现
并行求解需要将数据进行分解,我们将参加迭代的数据按列分割,假设一共有4个进程参与计算,分割结果如下:
假设需要迭代的数据是M×N的二维数组A(M,N),令M=4*N。分块后分布在4个不同进程上的数据分别是:
进程0:A(M,1:N) 进程1:A(M, N+1:2*N) 进程2:A(M, 2*N+1:3*N) 进程3:A(M, 3*N+1:M)
迭代过程中,边界点新值的计算需要相邻边界其它块的数据,需要在每一个块的两侧各增加1列数据空间,用于存放从相邻数据块通信得到的数据。这样原来每个数据块的大小从M*N扩大到M*(N+2),进程0和进程3的数据块只需扩大一侧即可满足通信要求,这里为了编程方便和形式的一致,统一在两侧增加1列。
计算和通信过程:首先对数组赋初值,边界赋8,内部赋0。对不同的进程,赋值方式是不同的(两个内部块相同,但内部块和外部块两两互不相同)。然后开始迭代,在迭代前,每个进程都需要从相邻进程得到数据块,同时每一个进程也需要向相邻的进程提供数据块(Fortran语言中数组在内存中排列是列优先)。由于每一个新迭代点的值是由相邻点的旧值得到的,所以引入一个中间数组,用来记录临时得到的新值,一次迭代完成后,统一进行更新操作。