我正在为一个项目使用MPI。我需要以非阻塞模式将数据包从一个节点传输到另一个节点。我正在使用包含有关我的通信逻辑的相关信息的类来组织此程序包。
我正在使用功能@babel/plugin-syntax-dynamic-import
进行一些测试,以获取我的通讯和缓冲区的请求,还使用irecv()
进行测试以验证是否有消息到达。
MPI缺少Python的文档,因此我正在检查source code以获得更多信息,我在使用什么功能。
源代码声明irecv如下:
test()
我了解到,如果我想将数据放入缓冲区中,则需要设置可选参数“ buf”以及我希望将接收到的消息存储的位置。
我尝试了以下测试以了解其工作原理:
def irecv(self, buf=None, int source=ANY_SOURCE, int tag=ANY_TAG):
"""Nonblocking receive"""
cdef MPI_Comm comm = self.ob_mpi
cdef Request request = <Request>Request.__new__(Request)
request.ob_buf = PyMPI_irecv(buf, source, tag, comm, &request.ob_mpi)
return request
我期望以下行为:
等级为0的节点将数据包作为对象发送到等级为1的节点
排名1的节点开始无阻塞接收,并且当接收完成时,from mpi4py import MPI
import time
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
class Package(object):
msg = [[0,1,0,1,0,1],
[0,1,0,1,0,1],
[0,1,0,1,0,1],
[0,1,0,1,0,1],
[0,1,0,1,0,1]]
gotMessage = False
destination = -1
if rank == 0:
data = Package()
comm.isend(data, dest=1, tag=11)
elif rank == 1:
data = Package()
req = comm.irecv(buf=data, source=0, tag=11)
while not req.test():
sleep(0.1)
print(rank, data.msg)
返回test()
时会发生什么,我可以打印True
。
问题是,当我运行时,data.msg
发生以下错误:
TypeError:应为可写缓冲区对象
如何正确使用buf
传输/接收对象?
答案 0 :(得分:1)
在mpi4py
中,MPI之上有两种接口。来回通信缓冲区的低级接口(以大写字母表示,Isend
),和通信python对象的高级别接口(即isend
)。
高级接口通过pickle序列化对象。对于非阻塞操作,这需要一个用户提供的缓冲区,并且需要足够大。另一方面,test
函数返回一个found, object
元组。因此,使用高级界面,您的代码接收器如下所示:
buf = bytearray(b" " * 256)
req = comm.irecv(buf=buf, source=0, tag=11)
while True:
found, data = req.test()
if found:
break
time.sleep(0.1)
print(1, data.msg)
请注意,您的发件人代码缺少邮件的填写内容。但是,您send
还是isend
数据都没关系。
在任何情况下,您都必须以某种方式为接收缓冲区确定足够的缓冲区大小,这可能实际上是不可能做到的。如果缓冲区太小,您将收到MPI.Exception
。
您还可以使用低级界面。例如,您可以轻松地发送numpy数组:
if rank == 0:
data = np.array([1, 2, 3], dtype=float)
comm.Send(data, dest=1, tag=11)
elif rank == 1:
data = np.zeros(3, dtype=float)
req = comm.Irecv(buf=data, source=0, tag=11)
while True:
found = req.Test()
if found:
break
time.sleep(0.1)
print(1, data)
shape
和dtype
必须匹配才能理解。