comm.Scatter KeyError с mpi4py

Я новичок в MPI и mpi4py. У меня есть две проблемы со следующим кодом. Во-первых, данные ранга 0 не печатаются, в то время как данные типа «Нет» в других рангах печатаются.

Во-вторых, я получаю ошибку KeyError '0' от функции comm.Scatter(), которую не могу объяснить.

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

person blong    schedule 24.03.2017    source источник


Ответы (2)


Хотя я не могу воспроизвести вашу конкретную ошибку, проблема здесь в том, что на некорневых рангах d это ошибка с одним элементом None, поэтому n=1 и m будут фиктивными. Если вы не знаете размер на некорневых рангах, вам нужно сначала его транслировать:

if rank == 0:
    df = pickle.load(open('lipad0406.p', 'rb'))
    d = np.array(df, dtype=float)
    m = d.size / size
    comm.bcast(m)
else:
    d = None
    m = comm.bcast(None)

d_loc = np.zeros(m, dtype=float)

comm.Scatter(d,d_loc)

Также убедитесь, что типы данных совпадают.

person Zulan    schedule 28.03.2017

KeyError происходит потому, что Scatter не может обрабатывать данные любого типа, загружаемые из вашего входного файла.

Mpi4py предоставляет два типа коммуникационных функций, имена которых начинаются с заглавной буквы, например. Scatter и те, чьи имена начинаются со строчной буквы, например. scatter. Из документации Mpi4py:

В MPI для Python методы Bcast(), Scatter(), Gather(), Allgather() и Alltoall() экземпляров Comm обеспечивают поддержку коллективной связи буферов памяти. Варианты bcast(), scatter(), collect(), 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)

Кроме того, как сказал Зулан, вам нужно убедиться, что dtypes ваших массивов numpy d и d_loc совпадают, и что m передается процессам без ранга 0.

Запуск вашего кода в точности, за исключением замены df = pickle.load(open('lipad0406.p', 'rb')) на df = range(size), поскольку у меня нет и не может быть особых предположений о содержимом вашего файла, не перестает печатать d в процессе ранга-0, поэтому я могу только предположить, что эта конкретная проблема имеет какое-то отношение к загрузке файла.

Минимально измененная рабочая версия вашего кода, за исключением загрузки файла,

from mpi4py import MPI
import numpy as np

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

if rank == 0:
    df = range(size)
else:
    df = None

p = size

d = np.array(df)

n = d.size

m = comm.bcast(n/p)

d_loc = np.zeros(m)

d_loc = comm.scatter(d)

print "process", rank, "x:", d
print "process", rank, "x_local:", d_loc.size
person calavicci    schedule 07.08.2017