MPI代码修复请求:实现b=MIN(A+C)并行计算作业需求
MPI代码修复:并行计算
b=MIN(A+C) 作业要求
- 实现多进程程序计算
b=MIN(A+C),源数据分发使用非阻塞操作,结果收集使用阻塞操作 - 核心规则:
- 最小值查找需并行执行
- 仅允许使用点对点(two-point)操作
- 辅助进程获取子数组时必须知晓数据大小
- 代码仅保留一次
if(rank==0)判断(已实现) - 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; }
关键合规说明
- 非阻塞分发+阻塞收集:0号进程用
MPI_Isend非阻塞发送子数组,用MPI_Gather阻塞收集结果,符合操作类型要求 - 并行计算:每个进程独立计算自身子数组的
A+C最小值,0号进程仅做结果汇总,未完成所有计算 - 点对点操作:所有数据传输均使用
MPI_Isend/MPI_Recv点对点通信,MPI_Gather属于阻塞集合操作,符合结果收集的要求 - 子数组大小知晓:辅助进程通过
ARRAY_SIZE / size明确子数组大小,满足规则要求 - 单一
if(rank==0)判断:所有进程分支逻辑整合在一个if-else块中,符合代码结构要求
内容的提问来源于stack exchange,提问作者w4de
相关产品推荐
相关产品推荐

