使用MPI实现1到10000求和结果异常问题排查求助
问题根因
你遇到的结果偏差由区间分配逻辑错误直接导致,同时代码和作业脚本存在可优化的风险点:
- 核心错误:当前10个进程的计算区间覆盖范围是
0~9999,完全遗漏了目标计算范围的最大值10000,两者的差值刚好是10000,和你观测到的结果偏差(50005000 - 49995000 = 10000)完全匹配。 - 潜在风险1:代码中硬编码了进程数
10,后续如果调整并行进程数,汇总逻辑会直接出错。 - 潜在风险2:PBS脚本混用
nodes和select两种资源申请语法,可能导致集群调度器分配资源异常。
修复方案
1. 调整区间分配逻辑
将原来的区间赋值修改为如下逻辑,刚好覆盖1~10000的所有数值:
int start = rank * 1000 + 1; int end = (rank + 1) * 1000;
调整后各进程的计算区间为:
- rank0:1~1000
- rank1:1001~2000
- ...
- rank9:9001~10000
2. 替换硬编码的进程数
将汇总逻辑的循环条件替换为MPI接口获取的全局进程数变量,提升代码通用性:
for(int j = 1; j < nodes; j++) { MPI_Recv(&ans, 1, MPI_INT, j, 0, MPI_COMM_WORLD, &status); total += ans; }
3. 规范PBS作业配置(可选)
删除冲突的#PBS -l nodes=2配置,根据集群实际配置调整select语法,比如申请单节点10核运行可以写成:
#PBS -l select=1:ncpus=10 #PBS -l walltime=00:02:00
修复后完整代码示例
#include <cstdio> #include <cstdlib> #include <mpi.h> static int rank, nodes; int main() { MPI_Init(NULL, NULL); MPI_Comm_size(MPI_COMM_WORLD, &nodes); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Status status; int ans = 0; int total = 0; int start = rank * 1000 + 1; int end = (rank + 1) * 1000; for(int i = start; i <= end; i++) { ans = ans + i; } if(rank != 0) { MPI_Ssend(&ans, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); } else { total = ans; for(int j = 1; j < nodes; j++) { MPI_Recv(&ans, 1, MPI_INT, j, 0, MPI_COMM_WORLD, &status); total += ans; } printf("Total is %d\n", total); printf("Total Nodes is %d\n", nodes); } MPI_Finalize(); return 0; }
内容的提问来源于stack exchange,提问作者anjana kumari
相关产品推荐
相关产品推荐

