MPI进程通信实例——用MPI实现梯形积分法(C++)

实例1中,我们体会了一个典型的MPI程序的设计思想和原则

当然,我们不应该仅仅只会hello word类型的并行程序

在本案例中,我们将设计和实现并行版本的梯形积分法

梯形积分法原理

图1(a)用直线下的面积来逼近积分

用a和b之间的梯形面积来近似替代a和b之间函数与x轴围成的面积,当a和b之间的区间分的越来越细的时候,近似值就会不断逼近真实值

假设我们把a和b之间的分为n段,则每段距离长h=(b-a)/2,则之间的任意两个点x_{i}x_{i+1}之间的面积为h/2*[f(x_i)+f(x_{i+1})]

将上述点之间的面积累加求和可以发现,除了两个端点只相加了一次之外,其余的点都被加了两次,因此我们可以得到下面的求和公式:

函数f(x)在[a,b]区间上的积分为h*[f(x_0)/2+f(x_1)+f(x_2)+...+f(x_{n-1})+f(x_n)/2]

将上述过程写成串行的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);
	
	// 初
  • 12
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
A:以下是梯形积分法MPI程序实验: ```c #include <stdio.h> #include <math.h> #include "mpi.h" double func(double x) { return sin(x); } double trap(double local_a, double local_b, int local_n, double h) { double integral; double x; int i; integral = (func(local_a) + func(local_b))/2.0; x = local_a; for (i = 1; i <= local_n-1; i++) { x = x + h; integral = integral + func(x); } integral = integral*h; return integral; } int main(int argc, char** argv) { int my_rank; int p; double a = 0.0; double b = 3.14159; int n = 1024; double h; double local_a; double local_b; int local_n; double integral; double total_integral; int source; int dest = 0; int tag = 0; MPI_Status status; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); MPI_Comm_size(MPI_COMM_WORLD, &p); h = (b-a)/n; local_n = n/p; local_a = a + my_rank*local_n*h; local_b = local_a + local_n*h; integral = trap(local_a, local_b, local_n, h); if (my_rank == 0) { total_integral = integral; for (source = 1; source < p; source++) { MPI_Recv(&integral, 1, MPI_DOUBLE, source, tag, MPI_COMM_WORLD, &status); total_integral = total_integral + integral; } } else { MPI_Send(&integral, 1, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD); } if (my_rank == 0) { printf("With n = %d trapezoids, our estimate\n", n); printf("of the integral from %f to %f = %f\n", a, b, total_integral); } MPI_Finalize(); } ``` 该程序使用了梯形积分法来计算 $sin(x)$ 的从0到$\pi$的积分。程序中首先定义了一个函数func,用于计算被积函数的值。接下来,定义了一个 trap 函数,用于计算局部积分的值。该函数接受了局部区间的起点local_a,终点local_b,局部区间内划分的梯形数量local_n和步长h,并使用梯形积分法计算该区间的局部积分。最后,程序使用MPI_Init来初始化MPI环境,调用MPI_Comm_rank和MPI_Comm_size来获取当前进程的排名和进程总数,计算局部积分并发送/接收各进程的积分值,使用Master进程将所有进程的积分值汇总计算总积分值并输出结果,并通过MPI_Finalize结束MPI环境。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值