2016-11-05 4 views
1

Ich habe einen Prozess, der ein Programm namens t1.py ausführt, das 3 andere Prozesse hervorbringt, die alle t2.py ausführen. Ich möchte einen Wert aus dem erzeugten Prozess mit einem Rang von 0 an die beiden anderen erzeugten Prozesse senden. Wenn jedoch bcast aufgerufen wird, blockiert das Programm. Irgendeine Idee, warum das passiert? Und wie repariere ich es?mpi4py: Kommunikation zwischen erzeugten Prozessen

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 

Ausgang

hi 
ho 2 
ho 0 
ho 1 
+2

Ich erinnere mich schwach, dass MPISpawn gibt einen Inter-Communicator im Gegensatz zu den Intra-Kommunikatoren, die wir gewohnt sind (oder andersrum runden). Sie können jedoch einen Typ in den anderen konvertieren. Bitte konsultieren Sie dazu den MPI-Standard. –

+0

Rufen Sie jemals MPI_Finalize() an? In allen Prozessen? –

+1

Ich denke, der Elternprozess muss an der Sendung teilnehmen. –

Antwort

1

Wenn Sie nur die Childs miteinander reden wollen, können Sie MPI.COMM_WORLD verwenden:

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

Durch Drucken von MPI.COMM_WORLD.Get_rank(), ' of ',MPI.COMM_WORLD.Get_size() können Sie überprüfen, ob die Kinder MPI.COMM_WORLD auf die Kinder beschränkt ist.

Jetzt untersuchen wir den Grund, warum comm.bcast(...) fehlgeschlagen ist, wenn comm von comm=MPI.Comm.Get_parent() erhalten wird. Wenn man sich die Größe und die Ränge dieses Kommunikators anschaut, sieht es in der Tat sehr ähnlich zu MPI.COMM_WORLD aus. Aber im Gegensatz comm ist sehr verschieden von MPI.COMM_WORLD: es ist ein intercommunicator. Genauer gesagt ist es die Art, wie ein Elternteil mit seinen Kindern sprechen kann. Kollektive Kommunikationen können verwendet werden, aber alle Prozesse, sowohl der Vater als auch die Kinder, müssen die Funktion aufrufen. Bitte lesen Sie sorgfältig die MPI standards, insbesondere die Abschnitte 5.2.2 und 5.2.3 über Intercommunicator Collective Operations. In Bezug auf bcast(), MPI.ROOT und MPI.PROC_NULL werden anstelle des Rangs des Broadcasters root verwendet, um die Richtung (Eltern zu Kind des Kindes zu Eltern) und den Sendeprozess anzugeben. Schließlich kann ein Intra-Kommunikator auf der Basis eines Interkommunikators unter Verwendung von Merge() (entsprechend MPI_Intercomm_merge()) definiert werden. In diesem Intra- kommunikator gehören Eltern und Kinder nicht zwei verschiedenen Gruppen an: Sie sind wie üblich durch ihren einzigartigen Rang charakterisiert.

Hier sind die modifizierten Versionen von t1.py und t2.py, wo ein bcast() für einen Interkommunikator durchgeführt wird. Dann wird der Interkommunikator Merge() und ein bcast() über den resultierenden Intra-Communicator wie üblich aufgerufen.

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 
Verwandte Themen