MPI并行化Mandelbrot集面积计算结果异常求助
修复MPI并行化Mandelbrot集面积计算的错误
关键错误分析
- 全局变量滥用:全局变量
numoutside初始值为1,testpoint函数依赖它标记外部点,每个进程都有独立副本,设计冗余且易出错,直接返回1标记外部点即可。 - 主进程累加逻辑错误:主进程中
res += numoutside逻辑完全错误,应将每个收到的结果(1=外部点,0=内部点)累加到总和变量,而非接收值加全局变量。 - 累加变量未初始化:主进程的
outsum未初始化为0,导致累加结果为随机值。 - 接收次数不匹配:主进程循环接收
NPOINTS*NPOINTS次,但自身未参与计算,实际发送点数远小于该值,会导致程序阻塞。 - MPI_Finalize调用时机错误:在
MPI_Wtime之前执行MPI_Finalize,不符合MPI规范,可能导致时间计算出错。 - 多进程冗余输出:所有进程都打印面积结果,但仅主进程计算了有效数值,其他进程的
area/error为未定义的垃圾值。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <mpi.h> #define NPOINTS 1000 #define MAXITER 1000 struct d_complex { double r; double i; }; int testpoint(struct d_complex); int main() { int i, j; int res; double area, error, eps = 1.0e-5; int myrank, mysize; double stsec, ensec, commtime; MPI_Status status; MPI_Init(NULL, NULL); MPI_Comm_size(MPI_COMM_WORLD, &mysize); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); stsec = MPI_Wtime(); int local_outside = 0; // 所有进程计算分配给自己的行 for (i = myrank; i < NPOINTS; i += mysize) { for (j = 0; j < NPOINTS; j++) { struct d_complex c; c.r = -2.0 + 2.5 * (double)(i) / (double)(NPOINTS) + eps; c.i = 1.125 * (double)(j) / (double)(NPOINTS) + eps; if (testpoint(c)) { local_outside++; } } } // 归约汇总所有进程的外部点数量 int total_outside; MPI_Reduce(&local_outside, &total_outside, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); // 主进程计算并输出结果 if (myrank == 0) { area = 2.0 * 2.5 * 1.125 * (double)(NPOINTS * NPOINTS - total_outside) / (double)(NPOINTS * NPOINTS); error = area / (double)NPOINTS; printf("Area of Mandlebrot set = %12.8f +/- %12.8f\n", area, error); printf("Finish.\n"); } ensec = MPI_Wtime(); commtime = ensec - stsec; if (myrank == 0) { printf("Total time: %.3f\n", commtime); } MPI_Finalize(); return 0; } int testpoint(struct d_complex c) { struct d_complex z; int iter; double temp; z = c; for (iter = 0; iter < MAXITER; iter++) { temp = (z.r * z.r) - (z.i * z.i) + c.r; z.i = 2 * z.r * z.i + c.i; z.r = temp; if ((z.r * z.r + z.i * z.i) > 4.0) { return 1; // 标记为外部点 } } return 0; // 标记为内部点 }
修正说明
- 移除冗余全局变量:删除全局的
c、numoutside等变量,改用局部变量避免进程间干扰。 - 分布式计算+归约汇总:每个进程计算分配到的行,统计本地外部点数量,通过
MPI_Reduce高效汇总结果,替代低效的逐个发送。 - 修复核心逻辑:主进程通过归约得到总外部点数量,再计算面积,逻辑符合预期。
- 规范MPI调用顺序:将
MPI_Finalize放到时间计算之后,符合MPI标准。 - 清理冗余输出:仅主进程输出有效结果,避免无效垃圾值打印。
- 简化测试函数:
testpoint直接返回1/0标记内外点,逻辑清晰易懂。
内容的提问来源于stack exchange,提问作者Mohammed
相关产品推荐
相关产品推荐

