在实例2中,我们体会了进程之间是如何通信的
实际上,在大规模并行计算中,我们常涉及到如何将数据分发给各个进程,进程完成后又如何将数据重新聚合回来
在这个实例中,我们将体会MPI是如何高效简洁的实现数据的分发和聚集操作的
向量求和的基本原理
给定向量和向量,求两个向量之和z,计算过程如下:
对于一个串行化程序,其代码如下:
void Vector_Sum(double x[], double y[], double z[], int n){
for(int i=0; i<n; i++){
z[i] = x[i] + y[i];
}
}
数据的基本划分方式
如何将上述代码并行化呢?一个简单的思路就是平分整个数组,每个进程计算相同大小的分量,最后再利用进程通信将结果送至主进程
上述问题的关键在于如何划分数据,一般情况下有三种划分方式:块划分、循环划分、块-循环划分
1. 块划分:连续划分。假设数组大小为12,有3个进程,则0号进程分到0-3号连续四个数据、1号进程分到4-7号连续四个数据、2号进程分到8-11号连续四个数据
2. 循环划分:取余划分。如上面的假设情况,将0/3/6/9这三个数据分至0号进程、将1/4/7/10这四个数据分至1号进程、将2/5/8/11这个四个数据分至2号进程
3. 块-循环划分:分块后取余划分。先将连续n个数据打包为一个块,再将块号取余;假设2个为一块,则0/1分为0号块、2/3为1号块、4/5为3号块;则0/1/6/7分至0号进程、2/3/8/9分至1号进程、3/4/10/11分至3号进程
散射函数
在MPI中,提供了第一种划分方法——块划分的实现函数MPI_Scatter,其函数原型如下所示:
int MPI_Scatter(
void* send_buf_p // 发送进程的消息地址
int send_count // 发送进程的消息大小
MPI_Datatypee send_type // 发送进程的数据类型
void* recv_buf_p // 接收进程的消息地址
int recv_count // 接收进程的消息大小
MPI_Datatyp