You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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; // 标记为内部点
}

修正说明

  1. 移除冗余全局变量:删除全局的c、numoutside等变量,改用局部变量避免进程间干扰。
  2. 分布式计算+归约汇总:每个进程计算分配到的行,统计本地外部点数量,通过MPI_Reduce高效汇总结果,替代低效的逐个发送。
  3. 修复核心逻辑:主进程通过归约得到总外部点数量,再计算面积,逻辑符合预期。
  4. 规范MPI调用顺序:将MPI_Finalize放到时间计算之后,符合MPI标准。
  5. 清理冗余输出:仅主进程输出有效结果,避免无效垃圾值打印。
  6. 简化测试函数:testpoint直接返回1/0标记内外点,逻辑清晰易懂。

内容的提问来源于stack exchange,提问作者Mohammed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 13:10:38