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
是否可以使用MPI从Fortran程序向Python发送数据?_Python_Fortran_Mpi_Openmpi - Fatal编程技术网

是否可以使用MPI从Fortran程序向Python发送数据?

是否可以使用MPI从Fortran程序向Python发送数据?,python,fortran,mpi,openmpi,Python,Fortran,Mpi,Openmpi,我正在开发一种建模波浪能转换器的工具,我需要将两个软件包相互耦合。一个程序用FORTRAN编写,另一个程序用C++编写。我需要在每个时间步把FORTRAN程序的信息发送给C++程序。然而,数据首先需要在Python中处理,然后才被发送到C++程序。我收到了一个使用MPI在程序之间传输数据的提示 我现在试图将一个简单的字符串从Fortran代码发送到Python,但是Python代码在receive命令处卡住了 我的Fortran代码如下所示: USE GlobalVariables

我正在开发一种建模波浪能转换器的工具,我需要将两个软件包相互耦合。一个程序用FORTRAN编写,另一个程序用C++编写。我需要在每个时间步把FORTRAN程序的信息发送给C++程序。然而,数据首先需要在Python中处理,然后才被发送到C++程序。我收到了一个使用MPI在程序之间传输数据的提示

我现在试图将一个简单的字符串从Fortran代码发送到Python,但是Python代码在receive命令处卡住了

我的Fortran代码如下所示:

      USE GlobalVariables
      USE MPI
      IMPLICIT NONE

      CHARACTER(LEN=10):: astring
      INTEGER :: comm, rank, size, mpierr

      ! Initialize MPI on first timestep
      IF(tstep .LT. 2) THEN
        call MPI_INIT(mpierr)
      ENDIF

      ! make string to send to python
      astring = "TEST"

      ! MPI Test
      call MPI_Comm_size(MPI_COMM_WORLD, size, mpierr)
      call MPI_Comm_rank(MPI_COMM_WORLD, rank, mpierr)

      ! Send message to python
      CALL MPI_SEND(astring, len(astring), MPI_CHARACTER, 0, 22, MPI_COMM_WORLD, mpierr)
      print *, 'MPI MESSAGE SENT  ', mpierr

      ! Initialize MPI on first timestep
      IF(tstep .EQ. Nsteps-1) THEN
        call MPI_FINALIZE(mpierr)
        print *, 'MPI FINALIZED!'
      ENDIF
我的Python代码如下所示:

    from mpi4py import MPI
    import numpy as np
    import subprocess as sp
    import os

    # Start OW3D_SPH in the background and send MPI message
    os.chdir('OW3D_run')
    args = ['OceanWave3D_SPH','OW3D.inp']
    pid = sp.Popen(args,shell=False)
    os.chdir('..')

    # Check if MPI is initialized
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()

    # Receive message from fortran
    test = comm.recv(source=0, tag=22)

    # Let the program end
    output = pid.communicate()

    with open('test.txt','w') as f:
        f.write(test)
Python代码永远不会通过MPI receive命令,也不会完成。Fortran代码完成并正确打印“MPI FINALIZED”消息


我看不出我哪里做错了什么,消息从进程0发送到进程0,带有标记22,并在两个代码中使用
MPI\u COMM\u WORLD

我不会为此使用MPI(除非明确要求并行执行代码)。如果你的目标是连接在Fortran、C++和Python中编写的例程,那么我建议在Python中编写(main)连接部分,同时为FORTRAN和C++例程创建适配器,以便将它们导入Python。然后,您可以管理主Python程序中的所有函数调用,并根据需要发送数据

查看以下链接:

在Python中运行Fortran代码
  • f2py
    现在附带了
    numpy
    ,允许您将Fortran源代码编译成Python字节码
在Python中运行C++代码

当源和目标都是不同的程序时,您当然不能同时拥有源和目标0。你说“从进程0到进程0”,但你显然有两个不同的进程!其中一个有一些不同的秩号,但是您没有显示实际的
mpirun
命令,因此很难说哪个是哪个

