基于MPI_Scatter计算10000个整数和出现运行错误问题求助
MPI 10进程求和程序报错修复方案
核心错误原因
你程序运行报错的核心是两个低级的参数和索引错误,以及PBS脚本的资源配置冲突:
MPI_Scatter参数配置错误
MPI_Scatter接口的第二个参数是根进程给每个接收进程发送的元素个数,不是全局数组的总元素数。你当前填写的10000会导致0号进程尝试从intArray读取10*10000=100000个元素,远超过数组实际的10000长度,直接触发内存越界。- 子数组访问越界
你已经通过MPI_Scatter将每个进程负责的1000个元素拷贝到了长度为1000的subIntArray数组中,该数组的合法索引范围是0~999。但你遍历的时候用start = rank * 1000作为起始下标,rank≥1的进程会直接访问subIntArray[1000]及以上的非法地址,触发段错误,也就是你遇到的follower进程崩溃问题。 - PBS脚本资源参数冲突
你同时指定了#PBS -l nodes=2和#PBS -l select=5两个冲突的资源申请参数,会导致集群调度器分配的资源不符合预期,建议改为#PBS -l select=2:ncpus=5,刚好申请10个CPU核心匹配你的10进程需求。
修复后的代码
#include <mpi.h> #include <stdio.h> #include <string.h> int main() { int rank, nodes; MPI_Init(NULL, NULL); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nodes); MPI_Status status; int intArray[10000]; int subIntArray[1000]; if(rank == 0) { FILE *fp = fopen("./lab7.csv", "r"); int i = 0; int num; if (!fp) { printf("Can't open file\n"); // 新增异常退出逻辑,避免其他进程永久等待 MPI_Abort(MPI_COMM_WORLD, 1); } else { while (fscanf(fp, "%d", &num) > 0) { intArray[i] = num; i++; } fclose(fp); } } // 修正Scatter的发送个数参数 MPI_Scatter(intArray, 1000, MPI_INT, subIntArray, 1000, MPI_INT, 0, MPI_COMM_WORLD); int ans = 0; int total = 0; // 修正子数组索引,直接遍历0~999即可 for(int i = 0; i < 1000; i++) { ans = ans + subIntArray[i]; } if(rank != 0) { MPI_Ssend(&ans, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); } else { total = ans; for(int j = 1; j < 10; j++) { MPI_Recv(&ans, 1, MPI_INT, j, 0, MPI_COMM_WORLD, &status); total += ans; } printf("Total is %d\n", total); } MPI_Finalize(); return 0; }
优化建议
你可以用MPI_Reduce接口代替手动的send/recv逻辑,代码更简洁也不容易出错,替换逻辑如下:
// 删去原来的if(rank!=0)发送和else接收的所有代码,直接调用以下接口即可 MPI_Reduce(&ans, &total, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); if(rank == 0) { printf("Total is %d\n", total); }
内容的提问来源于stack exchange,提问作者anjana kumari
相关产品推荐
相关产品推荐

