Дочерние процессы Fortran (или C++ или python), созданные из python с помощью Spawn(), не будут отключаться при объединении внутренних и внутренних коммуникаторов.

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

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

Затем я перешел к примеру порождения дочернего процесса в fortran90 из родительского процесса на python. Для этого я использовал пример из одного из предыдущий пост в 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)) не будут выполняться в коде фортрана (и, следовательно, любые операторы после команд Disconnect в код Python также не выполняется), и мой код не завершается в терминале.

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


person AdhityaRavi    schedule 25.04.2020    source источник
comment
Используйте более общие языковые теги fortran питон. При необходимости вы всегда можете добавить тег версии. Смотрите описание тега при добавлении. Рекомендуется использовать модуль MPI use mpi вместо включения файла mpif.h. Тогда компилятор может проверить многие вещи и предупредить вас или остановить вас от неправильных действий.   -  person Vladimir F    schedule 25.04.2020
comment
Что, если вы MPI_Comm_free() используете внутренний (также известный как объединенный) коммуникатор и MPI_Comm_discomnect() только интеркоммуникатор?   -  person Gilles Gouaillardet    schedule 25.04.2020
comment
@GillesGouaillardet Да, я пытался освободить внутренние коммуникаторы вместо их отключения. К сожалению, проблема все еще существует.   -  person AdhityaRavi    schedule 25.04.2020
comment
Вы пробовали написать спаунер на C? (чтобы убедиться, что ошибка не исходит из библиотеки MPI)   -  person Gilles Gouaillardet    schedule 25.04.2020
comment
Кроме того, вы можете попробовать запустить mpirun -np 1 python master.py   -  person Gilles Gouaillardet    schedule 25.04.2020
comment
@GillesGouaillardet Спасибо за предложения. Я попробовал mpirun предложение. К сожалению, это не сработало. Мне все еще нужно написать спаунер на C. Я также нашел открытый вопрос в той же теме. Мне это не очень помогло. К счастью, (пока) я могу распараллелить свой код без использования Merge(). Все работает гладко, пока родительский и дочерний процессы хранятся как отдельная группа.   -  person AdhityaRavi    schedule 26.04.2020
comment
Из любопытства, на какой библиотеке MPI (поставщик и версия) построен ваш mpi4py?   -  person Gilles Gouaillardet    schedule 27.04.2020
comment
Используемая библиотека MPI — Open MPI 2.1.1.   -  person AdhityaRavi    schedule 27.04.2020


Ответы (1)


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

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

Вот мой master.py

#!/usr/local/Cellar/[email protected]/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
person Gilles Gouaillardet    schedule 28.04.2020
comment
Спасибо большое!!!. Это значительно облегчает мне жизнь сейчас. Не могу поверить, что совершил глупую ошибку, поменяв местами команды Disconnect(). В любом случае, спасибо еще раз! - person AdhityaRavi; 28.04.2020
comment
В заключение, не могли бы вы сказать мне, почему код зависает, если мы отключаем внутреннюю связь вместо ее освобождения? Я понял (что может быть неверным) из MPI-справочник, что Disconnect() предпочтительнее Free(). - person AdhityaRavi; 28.04.2020
comment
Я не знаю точно, но я слышал, что MPI_Comm_disconnect() может быть неправильно реализован в Open MPI, и это может объяснить зависание. - person Gilles Gouaillardet; 28.04.2020
comment
меня устраивает. Вы обновили мастер, чтобы он отправлял сообщение всем детям? если нет, дети, кроме первого, застрянут на MPI_Recv(). также обратите внимание, что Open MPI 2.1.1 больше не поддерживается, и вам следует подумать об обновлении до более новой версии, например 4.0.3. - person Gilles Gouaillardet; 28.04.2020
comment
да. Понятно!. Вы правы, я обновляю свой Open MPI, пока комментирую. Спасибо за поддержку!. - person AdhityaRavi; 28.04.2020