并行计算MPI(三):计算π

    学习了之前的一些并行计算MPI基本知识之后,其实可以尝试应用起来,今天这篇文章就是用并行计算求解π的。首先需要知道π的求解方式:

    

    上面是高等数学里的基本知识,所以π的求解就可以变为求解y(x)=4/(1+x^2)在(0,1)区间的面积。而且求解面积这一块可以采用将(0,1)平均分n个块,将n个矩形面积相加即可得到近似解。而且n取得越大,近似解越精确。

    比如我们取n=100,开4个进程来处理,那么相应的每个进程平均分到计算25个矩形面积,如果开5个进程,那么平均分下来每个进程计算20个矩形面积。下面列出代码:

//返回函数值,因为调用次数很多,这里写成inline提高效率
inline double f(double x) {
	return 4/(1+x*x);
}

int main(int argc, char *argv[]) {
	double pi, h, sum, x, startime, endtime;
	int size, myid;
	long long n;
	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &myid);
	MPI_Comm_size(MPI_COMM_WORLD, &size);

	n=0;
	if(0 == myid) {
		cout << "Please enter n" << endl;
		cin >> n;
		startime = MPI_Wtime();
	}
	MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);  //将n广播到所有进程中
	h = 1.0/(double)n;							   //每个矩形块的宽
	sum = 0.0;        
	for(int i=myid+1; i<=n; i+=size) {             //4个进程
		x = h*((double)i - 0.5);                   //进程0:1,5,9,...  进程1:2,6,10,...
		sum = sum + f(x);                          //进程2:3,7,11,... 进程3:4,8,12,...
	}          
	sum = sum * h;								   //每个进程计算的矩形面积之和
	MPI_Reduce(&sum, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);  //利用归约操作(MPI_SUM)将所有进程的sum累加到root进程(0)的sum当中得到结果
	if(myid == 0) {
		endtime = MPI_Wtime();
		printf("用时:%f\n", endtime-startime);
		printf("%0.15f\n", pi);
	}
   下面是测试结果:

并行计算MPI(三):计算π_第1张图片

并行计算MPI(三):计算π_第2张图片并行计算MPI(三):计算π_第3张图片

并行计算MPI(三):计算π_第4张图片

并行计算MPI(三):计算π_第5张图片

    这里n取100000000,是为了计算结果精确一些。实验室机器是单核CPU,而且处理能力不是很强。可以发现4个进程获得的效果是最好的,但是当进程数增加的时候,时间反而会增加,原因应该是当进程太大,那么进程之间的通信成了最主要的瓶颈了。对于这个例子而言,其实主要就是最后一步MPI_Reduce这个操作是进程之间进行了通信,也是比较耗时的地方。而且更主要的是本机是单核的,可能最适合的4个进程,如果是多核的话那么肯定会有其他比较合适的进程数。所以并不是进程数越多越好,而是要结合具体的情况平衡进程数和进程之间通信来编写程序。

你可能感兴趣的:(并行计算)