У меня есть следующий MWE, использующий comm.Scatterv
и comm.Gatherv
для распределения массива 4D по заданному количеству ядер (size
)
import numpy as np
from mpi4py import MPI
import matplotlib.pyplot as plt
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
if rank == 0:
test = np.random.rand(411,48,52,40) #Create array of random numbers
outputData = np.zeros(np.shape(test))
split = np.array_split(test,size,axis = 0) #Split input array by the number of available cores
split_sizes = []
for i in range(0,len(split),1):
split_sizes = np.append(split_sizes, len(split[i]))
displacements = np.insert(np.cumsum(split_sizes),0,0)[0:-1]
plt.imshow(test[0,0,:,:])
plt.show()
else:
#Create variables on other cores
split_sizes = None
displacements = None
split = None
test = None
outputData = None
#Broadcast variables to other cores
test = comm.bcast(test, root = 0)
split = comm.bcast(split, root=0)
split_sizes = comm.bcast(split_sizes, root = 0)
displacements = comm.bcast(displacements, root = 0)
output_chunk = np.zeros(np.shape(split[rank])) #Create array to receive subset of data on each core, where rank specifies the core
print("Rank %d with output_chunk shape %s" %(rank,output_chunk.shape))
comm.Scatterv([test,split_sizes, displacements,MPI.DOUBLE],output_chunk,root=0) #Scatter data from test across cores and receive in output_chunk
output = output_chunk
plt.imshow(output_chunk[0,0,:,:])
plt.show()
print("Output shape %s for rank %d" %(output.shape,rank))
comm.Barrier()
comm.Gatherv(output,[outputData,split_sizes,displacements,MPI.DOUBLE], root=0) #Gather output data together
if rank == 0:
print("Final data shape %s" %(outputData.shape,))
plt.imshow(outputData[0,0,:,:])
plt.show()
Это создает четырехмерный массив случайных чисел и в принципе должен разделить его на size
ядер перед рекомбинацией. Я ожидал, что Scatterv
будет делиться по оси 0 (длина 411) в соответствии с начальными целыми числами и смещениями в векторах split_sizes
и displacements
. Однако я получаю ошибку при рекомбинации с Gatherv
(mpi4py.MPI.Exception: MPI_ERR_TRUNCATE: message truncated
) и график output_chunk на каждом ядре показывает, что большая часть входных данных была потеряна, поэтому кажется, что разделение не произошло по первой оси.
Мои вопросы: почему разделение не происходит по первой оси, как узнать, по какой оси происходит разделение, и можно ли изменить/указать, по какой оси это происходит?
comm.Scatterv
вероятно ничего не знает оnumpy
массиве, форме, размерах или шагах. В лучшем случае он может рассматриватьtest
как блок памяти. На самом деле это может быть только указатель на объект массива, а не на его буфер данных. Работает ли этот код с массивом 1d? Илиtest.flatten()
? - person hpaulj   schedule 16.03.2016