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

MPI编程汇总各进程均值求总均值(禁用MPI_Reduce)及代码排错

问题分析

你的代码存在几个关键错误,直接导致了异常输出:

  • 输入顺序错误:根进程在读取m之前就计算size*m,此时m未初始化,值为随机垃圾值(大概率是0),所以会打印Enter 0 elements,后续输入逻辑完全混乱。
  • 总均值计算逻辑错误:根进程通过MPI_Gather收集到了size个进程的均值,但你用for (int i = 0; i < m; i++)循环累加,循环次数完全错误,应该遍历size次;同时累加前未重置avg,会把根进程自身的均值重复计算。
  • 固定数组大小限制:arr[10]和ans[10]的固定大小会导致当size*m超过10时数组越界,引发未知错误。
  • 变量初始化不严谨:非根进程的sum和avg未显式初始化,可能被垃圾值干扰计算。

修复后的代码

#include<stdio.h>
#include<stdlib.h>
#include<mpi.h>

int main(int argc, char *argv[]){
    int rank, size, m;
    int *arr = NULL;
    int *ans = NULL;
    float avg = 0.0f, sum = 0.0f;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    if (rank == 0){
        fprintf(stdout, "Enter m:\n");
        fflush(stdout);
        // 先读取m的值,再计算需要输入的元素总数
        scanf("%d", &m);
        fprintf(stdout, "Enter %d elements:\n", size * m);
        fflush(stdout);
        // 动态分配数组,适配任意合法的size和m
        arr = (int*)malloc(size * m * sizeof(int));
        for (int i = 0; i < size * m; i++){
            scanf("%d", &arr[i]);
        }
    }
    
    // 广播m到所有进程,确保非根进程知道要处理的元素数量
    MPI_Bcast(&m, 1, MPI_INT, 0, MPI_COMM_WORLD);

    // 非根进程分配接收数据的内存
    if (rank != 0){
        ans = (int*)malloc(m * sizeof(int));
    }

    // 分发数据到各个进程
    MPI_Scatter(arr, m, MPI_INT, ans, m, MPI_INT, 0, MPI_COMM_WORLD);

    // 计算当前进程的局部均值
    sum = 0.0f;
    for (int i = 0; i < m; i++){
        sum += ans[i];
    }
    avg = sum / m;

    // 根进程分配存储所有进程均值的内存
    float *all_avgs = NULL;
    if (rank == 0){
        all_avgs = (float*)malloc(size * sizeof(float));
    }

    // 收集所有进程的均值到根进程
    MPI_Gather(&avg, 1, MPI_FLOAT, all_avgs, 1, MPI_FLOAT, 0, MPI_COMM_WORLD);

    if (rank == 0){
        // 重新初始化变量计算总均值,避免和局部均值混淆
        float total_avg = 0.0f;
        // 遍历所有进程的均值,共size个
        for (int i = 0; i < size; i++){
            total_avg += all_avgs[i];
        }
        total_avg /= size;
        fprintf(stdout, "The average of all values: %f\n", total_avg);
        fflush(stdout);

        // 释放动态分配的内存
        free(arr);
        free(all_avgs);
    } else {
        free(ans);
    }

    MPI_Finalize();
    return 0;
}

修复要点说明

  1. 调整输入流程:根进程先读取m,再计算需要输入的元素总数,确保m已被正确赋值。
  2. 修正总均值计算:根进程循环size次累加所有进程的均值,使用独立变量total_avg避免和局部均值混淆。
  3. 动态内存分配:替换固定大小数组为动态分配,适配任意合法的进程数和元素数量,避免数组越界。
  4. 严谨的变量初始化:显式初始化sum和avg,避免垃圾值干扰计算。
  5. 内存释放:所有动态分配的内存使用后及时释放,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:17:38