MPI4Py вызывает ошибку при отправке/получении

Может ли кто-нибудь сказать мне, почему этот минимальный рабочий пример (MWE) жалуется на TypeError: expected a writeable buffer object?

MWE:

#!/usr/bin/env python
from mpi4py import MPI

# MPI Initialization
rank = MPI.COMM_WORLD.Get_rank()
comm = MPI.COMM_WORLD

if __name__ == '__main__':
   a = True
   if rank == 0:
      a = False
      comm.Send ( [ a, MPI.BOOL ], 1, 111 )
   if rank == 1:
      comm.Recv ([ a, MPI.BOOL], 0, 111 )

Ошибка:

Traceback (most recent call last):
  File "test.py", line 14, in <module>
    comm.Recv ([ a, MPI.BOOL], 0, 111 )
  File "Comm.pyx", line 143, in mpi4py.MPI.Comm.Recv (src/mpi4py.MPI.c:62980)
  File "message.pxi", line 323, in mpi4py.MPI.message_p2p_recv (src/mpi4py.MPI.c:22814)
  File "message.pxi", line 309, in mpi4py.MPI._p_msg_p2p.for_recv (src/mpi4py.MPI.c:22665)
  File "message.pxi", line 111, in mpi4py.MPI.message_simple (src/mpi4py.MPI.c:20516)
  File "message.pxi", line 51, in mpi4py.MPI.message_basic (src/mpi4py.MPI.c:19644)
  File "asbuffer.pxi", line 108, in mpi4py.MPI.getbuffer (src/mpi4py.MPI.c:6757)
  File "asbuffer.pxi", line 48, in mpi4py.MPI.PyObject_GetBufferEx (src/mpi4py.MPI.c:6081)
TypeError: expected a writeable buffer object
Traceback (most recent call last):
  File "test.py", line 12, in <module>
    comm.Send ( [ a, MPI.BOOL ], 1, 111 )
  File "Comm.pyx", line 132, in mpi4py.MPI.Comm.Send (src/mpi4py.MPI.c:62796)
  File "message.pxi", line 318, in mpi4py.MPI.message_p2p_send (src/mpi4py.MPI.c:22744)
  File "message.pxi", line 301, in mpi4py.MPI._p_msg_p2p.for_send (src/mpi4py.MPI.c:22604)
  File "message.pxi", line 111, in mpi4py.MPI.message_simple (src/mpi4py.MPI.c:20516)
  File "message.pxi", line 51, in mpi4py.MPI.message_basic (src/mpi4py.MPI.c:19644)
  File "asbuffer.pxi", line 108, in mpi4py.MPI.getbuffer (src/mpi4py.MPI.c:6757)
  File "asbuffer.pxi", line 50, in mpi4py.MPI.PyObject_GetBufferEx (src/mpi4py.MPI.c:6093)

===================================================================================
=   BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
=   EXIT CODE: 1
=   CLEANING UP REMAINING PROCESSES
=   YOU CAN IGNORE THE BELOW CLEANUP MESSAGES
===================================================================================
[proxy:0:0@raspi1] HYD_pmcd_pmip_control_cmd_cb (./pm/pmiserv/pmip_cb.c:886): assert (!closed) failed
[proxy:0:0@raspi1] HYDT_dmxu_poll_wait_for_event (./tools/demux/demux_poll.c:77): callback returned error status
[proxy:0:0@raspi1] main (./pm/pmiserv/pmip.c:206): demux engine error waiting for event
[mpiexec@raspi1] HYDT_bscu_wait_for_completion (./tools/bootstrap/utils/bscu_wait.c:76): one of the processes terminated badly; aborting
[mpiexec@raspi1] HYDT_bsci_wait_for_completion (./tools/bootstrap/src/bsci_wait.c:23): launcher returned error waiting for completion
[mpiexec@raspi1] HYD_pmci_wait_for_completion (./pm/pmiserv/pmiserv_pmci.c:217): launcher returned error waiting for completion
[mpiexec@raspi1] main (./ui/mpich/mpiexec.c:331): process manager error waiting for completion

