2016-11-05 53 views
1

我有一個進程運行一個名爲t1.py的程序,它產生了3個其他進程,所有進程都運行t2.py。我想從生成的進程中以等級0向其他兩個衍生進程廣播一個值。但是,當調用bcast時,程序會阻塞。任何想法爲什麼發生這種情況我該如何解決它?mpi4py:在產生的進程之間進行通信

t1.py

from mpi4py import MPI 
import sys 

sub_comm = MPI.COMM_SELF.Spawn(sys.executable, args=['t2.py'], maxprocs=3) 
print 'hi' 

t2.py

from mpi4py import MPI 

comm = MPI.Comm.Get_Parent() 

print 'ho ', comm.Get_rank() 
a = comm.bcast(comm.Get_rank(), root=0) 
print a 

輸出

hi 
ho 2 
ho 0 
ho 1 
+2

我依稀記得MPISpawn相反,我們正在使用的幀內傳播者(或其他方式返回間通訊回合)。但是,您可以將一種類型轉換爲另一種類型。請參考MPI標準。 –

+0

你曾經叫過MPI_Finalize()嗎?在所有過程中? –

+1

我猜父程序必須參與廣播。 –

回答

1

如果你只是想孩子的交談對方,你可以使用MPI.COMM_WORLD

a = MPI.COMM_WORLD.bcast(MPI.COMM_WORLD.Get_rank(), root=0) 

通過打印MPI.COMM_WORLD.Get_rank(), ' of ',MPI.COMM_WORLD.Get_size(),您可以檢查孩子的MPI.COMM_WORLD僅限於孩子。

現在,讓我們來探討爲什麼如果commcomm=MPI.Comm.Get_parent()獲得comm.bcast(...)失敗的原因。事實上,通過查看這個傳播者的規模和排名,它看起來非常類似於MPI.COMM_WORLD但是,相反,commMPI.COMM_WORLD有很大不同:它是intercommunicator。更確切地說,這是父母與孩子交談的方式。可以使用集體通信,但是父母及其子女的所有過程都必須調用該功能。請認真閱讀MPI standards,特別是關於Intercommunicator集體操作的第5.2.2和5.2.3節。關於bcast(),MPI.ROOTMPI.PROC_NULL被用來代替廣播公司的等級root來指定方向(父母對孩子的父母)和發送過程。最後,通過使用Merge()(對應於MPI_Intercomm_merge()),可以在互通器的基礎上定義內部通信器。在這個內部通訊員中,父母和孩子不屬於兩個不同的羣體:像往常一樣,他們是以獨特的等級爲特徵的過程。

這裏是t1.py和t2.py的修改版本,其中執行intercommunicator的bcast()。然後,通信器是Merge(),並且產生的內部通信器上的bcast()按照慣例調用。

t1.py

from mpi4py import MPI 
import sys 

sub_comm = MPI.COMM_SELF.Spawn(sys.executable, args=['t2.py'], maxprocs=3) 

val=42 
sub_comm.bcast(val, MPI.ROOT) 

common_comm=sub_comm.Merge(False) 
print 'parent in common_comm ', common_comm.Get_rank(), ' of ',common_comm.Get_size() 
#MPI_Intercomm_merge(parentcomm,1,&intracomm); 

val=13 
c=common_comm.bcast(val, root=0) 
print "value from rank 0 in common_comm", c 

t2.py

from mpi4py import MPI 

comm = MPI.Comm.Get_parent() 

print 'ho ', comm.Get_rank(), ' of ',comm.Get_size(),' ', MPI.COMM_WORLD.Get_rank(), ' of ',MPI.COMM_WORLD.Get_size() 
a = MPI.COMM_WORLD.bcast(MPI.COMM_WORLD.Get_rank(), root=0) 
print "value from other child", a 

print "comm.Is_inter", comm.Is_inter() 
b = comm.bcast(comm.Get_rank(), root=0) 
print "value from parent", b 

common_comm=comm.Merge(True) 
print "common_comm.Is_inter", common_comm.Is_inter() 
print 'common_comm ', common_comm.Get_rank(), ' of ',common_comm.Get_size() 

c=common_comm.bcast(0, root=0) 
print "value from rank 0 in common_comm", c