2016-11-05 5 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 возвращает Inter-коммуникатор, в отличие от интра-коммуникаторов, которые мы привыкли (или другим способом круглый). Однако вы можете преобразовать один тип в другой. Проконсультируйтесь со стандартом 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 ограничено дочерними элементами.

Теперь давайте расследуем причину, по которой comm.bcast(...) не удалось, если comm получено: comm=MPI.Comm.Get_parent(). Действительно, глядя на размер и ряды этого коммуникатора, он кажется очень похожим на MPI.COMM_WORLD. Но, наоборот, comm сильно отличается от MPI.COMM_WORLD: это intercommunicator. Точнее, именно так родитель может поговорить со своими детьми. Коллективные сообщения могут использоваться, но все процессы, как родительский, так и его дочерний, должны вызывать функцию. Пожалуйста, внимательно прочитайте MPI standards, в частности разделы 5.2.2 и 5.2.3, посвященные коллективным операциям между операторами. В отношении bcast(), MPI.ROOT и MPI.PROC_NULL используются вместо ранга вещателя root для указания направления (от родителя к дочернему положению от родителя к родительскому объекту) и процесса отправки. Наконец, интракоммуникатор может быть определен на основе межкоммуникатора с использованием Merge() (соответствует MPI_Intercomm_merge()). В этом интракоммуникаторе родители и дети не принадлежат к двум различным группам: это процессы, характеризующиеся своим уникальным рангом, как обычно.

Здесь приведены измененные версии t1.py и t2.py, где выполняется 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 
Смежные вопросы