与SCi4py的comm.Scatter KeyError

时间:2017-03-24 18:27:37

标签: python mpi4py

我是MPI和mpi4py的新手。我有以下代码的两个问题。例如,排名0的数据不打印,而其他排名的非类型数据打印。

其次,我从comm.Scatter()函数得到一个KeyError'0'错误,我无法解释。

comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()

if rank == 0:
    df = pickle.load(open('lipad0406.p', 'rb'))
else:
    df = None

p = size

d = np.array(df)

n = d.size

m = n/p

d_loc = np.zeros(m)

comm.Scatter(d,d_loc)

print "process", rank, "x:", d
print "process", rank, "x_local:", d_loc.size

2 个答案:

答案 0 :(得分:1)

虽然我无法重现您的特定错误,但此处的问题是非根列d上的错误是单个元素None,因此n=1和{{1}将是假的。如果您不知道非根级别的大小,则需要先将其广播:

m

还要确保数据类型匹配。

答案 1 :(得分:0)

KeyError正在发生,因为Scatter无法处理从输入文件加载的任何数据类型。

Mpi4py提供两种通信功能,名称以大写字母开头的通信功能,例如: Scatter,以及名称以小写字母开头的人,例如scatterFrom the Mpi4py documentation:

  

在MPI for Python中,Comm实例的Bcast(),Scatter(),Gather(),Allgather()和Alltoall()方法为内存缓冲区的集体通信提供支持。变种bcast(),scatter(),gather(),allgather()和alltoall()可以传递通用Python对象。

不清楚的是,即使numpy数组假设暴露内存缓冲区,缓冲区显然需要是一小部分原始数据类型之一,当然也不适用于通用对象。比较以下两段代码:

from mpi4py import MPI
import numpy

Comm = MPI.COMM_WORLD
Size = Comm.Get_size()
Rank = Comm.Get_rank()

if Rank == 0:
    Data = numpy.empty(Size, dtype=object)
else:
    Data = None

Data = Comm.scatter(Data, 0) # I work fine!

print("Data on rank %d: " % Rank, Data)

from mpi4py import MPI
import numpy

Comm = MPI.COMM_WORLD
Size = Comm.Get_size()
Rank = Comm.Get_rank()

if Rank == 0:
    Data = numpy.empty(Size, dtype=object)
else:
    Data = None

Datb = numpy.empty(1, dtype=object)

Comm.Scatter(Data, Datb, 0) # I throw KeyError!

print("Datb on rank %d: " % Rank, Datb)

您应该只需在代码中使用scatter而无需进行其他修改:

d_loc = comm.scatter(d)

或完全消除d_loc,因为scatter不需要像Scatter这样的单独接收缓冲区,只需使用

d = comm.scatter(d)

此外,正如Zulan所说,你需要确保你的numpy数组dtyped的{​​{1}}匹配,并且d_loc被广播到非秩0进程。

完全运行您的代码,m替换为df = pickle.load(open('lipad0406.p', 'rb')),因为我没有并且无法猜测文件的内容,因此无法打印df = range(size) rank-0进程,所以我只能推测这个特定问题与加载文件有关。

代码的最低修改工作版本(文件加载除外)是

d