Ошибка сегментации с использованием mpi4py

Я использую mpi4py для распределения задачи обработки по кластеру ядер. Мой код выглядит так:

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

'''Perform processing operations with each processor returning 
   two arrays of equal size, array1 and array2'''

all_data1 = comm.gather(array1, root = 0)
all_data2 = comm.gather(array2, root = 0)

Это возвращает следующую ошибку:

SystemError: Negative size passed to PyString_FromStringAndSize

Я считаю, что эта ошибка означает, что массив данных, хранящихся в all_data1, превышает максимальный размер массива в Python, что вполне возможно.

Я попытался сделать это небольшими частями, как показано ниже:

comm.isend(array1, dest = 0, tag = rank+1)
comm.isend(array2, dest = 0, tag = rank+2)
if rank == 0:
    for proc in xrange(size):
        partial_array1 = comm.irecv(source = proc, tag = proc+1)
        partial_array2 = comm.irecv(source = proc, tag = proc+2)

но это возвращает следующую ошибку.

[node10:20210] *** Process received signal ***
[node10:20210] Signal: Segmentation fault (11)
[node10:20210] Signal code: Address not mapped (1)
[node10:20210] Failing at address: 0x2319982b

за которым следует целая куча неразборчивой информации о пути и финальное сообщение:

mpirun noticed that process rank 0 with PID 0 on node node10 exited on signal 11 (Segmentation fault).

Кажется, это происходит независимо от того, сколько процессоров я использую.

Для подобных вопросов в C решение, похоже, слегка меняет способ анализа аргументов в вызове recv. В Python синтаксис отличается, поэтому я был бы признателен, если бы кто-нибудь мог прояснить, почему появляется эта ошибка и как ее исправить.


person berkelem    schedule 16.11.2015    source источник
comment
Не могли бы вы запаковать и заархивировать свой массив с одной стороны, а затем заархивировать/распаковать его с другой стороны?   -  person Ashalynd    schedule 17.11.2015
comment
Поправьте меня, если я ошибаюсь, но разве не так работает mpi4py? Насколько я понимаю, передаваемые данные маринуются «под капотом».   -  person berkelem    schedule 17.11.2015
comment
По идее, должно... Вы вообще можете что-нибудь отправить с одной стороны на другую? Все ли сущности в кластере похожи друг на друга?   -  person Ashalynd    schedule 17.11.2015
comment
Я только что попытался отправить тестовый объект и распечатать его на другой стороне, но он отображается как <mpi4py.MPI.Request object at 0x7f7b125690e0> Как мне распаковать этот объект? Это может быть причиной проблемы.   -  person berkelem    schedule 17.11.2015
comment
как отправить и распечатать?   -  person Ashalynd    schedule 17.11.2015
comment
Я немного поиграл и решил свою первоначальную проблему, используя comm.Isend([array1, MPI.FLOAT], dest = 0, tag = rank + 1) и comm.Irecv([partial_array1, MPI.FLOAT], source = proc, tag = proc + 1) после инициализации пустого приемного буфера. Я до сих пор не понимаю, как и почему comm.Isend() и comm.isend() отличаются, поэтому любое понимание будет оценено. Любопытно, что я все еще получаю ту же ошибку ошибки сегментации, даже после того, как все процессоры успешно завершили код. Что может быть причиной этого?   -  person berkelem    schedule 17.11.2015
comment
Трудно сказать, не видя больше вашего кода, почему вы получаете ошибку сегментации (может быть что угодно).   -  person Ashalynd    schedule 17.11.2015
comment
Относительно разницы: согласно документации (pythonhosted.org/mpi4py/usrman/tutorial .html?highlight=isend), версии нижнего регистра используются для передачи общих объектов Python и возвращают экземпляры запроса (и вам нужно подождать или проверить завершение, чтобы получить результат), в то время как версии верхнего регистра возвращают объекты буфера (которые кортежи данных + информация о типе). Эти вызовы являются неблокирующими, поэтому убедитесь, что вы не изменяете буфер до завершения отправки/получения.   -  person Ashalynd    schedule 17.11.2015


Ответы (1)


Мне удалось решить проблему, с которой я столкнулся, выполнив следующие действия.

if rank != 0:
    comm.Isend([array1, MPI.FLOAT], dest = 0, tag = 77) 
    # Non-blocking send; allows code to continue before data is received.

if rank == 0:
    final_array1 = array1
    for proc in xrange(1,size):
        partial_array1 = np.empty(len(array1), dtype = float)
        comm.Recv([partial_array1, MPI.FLOAT], source = proc, tag = 77) 
        # A blocking receive is necessary here to avoid a Segfault.

        final_array1 += partial_array1

if rank != 0:
    comm.Isend([array2, MPI.FLOAT], dest = 0, tag = 135)

if rank == 0:
    final_array2 = array2
    for proc in xrange(1,size):
        partial_array2 = np.empty(len(array2), dtype = float)
        comm.Recv([partial_array2, MPI.FLOAT], source = proc, tag = 135)

        final_array2 += partial_array2

comm.barrier() # This barrier call resolves the Segfault.
if rank == 0:
    return final_array1, final_array2
else:
    return None
person berkelem    schedule 18.11.2015