实例1中,我们体会了一个典型的MPI程序的设计思想和原则
当然,我们不应该仅仅只会hello word类型的并行程序
在本案例中,我们将设计和实现并行版本的梯形积分法
梯形积分法原理
用a和b之间的梯形面积来近似替代a和b之间函数与x轴围成的面积,当a和b之间的区间分的越来越细的时候,近似值就会不断逼近真实值
假设我们把a和b之间的分为n段,则每段距离长,则之间的任意两个点和之间的面积为
将上述点之间的面积累加求和可以发现,除了两个端点只相加了一次之外,其余的点都被加了两次,因此我们可以得到下面的求和公式:
函数f(x)在[a,b]区间上的积分为
将上述过程写成串行的C代码为:
double trap(double a, double b, int n) {
/*梯形积分法的实现 a,b 为积分的上下限, n为细分的区间数目*/
double h = (b - a) / n;
double sum = (f(a) + f(b)) / 2;
for (int i = 1; i < n; i++) {
sum += f(a + i * h);
}
return sum * h;
}
并行化梯形积分法
在此基础上我们使用四个基本步骤去设计并行代码:
1. 将问题划分为多个任务
2. 在任务中识别出要通信的地方
3. 将任务聚合为复合任务
4. 在核上分配任务
按照上述原则,我们可以把任务简单的按照积分的上下限来分,有n个进程,就将积分限划分为n等分,每一个进程计算这段区间的上的积分
因此,我们需要再对n个进程的计算结果累加求和,这就需要用到进程通信了,在这里我们先简单处理,规定0号进程负责接收和求和各个段的积分,其余进程则将计算结果发送至0号进程
大体的思路就如上所说,接下来我们写一下有关的代码版本1:
int main() {
int my_rank, comm_sz; //当前进程的编号,所有进程的数目
double a = -3.1415926535, b = 3.1415926535; //积分的上下限
int n = 1024; //区间的宽度
/*并行部分开始*/
MPI_Init(NULL,NULL);
// 获取当前进程的编号,所有进程的数目
MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
// 初