Если вы просто хотите, чтобы Чайлдс разговаривать друг с другом, вы можете использовать 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
я слабо помню, что MPISpawn возвращает Inter-коммуникатор, в отличие от интра-коммуникаторов, которые мы привыкли (или другим способом круглый). Однако вы можете преобразовать один тип в другой. Проконсультируйтесь со стандартом MPI. –
Вы когда-нибудь называли MPI_Finalize()? Во всех процессах? –
Я предполагаю, что родительский процесс должен принять участие в трансляции. –