mpi4py跨函数使用Bcast广播numpy数组出现None输出问题求解
问题根因
你代码的问题出在worker函数中对comm.Bcast的返回值处理逻辑:
- mpi4py中大写开头的缓冲类通信接口(Bcast、Send、Recv等)都是直接修改传入的可变缓冲对象本身,返回值固定为
None,你在worker里把comm.Bcast的返回值赋值给data,直接把初始化好的numpy数组覆盖成了None,所以输出全是空。 - 你之前用列表能正常工作,大概率是用了小写开头的对象类通信接口
bcast,这个接口会直接返回广播的对象,不需要提前初始化接收缓冲,所以赋值逻辑是对的。
修正后代码
把worker里的赋值操作去掉即可,Bcast会直接修改你传入的data数组内容:
from mpi4py import MPI import numpy as np comm = MPI.COMM_WORLD rank = comm.rank def master(): data = np.arange(4.0) comm.Bcast([data, MPI.DOUBLE], root=0) print('rank',rank,data) return def worker(): data = np.zeros(4) # 此处无需赋值,Bcast会直接修改data的内存内容 comm.Bcast([data, MPI.DOUBLE], root=0) print('rank',rank,data) return if rank == 0: master() else: worker()
额外说明
- 该问题和跨函数、跨模块调用没有关联,只要所有进程调用
Bcast时传入的缓冲类型、长度、root参数匹配,就能正常通信,你拆分master、worker函数的逻辑本身没有问题。 - 两种广播接口的适用场景差异可以参考:
comm.Bcast:适用于numpy数组等连续内存缓冲对象,需要提前在接收端初始化相同长度、类型的缓冲,性能更高,适合大数据量通信comm.bcast:适用于Python原生对象(列表、字典、自定义类等),不需要提前初始化接收缓冲,直接拿返回值即可,内部会做序列化,小数据量使用更方便。
内容的提问来源于stack exchange,提问作者Pouncequick
相关产品推荐
相关产品推荐