澄清:MPI_COM_WORLD是在MPI运行或等效程序中执行的所有进程的通信器。你必须离开简单的心灵图景,第一个Python进程是等级0,第一个FORTRAN进程是等级0,第一个C++是等级0…< /P> 如果你这样做

mpirun -n 1 python main.py : -n 1 ./fortran_main : -n 1 ./c++_main

在MPIYCOMSOLL世界中,Python程序将为秩0,FORTRAN过程将为秩1,C++将为秩2。您可以创建仅在Python子集或FORTRAN子集或C++一个本地通信器,并且每个级别都有0级,但这将在不同的通信器中编号,而不是在MPIYCOMLWord中。

< P>如果您要在同一MPI作业中同时启动FORTRAN程序和Python程序,您必须使用以下内容:

mpiexec -n 1 fortran_program : -n 1 python main.py
Fortran程序将成为MPI等级0,Python程序将成为MPI等级1。您还可以启动每个可执行文件中的多个,例如:

mpiexec -n 2 fortran_program : -n 4 python main.py
等级0和1来自Fortran程序,等级2到5来自Python程序

还要注意的是,
comm.recv()
和mpi4py中以小写字母开头的其他通信方法(
comm.send()
comm.irecv()
,等等)在后台使用Pickle,并实际操作序列化Python对象。这与Fortran代码发送的字符数组不兼容。您必须使用以大写字母开头的通信方法(
comm.Send()
comm.Recv()
,等等),这些方法在NumPy数组上运行并接收显式类型信息。不幸的是,我的Python fu很弱,现在无法提供完整的工作示例,但MPI部分应该是这样的(未经验证的代码):


在Fortran代码中,您必须指定目标秩为1(在运行一个Fortran可执行文件和一个Python可执行文件的情况下)。

MPI进程可以使用此函数生成进程。在Python程序中,此函数是通信器的一种方法:
comm.spawn()
。有关示例,请参见生成的进程根据可执行文件运行,该可执行文件可以是另一个python程序、c/c++/fortran程序或任何您想要的程序。然后,内部通信程序可以定义主进程和生成进程之间的内部通信程序,如中所执行,主进程和派生进程可以自由通信而不受任何限制。

让我们介绍一个Python/c示例。Python代码生成进程并接收一个字符:

从MPI4p导入MPI
导入系统
进口numpy
'''
slavec是从slave.c开始构建的可执行文件
'''
#Spawing运行可执行文件的进程
#sub_comm是MPI内部通讯器
sub_comm=MPI.comm_SELF.Spawn('slavec',args=[],maxprocs=1)
#common_comm是一个跨python进程和派生进程的内部通信程序。python进程和c进程之间现在可以进行所有类型的集体通信(Bcast…)
公共通信=子通信合并(假)
#打印“公共通信中的父级”,公共通信获取等级(),“of”,公共通信获取大小()
data=numpy.arange(1,dtype='int8')
公共通信记录([数据,MPI.CHAR],源=1,标记=0)
打印“Python从C:收到的消息”,数据
#需要断开共享通讯器才能完成生成的进程。
公共通信断开()
子通信断开()
由mpicc slave.C-o slavec-Wall编译的C代码使用合并的通信器发送字符:

#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
int等级、大小;
MPI_Comm parentcomm、intracomm;
MPI_Init(&argc,&argv);
//MPI通信等级(MPI通信世界和等级);
MPI_Comm_get_parent(&parentcomm);
if(parentcomm==MPI_COMM_NULL){fprintf(stderr,“模块1:我应该是生成的进程!”);退出(1);}
MPI\U内部通信合并(pa)
# Create an MPI status object
status = MPI.Status()
# Wait for a message without receiving it
comm.Probe(source=0, tag=22, status=status)
# Check the length of the message
nchars = status.Get_count(MPI.CHARACTER)
# Allocate a big enough data array of characters
data = np.empty(nchars, dtype='S')
# Receive the message
comm.Recv([data, MPI.CHARACTER], source=0, tag=22)
# Construct somehow the string out of the individual chars in "data"