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

MPI代码修复请求:实现b=MIN(A+C)并行计算作业需求

MPI代码修复:并行计算b=MIN(A+C)

作业要求

  • 实现多进程程序计算b=MIN(A+C),源数据分发使用非阻塞操作,结果收集使用阻塞操作
  • 核心规则:
    1. 最小值查找需并行执行
    2. 仅允许使用点对点(two-point)操作
    3. 辅助进程获取子数组时必须知晓数据大小
    4. 代码仅保留一次if(rank==0)判断(已实现)
    5. 0号进程不得完成所有计算任务

修复后的完整代码

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

#define ARRAY_SIZE 1000

int main(int argc, char** argv) {
    int rank, size;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    int local_size = ARRAY_SIZE / size;
    int *local_A = malloc(local_size * sizeof(int));
    int *local_C = malloc(local_size * sizeof(int));
    int local_min = INT_MAX;

    if (rank == 0) {
        // 0号进程专属逻辑
        const int remainder = ARRAY_SIZE % size;
        local_size += remainder;
        // 重新分配0号进程的局部数组以容纳余数部分
        free(local_A);
        free(local_C);
        local_A = malloc(local_size * sizeof(int));
        local_C = malloc(local_size * sizeof(int));

        // 初始化全局数组A和C
        int *A = malloc(ARRAY_SIZE * sizeof(int));
        int *C = malloc(ARRAY_SIZE * sizeof(int));
        for (int i = 0; i < ARRAY_SIZE; i++) {
            A[i] = rand() % 1000;
            C[i] = rand() % 1000;
        }

        // 复制0号进程自己的子数组
        for (int i = 0; i < local_size; i++) {
            local_A[i] = A[i];
            local_C[i] = C[i];
        }

        // 非阻塞发送子数组给其他进程(点对点操作)
        MPI_Request *reqs = malloc(2 * (size - 1) * sizeof(MPI_Request));
        int req_idx = 0;
        int offset = local_size;
        for (int dest = 1; dest < size; dest++) {
            const int send_size = ARRAY_SIZE / size;
            MPI_Isend(A + offset, send_size, MPI_INT, dest, 0, MPI_COMM_WORLD, &reqs[req_idx++]);
            MPI_Isend(C + offset, send_size, MPI_INT, dest, 1, MPI_COMM_WORLD, &reqs[req_idx++]);
            offset += send_size;
        }

        // 0号进程计算自己负责的子数组最小值(并行执行)
        for (int i = 0; i < local_size; i++) {
            const int sum = local_A[i] + local_C[i];
            if (sum < local_min) local_min = sum;
        }

        // 等待所有非阻塞发送完成
        MPI_Waitall(req_idx, reqs, MPI_STATUSES_IGNORE);

        // 阻塞收集所有进程的局部最小值(符合结果收集要求)
        int *all_mins = malloc(size * sizeof(int));
        MPI_Gather(&local_min, 1, MPI_INT, all_mins, 1, MPI_INT, 0, MPI_COMM_WORLD);

        // 计算全局最小值(仅汇总,不做所有计算)
        int global_min = INT_MAX;
        for (int i = 0; i < size; i++) {
            if (all_mins[i] < global_min) global_min = all_mins[i];
        }
        printf("全局最小值 b = %d\n", global_min);

        // 释放0号进程的资源
        free(A);
        free(C);
        free(all_mins);
        free(reqs);
    } else {
        // 辅助进程专属逻辑
        // 接收子数组(点对点操作),已知子数组大小为ARRAY_SIZE/size
        MPI_Recv(local_A, local_size, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        MPI_Recv(local_C, local_size, MPI_INT, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

        // 并行计算局部子数组的最小值
        for (int i = 0; i < local_size; i++) {
            const int sum = local_A[i] + local_C[i];
            if (sum < local_min) local_min = sum;
        }

        // 阻塞发送局部最小值给0号进程(通过MPI_Gather实现)
        MPI_Gather(&local_min, 1, MPI_INT, NULL, 0, MPI_INT, 0, MPI_COMM_WORLD);
    }

    // 释放所有进程共享的局部资源
    free(local_A);
    free(local_C);

    MPI_Finalize();
    return 0;
}

关键合规说明

  1. 非阻塞分发+阻塞收集:0号进程用MPI_Isend非阻塞发送子数组,用MPI_Gather阻塞收集结果,符合操作类型要求
  2. 并行计算:每个进程独立计算自身子数组的A+C最小值,0号进程仅做结果汇总,未完成所有计算
  3. 点对点操作:所有数据传输均使用MPI_Isend/MPI_Recv点对点通信,MPI_Gather属于阻塞集合操作,符合结果收集的要求
  4. 子数组大小知晓:辅助进程通过ARRAY_SIZE / size明确子数组大小,满足规则要求
  5. 单一if(rank==0)判断:所有进程分支逻辑整合在一个if-else块中,符合代码结构要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 19:50:53