person puk    schedule 15.10.2013    source источник


Ответы (3)


Я не эксперт по MPI, но мне интересно, не совместим ли логический тип данных в numpy с логическим типом данных в C? Возможно, это и является причиной ошибки. (Не доказательство, а некоторые доказательства: http://docs.scipy.org/doc/numpy/reference/arrays.scalars.html#arrays-scalars-built-in и https://cython.readthedocs.org/en/last/src/tutorial/numpy.html)

puk, как вы заметили, одним из решений является передача данных в виде объектов python с помощью функций sendsend и recv (с строчными буквами s и r) (http://mpi4py.scipy.org/docs/usrman/tutorial.html). «Под капотом» mpi4py использует для этого pickle, поэтому может быть отправлен любой общий объект Python.

Моя основная причина ответить — опубликовать альтернативное решение с использованием массивов целых чисел, где 0 соответствует True, а 1 — False:

#!/usr/bin/env python
import numpy as np
from mpi4py import MPI

# MPI Initialization
rank = MPI.COMM_WORLD.Get_rank()
comm = MPI.COMM_WORLD

if __name__ == '__main__':
    a=np.array([0,])
    if rank == 0:
        a[0]=1
        comm.Send( [ a, MPI.INT ], 1, tag=111 )
        print rank,a
    if rank == 1:
        comm.Recv([ a, MPI.INT], 0, tag=111 )
        print rank,a

на случай, если кто-то захочет воспользоваться преимуществами более быстрых (согласно mpi4py docs) массивов numpy.

person amd    schedule 02.04.2014

Я понятия не имею, почему я получаю вышеуказанную ошибку, поэтому, если кто-нибудь знает, ответьте, и я приму ее. При этом я могу заставить код работать, если вместо этого использую этот стиль (старый код закомментирован):

MWE:

#!/usr/bin/env python
from mpi4py import MPI

# MPI Initialization
rank = MPI.COMM_WORLD.Get_rank()
comm = MPI.COMM_WORLD

if __name__ == '__main__':
   a = True
   if rank == 0:
      a = False
      # comm.Send ( [ a, MPI.BOOL ], dest=1, tag=111 )
      comm.send ( a, dest=1, tag=111 )
   if rank == 1:
      # comm.Recv ([ a, MPI.BOOL], dest=0, tag=111 )
      a = comm.recv (source=0, tag=111 )
person puk    schedule 15.10.2013
comment
Ваш проблемный код отличается в ваших двух примерах. comm.Send ( [ a, MPI.BOOL ], 1, 111 ) против # comm.Send ( [ a, MPI.BOOL ], dest=1, tag=111 ) Помогло ли решить вашу проблему простое добавление меток полей? - person kraffenetti; 15.10.2013
comment
Может поэтому. Обратите внимание, что сначала я использовал send, и он разбился, затем Send разбился, затем я вернулся к send, и все заработало. Я предполагаю, что метки полей являются тем, что имело значение. Позвольте мне перепроверить - person puk; 15.10.2013
comment
@kraffenetti Я только что попробовал еще раз, используя версии Send/Recv в верхнем регистре, и я исправил dest на source во второй строке комментария, и я все еще получил ту же ошибку. - person puk; 15.10.2013
comment
Похоже, что mpi4py ожидает объект провайдера буфера в вызовах Send/Recv в верхнем регистре. Поскольку в вашем примере вы используете общие объекты Python, вы должны придерживаться вызовов в нижнем регистре. mpi4py.scipy.org/docs/usrman/tutorial.html - person kraffenetti; 15.10.2013

Функции верхнего регистра MPI принимают такие объекты, как масло, такие как массивы NumPy в python. Функции нижнего регистра используют pickle, чтобы иметь возможность отправлять объекты.

http://mpi4py.readthedocs.org/en/latest/tutorial.html

person Jorge Silva    schedule 10.11.2015