我想从所有处理器中将numpy数组内容收集到一个。如果所有数组的大小相同,则可以使用。但是我没有看到为proc相关大小的数组执行相同任务的自然方式。请考虑下面的代码:发送/接收奇数大小的numpy数组
from mpi4py import MPI
import numpy
comm = MPI.COMM_WORLD
rank = comm.rank
size = comm.size
if rank >= size/2:
nb_elts = 5
else:
nb_elts = 2
# create data
lst = []
for i in xrange(nb_elts):
lst.append(rank*3+i)
array_lst = numpy.array(lst, dtype=int)
# communicate array
result = []
if rank == 0:
result = array_lst
for p in xrange(1, size):
received = numpy.empty(nb_elts, dtype=numpy.int)
comm.Recv(received, p, tag=13)
result = numpy.concatenate([result, received])
else:
comm.Send(array_lst, 0, tag=13)
我的问题是在“收到”的分配。我怎么知道什么是分配的大小?我必须首先发送/接收每个数组的大小吗?
基于下面的建议,我会
data_array = numpy.ones(rank + 3, dtype=int)
data_array *= rank + 5
print '[{}] data: {} ({})'.format(rank, data_array, type(data_array))
# make all processors aware of data array sizes
all_sizes = {rank: data_array.size}
gathered_all_sizes = comm_py.allgather(all_sizes)
for d in gathered_all_sizes:
all_sizes.update(d)
# prepare Gatherv as described by @francis
nbsum = 0
sendcounts = []
displacements = []
for p in xrange(size):
n = all_sizes[p]
displacements.append(nbsum)
sendcounts.append(n)
nbsum += n
if rank==0:
result = numpy.empty(nbsum, dtype=numpy.int)
else:
result = None
comm_py.Gatherv(data_array,[result, tuple(sendcounts), tuple(displacements), MPI.INT64_T], root=0)
print '[{}] gathered data: {}'.format(rank, result)
谢谢弗朗西斯。我不能直接使用你的代码,因为在我的情况下,每个处理器只知道它自己的数组大小。我已经添加了一个更新的代码构建您的Gatherv建议对我的问题。 –
不客气!请注意,'recvcounts','displs'和'recvtype'这两个参数只在根目录中有意义。请参阅https://www.open-mpi.org/doc/v1.8/man3/MPI_Gatherv.3.php。因此,很可能发送的项目数量的gather()'是足够的,'all_gather()'是过量的。尝试将一个空列表'[]'传递给'gatherv()'中的其他进程:它似乎工作。 – francis