2013-10-15 64 views
2

有人可以告訴我爲什麼這個最小的工作示例(MWE)抱怨TypeError: expected a writeable buffer objectMPI4Py導致發送/接收錯誤

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:[email protected]] HYD_pmcd_pmip_control_cmd_cb (./pm/pmiserv/pmip_cb.c:886): assert (!closed) failed 
[proxy:0:[email protected]] HYDT_dmxu_poll_wait_for_event (./tools/demux/demux_poll.c:77): callback returned error status 
[proxy:0:[email protected]] main (./pm/pmiserv/pmip.c:206): demux engine error waiting for event 
[[email protected]] HYDT_bscu_wait_for_completion (./tools/bootstrap/utils/bscu_wait.c:76): one of the processes terminated badly; aborting 
[[email protected]] HYDT_bsci_wait_for_completion (./tools/bootstrap/src/bsci_wait.c:23): launcher returned error waiting for completion 
[[email protected]] HYD_pmci_wait_for_completion (./pm/pmiserv/pmiserv_pmci.c:217): launcher returned error waiting for completion 
[[email protected]] main (./ui/mpich/mpiexec.c:331): process manager error waiting for completion 

回答

1

我不知道爲什麼我收到上述錯誤,所以如果有人不知道,請回答我能接受。話雖這麼說,我可以得到的代碼,如果我用這個代替風格的工作(舊代碼註釋掉):

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) 
+0

您的問題代碼在您的2個示例中有所不同。 'comm.Send([a,MPI.BOOL],1,111)' 與 '#com.Send([a,MPI.BOOL],dest = 1,tag = 111)' 現場標籤解決您的問題? – kraffenetti

+0

這可能是爲什麼。請注意,我先使用'send'並且它崩潰了,然後'發送'崩潰了,然後我又回到'send'並且它工作。我想現場標籤**是**造成差異的原因。讓我仔細檢查 – puk

+0

@kraffenetti我只是使用大寫版本'Send/Recv'重新嘗試一次,並且在第二條註釋行中將'dest'固定爲'source',並且I **仍然**一樣錯誤 – puk

2

我不是MPI的專家,但我不知道如果numpy中的布爾數據類型與C中的布爾數據類型不兼容?也許這是導致錯誤的原因。 (沒有證據,但一些證據:http://docs.scipy.org/doc/numpy/reference/arrays.scalars.html#arrays-scalars-built-inhttps://cython.readthedocs.org/en/latest/src/tutorial/numpy.html

PUK,正如你指出,一個解決方案是將數據作爲使用send發送和recv(用小寫字母S和R)Python對象傳遞函數(http://mpi4py.scipy.org/docs/usrman/tutorial.html)。 「在引擎蓋下,」mpi4py使用pickle,因此可以發送任何通用的python對象。

我的主要原因回答是使用整數數組發佈一個替代的解決方案,與對應於True和1爲False 0:

#!/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數組。