Я хотел бы собрать содержимое массива numpy от всех процессоров до одного. Если все массивы имеют одинаковый размер, это работает. Однако я не вижу естественного способа выполнения одной и той же задачи для массивов прозависимого размера. Пожалуйста, обратите внимание на следующий код:Нечетные массивы numpy send/receive
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',' disps' и 'recvtype' имеют значение только у root. См. Https://www.open-mpi.org/doc/v1.8/man3/MPI_Gatherv.3.php. Следовательно, вполне вероятно, что 'gather()' количества отправленных элементов является достаточным и 'all_gather()' overkill. Попробуйте передать пустой список '[]' другим процессам в 'gatherv()': он работает. – francis