通过 MPI [MPI4py] 发送复数时的 MPI_ERR_TRUNCATE
Posted
技术标签:
【中文标题】通过 MPI [MPI4py] 发送复数时的 MPI_ERR_TRUNCATE【英文标题】:MPI_ERR_TRUNCATE when sending complex number over MPI [MPI4py] 【发布时间】:2018-05-22 01:16:12 【问题描述】:我正在尝试使用 Python 的 MPI (MPI4py) 实现将单个复数从单个发送方发送到单个接收方。代码如下:
from mpi4py import MPI
import numpy as np
comm = MPI.COMM_WORLD
if comm.rank == 0:
print("I am sender")
a = np.matrix('5+1j')
req = [None]
#Send message with a predefined tag, like 15, to rank 1
req = comm.Isend([a, MPI.COMPLEX], dest=1, tag=15)
MPI.Request.Wait(req)
print("Sender sent: ")
print(a[0])
else:
print("I am receiver")
A = np.empty_like(np.matrix([[0]*(1) for i in range(1)]))
print("point 1")
#Receive message with tag 15 from rank 0
rA = comm.Irecv(A, source=0, tag=15)
rA.wait()
print("Receiver received: ")
print(A)
请注意,上面的示例是我的目标的简化版本,即从一个发送者向多个接收者发送一个包含许多复杂条目的numpy
数组(或numpy
矩阵)。这就是为什么我在此示例中使用非阻塞发送Comm::Isend()
和接收Comm::Irecv()
,以及Request::Wait()
。但是,一般来说,对于 for 循环的每次迭代,我都会有一个 Comm::Isend()
,而对于一个请求向量,我会拥有一个 Request::Waitall()
,一般来说,每个接收者都有一个。
对于上述程序,创建的 MPI 进程只有两个,一个发送者和一个接收者。我的 MPI4py 安装也是 3.0.0。并使用 Python 2.7.14 和 Open MPI 2.1.2 的内核。
现在,程序崩溃了
rA.wait()
出现以下错误
mpi4py.MPI.Exception: MPI_ERR_TRUNCATE: 消息被截断
根据网上搜索的意思是接收方的缓冲区不足以存储接收到的数据即复数,但我不明白为什么。
【问题讨论】:
【参考方案1】:这是幕后发生的事情:
MPI_Isend(..., datatype=MPI_COMPLEX, ...)
MPI_Irecv(..., datatype=MPI_LONG, ...)
所以问题出在你如何初始化接收缓冲区
A = np.empty_like(np.matrix([[0]*(1) for i in range(1)]))
可能的修复是
A = np.empty(shape(1,1), dtype=complex)
或
A = np.matrix('-1-1j')
为了将A
定义为复数矩阵
【讨论】:
这对于 1×1 操作数来说很好,但接收到的矩阵通常是 n×n。在这种情况下你将如何初始化? MPI 是否要求提前为整个矩阵初始化接收缓冲区? 另一个选项是A = np.zeros(shape(1,1),dtype=complex)
MPI
要求在MPI_Irecv()
之前分配缓冲区(不需要初始化)。 mpi4py
可能做一些额外的魔法并为你分配缓冲区,但老实说,我不知道。
为了不初始化分配,可以A = np.empty(shape(1,1), dtype=complex)
以上是关于通过 MPI [MPI4py] 发送复数时的 MPI_ERR_TRUNCATE的主要内容,如果未能解决你的问题,请参考以下文章
MPI (mpi4py) - 如果第一个 test() 返回 false,则 irecv() 和 test() 不会在循环中工作