mpi4py接收用户输入场景下Recv()报MPI_ERR_TRUNCATE错误求助
问题根源
你的报错由核心传参错误和多个隐藏逻辑bug共同导致:
comm.recv()参数传参错误:mpi4py的recv方法第一个位置参数是接收缓冲区buf,源进程编号需要用关键字参数source=传入。你在0号进程接收其他进程计算结果时写的comm.recv(source,tag = 0),把存储源进程号的整数变量source当成了接收缓冲区传入,首先触发了'buf' argument is deprecated的警告;其次整数缓冲区长度和其他进程发送的浮点型积分结果长度不匹配,直接触发MPI_ERR_TRUNCATE: message truncated消息截断错误。- 隐藏逻辑bug(解决传参错误后仍会导致程序异常或结果错误):
- 接收循环逻辑错误:0号进程接收结果时初始
source=1,进入循环后先执行source +=1,会直接跳过1号进程从2号进程开始接收,最终会因为收不到1号进程发送的消息触发死锁。 - 局部区间上限计算公式错误:
local_b = (local_a + local_n) * h写法不符合梯形积分的区间划分逻辑,正确公式应为local_b = local_a + local_n * h。 - 积分上下限输入逻辑颠倒:你将第一个输入的"Upper Limit(上限)"赋值给a,第二个输入的"Lower Limit(下限)"赋值给b,后续计算步长
h=(b-a)/n会得到负值,积分结果完全错误。 local_n = n/size得到的是浮点数,传入梯形计算函数的循环范围时容易出现计数偏差。
- 接收循环逻辑错误:0号进程接收结果时初始
修复方案
- 修正所有
recv调用的传参,源进程号必须显式用source=关键字传入,不要作为第一个位置参数传递。 - 调整接收循环的计数逻辑,从1号进程开始按顺序接收所有非0进程的计算结果。
- 修正局部区间边界的计算公式。
- 调整积分上下限的输入逻辑,保证a为积分下限、b为积分上限。
- 将
local_n转为整数,避免浮点数循环计数问题。
修复后的可运行代码如下:
from mpi4py import MPI def fx(x): return x*x def Trap(local_a , local_b, local_n, h): integral = (fx(local_a) + fx(local_b))/2.0 x = local_a for i in range(1,int(local_n)): x += h integral += fx(x) integral *= h return integral comm = MPI.COMM_WORLD rank = comm.rank size = comm.size source = 1 dest = 0 a = 0.0 b = 0.0 n = 0 if rank == 0: # 修正上下限输入对应关系,a为下限,b为上限 a = float(input("Enter Lower Limit \n")) b = float(input("Enter Upper Limit \n")) n = int(input("Enter number of trapezoids \n")) for i in range(1,size): dest = i comm.send(a, dest=dest, tag=0) comm.send(b, dest=dest, tag=1) comm.send(n, dest=dest, tag=2) else: a = comm.recv(source=0, tag=0) b = comm.recv(source=0, tag=1) n = comm.recv(source=0, tag=2) h = (b - a) / n local_n = n // size # 转为整数,默认n可被size整除的场景 local_a = a + rank * local_n * h local_b = local_a + local_n * h # 修正local_b计算公式 integral = Trap(local_a, local_b, local_n, h) if rank == 0: total = integral while source < size: # 修正recv传参,source用关键字传入,先接收再递增进程号 recv_integral = comm.recv(source=source, tag=0) total = total + recv_integral source += 1 else: comm.send(integral, dest=0, tag=0) if rank == 0: print(" With n = %d trapezoids, our estimate \n" %(n)) print("of the integral from %f to %f = %0.8f\n" %(a,b,total))
注:如果需要支持n不能被进程数整除的场景,可以额外给最后一个进程分配剩余的梯形段数,避免积分区间遗漏。
内容的提问来源于stack exchange,提问作者h3avyc0der
相关产品推荐
相关产品推荐

