Дочерние процессы Fortran (или C ++ или python), порожденные из python с использованием Spawn (), не будут отключаться при объединении внутренних и внутренних коммуникаторов. - PullRequest
3 голосов
/ 25 апреля 2020

Я пытаюсь распараллелить небольшую часть моего python кода в Fortran90. Итак, для начала я пытаюсь понять, как работает функция порождения.

Во-первых, я пытался порождать дочерний процесс в python от python родителя. Я использовал пример управления процессами Dynami c из руководства mpi4py . Все работало нормально В этом случае, насколько я понимаю, используется только межкоммуникатор между родительским процессом и дочерним процессом.

Затем я перешел к примеру для порождения дочернего процесса в fortran90 из * 1026. * родитель. Для этого я использовал пример из предыдущего поста в stackoverflow. Код python (master.py), который порождает дочерний элемент fortran, выглядит следующим образом:

from mpi4py import MPI
import numpy

'''
slavef90 is an executable built starting from slave.f90
'''
# Spawing a process running an executable
# sub_comm is an MPI intercommunicator
sub_comm = MPI.COMM_SELF.Spawn('slavef90', args=[], maxprocs=1)
# common_comm is an intracommunicator accross the python process and the spawned process.
# All kind sof collective communication (Bcast...) are now possible between the python process and the c process
common_comm=sub_comm.Merge(False)
print('parent in common_comm ', common_comm.Get_rank(), ' of  ', common_comm.Get_size())
data = numpy.arange(1, dtype='int32')
data[0]=42
print("Python sending message to fortran: {}".format(data))
common_comm.Send([data, MPI.INT], dest=1, tag=0)

print("Python over")
# disconnecting the shared communicators is required to finalize the spawned process.
sub_comm.Disconnect()
common_comm.Disconnect()

Соответствующий код fortran90 (slave.f90), в котором создаются дочерние процессы, выглядит следующим образом:

  program test
  !
  implicit none
  !
  include 'mpif.h'
  !
  integer :: ierr,s(1),stat(MPI_STATUS_SIZE)
  integer :: parentcomm,intracomm
  !
  call MPI_INIT(ierr)
  call MPI_COMM_GET_PARENT(parentcomm, ierr)
  call MPI_INTERCOMM_MERGE(parentcomm, 1, intracomm, ierr)
  call MPI_RECV(s, 1, MPI_INTEGER, 0, 0, intracomm,stat, ierr)
  print*, 'fortran program received: ', s
  call MPI_COMM_DISCONNECT(intracomm, ierr)
  call MPI_COMM_DISCONNECT(parentcomm, ierr)
  call MPI_FINALIZE(ierr)
  endprogram test

Я скомпилировал код fortran90, используя mpif90 slave.f90 -o slavef90 -Wall. Я обычно запускал код python, используя python master.py. Я могу получить желаемый результат, но порожденные процессы не будут отключаться, т. Е. Любые операторы после команд Disconnect (call MPI_COMM_DISCONNECT(intracomm, ierr) и call MPI_COMM_DISCONNECT(parentcomm, ierr)) не будут выполняться в коде Fortran (и, следовательно, любые операторы после Команды разъединения в коде python также не выполняются), и мой код не завершится в терминале.

В этом случае, насколько я понимаю, интер-коммуникатор и интра-коммуникатор объединены так, что дочерние процессы и родительские процессы больше не две разные группы. И, кажется, есть некоторые проблемы при их отключении. Но я не могу найти решение. Я попытался воспроизвести код fortran90, где дочерние процессы создаются в C ++, а также в python, и столкнулись с той же проблемой. Любая помощь приветствуется. Спасибо.

1 Ответ

1 голос
/ 28 апреля 2020

Обратите внимание, что ваш скрипт python сначала отключает внутренний коммуникатор, а затем внутренний коммуникатор, но ваша программа Fortran сначала отключает внутренний коммуникатор, а затем внутренний коммуникатор.

Я могу запустить этот тест на ма c (Open MPI и mpi4py установлен brew) после исправления порядка и освобождения внутреннего коммуникатора.

Вот мой master.py

#!/usr/local/Cellar/python@3.8/3.8.2/bin/python3

from mpi4py import MPI
import numpy

'''
slavef90 is an executable built starting from slave.f90
'''
# Spawing a process running an executable
# sub_comm is an MPI intercommunicator
sub_comm = MPI.COMM_SELF.Spawn('slavef90', args=[], maxprocs=1)
# common_comm is an intracommunicator accross the python process and the spawned process.
# All kind sof collective communication (Bcast...) are now possible between the python process and the c process
common_comm=sub_comm.Merge(False)
print('parent in common_comm ', common_comm.Get_rank(), ' of  ', common_comm.Get_size())
data = numpy.arange(1, dtype='int32')
data[0]=42
print("Python sending message to fortran: {}".format(data))
common_comm.Send([data, MPI.INT], dest=1, tag=0)

print("Python over")
# free the (merged) intra communicator
common_comm.Free()
# disconnect the inter communicator is required to finalize the spawned process.
sub_comm.Disconnect()

и мой slave.f90

  program test
  !
  implicit none
  !
  include 'mpif.h'
  !
  integer :: ierr,s(1),stat(MPI_STATUS_SIZE)
  integer :: parentcomm,intracomm
  integer :: rank, size
  !
  call MPI_INIT(ierr)
  call MPI_COMM_GET_PARENT(parentcomm, ierr)
  call MPI_INTERCOMM_MERGE(parentcomm, .true., intracomm, ierr)
  call MPI_COMM_RANK(intracomm, rank, ierr)
  call MPI_COMM_SIZE(intracomm, size, ierr)
  call MPI_RECV(s, 1, MPI_INTEGER, 0, 0, intracomm,stat, ierr)
  print*, 'fortran program', rank, ' / ', size, ' received: ', s
  print*, 'Slave frees intracomm'
  call MPI_COMM_FREE(intracomm, ierr)
  print*, 'Slave disconnect intercomm'
  call MPI_COMM_DISCONNECT(parentcomm, ierr)
  print*, 'Slave finalize'
  call MPI_FINALIZE(ierr)
  endprogram test
...