Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Spawn()从python生成的Fortran子进程(或C+;+;或python)在合并内部和内部通讯器时不会断开连接_Python_Fortran_Mpi_Spawn_Mpi4py - Fatal编程技术网

使用Spawn()从python生成的Fortran子进程(或C+;+;或python)在合并内部和内部通讯器时不会断开连接

使用Spawn()从python生成的Fortran子进程(或C+;+;或python)在合并内部和内部通讯器时不会断开连接,python,fortran,mpi,spawn,mpi4py,Python,Fortran,Mpi,Spawn,Mpi4py,我正在尝试用Fortran90并行化python代码的一小部分。因此,作为一个开始,我试图了解产卵函数是如何工作的 首先,我尝试从python父进程派生python中的子进程。我使用了来自的动态流程管理示例。一切都很顺利。在这种情况下,据我所知,只使用父进程和子进程之间的intercommunicator 然后,我转到一个示例,该示例使用fortran90从python父进程派生子进程。为此,我使用了stackoverflow中的一个示例。生成fortran子级的python代码(master.

我正在尝试用Fortran90并行化python代码的一小部分。因此,作为一个开始,我试图了解产卵函数是如何工作的

首先,我尝试从python父进程派生python中的子进程。我使用了来自的动态流程管理示例。一切都很顺利。在这种情况下,据我所知,只使用父进程和子进程之间的intercommunicator

然后,我转到一个示例,该示例使用fortran90从python父进程派生子进程。为此,我使用了stackoverflow中的一个示例。生成fortran子级的python代码(master.py)如下所示:

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()
  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代码(slave.f90)如下所示:

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()
  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
我使用
mpif90 slave.f90-o slavef90-Wall
编译了fortran90代码。我使用
pythonmaster.py
正常运行python代码。我能够获得所需的输出,但是生成的进程不会断开连接,也就是说,断开连接命令(
call MPI\u COMM\u disconnect(intracom,ierr)
call MPI\u COMM\u disconnect(parentcomm,ierr)
)之后的任何语句都不会在fortran代码中执行(因此python代码中的Disconnect命令之后的任何语句也不会执行)并且我的代码不会在终端中终止


在这种情况下,据我所知,inter communicator和intra communicator被合并,这样子进程和父进程就不再是两个不同的组了。而且,在断开它们的连接时似乎出现了一些问题。但是,我无法找到解决方案。我尝试重新生成fortran90代码,其中子进程在C++和Python中也产生了同样的问题。任何帮助都是值得赞赏的。谢谢。

< P>注意,你的Python脚本首先断开了通信器,然后是内部通信程序,但是你的FORTRAN程序首先断开了内部通信器,然后断开了通信器。 修复顺序并释放内部通信器后,我能够在mac上运行此测试(
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

请使用更多通用语言标记。如有必要,您可以随时添加版本标记。添加时请参阅标记说明。建议使用MPI模块
use MPI
,而不是包含
mpif.h
文件。然后编译器可以检查许多内容并警告您或阻止您做错误的事情。如果您
MP怎么办I_Comm_free()
内部(也称为合并)通信器和
MPI_Comm_discomnect()
仅内部通信器?@GillesGouaillardet是的,我尝试释放内部通信器而不是断开它们。不幸的是,问题仍然存在。您是否尝试用C编写生成程序?(为了确保错误不是来自MPI库)另外,您可以试着运行
mpirun-np 1 python master.py
非常感谢!!!。这让我现在的生活轻松多了。我不敢相信我犯了愚蠢的错误,交换了
Disconnect()
命令。无论如何,再次感谢您!对于闭包,您能否告诉我,如果我们断开内部命令而不是释放它,为什么代码会冻结?我从中了解到(这可能是不正确的)
disconnect()
Free()
更可取。我不确定,但我听说了
MPI\u Comm\u disconnect()
可能无法在Open MPI中正确实现,这可以解释冻结的原因。它对我有效。您是否更新了主机,以便它向所有子项发送消息?如果不更新,则除第一个子项之外的子项将卡在
MPI\u Recv()上另外,注意打开MPI2.1.1不再支持,你应该考虑升级到最近的一个,比如4.0.3YES。得到它!你是对的,我正在升级我的代码>开放MPI < /代码>,我正在评论。谢谢你的支持!