简体   繁体   English

在同一台计算机上的两个正在运行的fortran程序之间传输数据(实数和整数数组)的最佳方法是什么?

[英]What is the best way to transfer data (Real and Integer arrays) between two runnings fortran programs on the same machine?

We are currently using file I/O but need a better/faster way. 我们目前正在使用文件I / O,但需要更好/更快的方法。 Sample code would be appreciated. 示例代码将不胜感激。

By using files for transfer, you're already implementing a form of message passing, and so I think that would be the most natural fit for this sort of program. 通过使用文件进行传输,您已经在实现一种消息传递形式,因此,我认为这最适合此类程序。 Now, you could write something yourself that uses shared memory when available and something like TCP/IP when not - or you could just use a library that already does that, like MPI, which is widely available, works, will take advantage of shared memory if you are running on the same machine, but would then also extend to letting you run them on different machines entirely without you changing your code. 现在,您可以自己编写一些在可用时使用共享内存的东西,而在不使用时使用类似TCP / IP的东西-或者您可以使用已经做到这一点的库,例如MPI(可以广泛使用)可以利用共享内存如果您是在同一台计算机上运行,​​那么还可以扩展为让您完全在不同的计算机上运行它们而无需更改代码。

So as a simple example of one program sending data to a second and then waiting for data back, we'd have two programs as follows; 因此,作为一个简单的示例,一个程序将数据发送到第二个然后等待数据返回,我们将有两个程序如下: first.f90 第一.f90

program first

    use protocol
    use mpi
    implicit none
    real, dimension(n,m) :: inputdata
    real, dimension(n,m) :: processeddata
    integer :: rank, comsize, ierr, otherrank
    integer :: rstatus(MPI_STATUS_SIZE)


    call MPI_INIT(ierr)
    call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
    call MPI_COMM_SIZE(MPI_COMM_WORLD, comsize, ierr)

    if (comsize /= 2) then 
        print *,'Error: this assumes n=2!'
        call MPI_ABORT(1,MPI_COMM_WORLD,ierr)
    endif

    !! 2 PEs; the other is 1 if we're 0, or 0 if we're 1.
    otherrank = comsize - (rank+1)

    inputdata = 1.
    inputdata = exp(sin(inputdata))

    print *, rank, ': first: finished computing; now sending to second.'
    call MPI_SEND(inputdata, n*m, MPI_REAL, otherrank, firsttag, &
                  MPI_COMM_WORLD, ierr)
    print *, rank, ': first: Now waiting for return data...'
    call MPI_RECV(processeddata, n*m, MPI_REAL, otherrank, backtag, &
                  MPI_COMM_WORLD, rstatus, ierr)
    print *, rank, ': first: recieved data from partner.'

    call MPI_FINALIZE(ierr)

end program first

and second.f90: 和second.f90:

program second

    use protocol
    use mpi
    implicit none
    real, dimension(n,m) :: inputdata
    real, dimension(n,m) :: processeddata
    integer :: rank, comsize, ierr, otherrank
    integer :: rstatus(MPI_STATUS_SIZE)

    call MPI_INIT(ierr)
    call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
    call MPI_COMM_SIZE(MPI_COMM_WORLD, comsize, ierr)

    if (comsize /= 2) then 
        print *,'Error: this assumes n=2!'
        call MPI_ABORT(1,MPI_COMM_WORLD,ierr)
    endif

    !! 2 PEs; the other is 1 if we're 0, or 0 if we're 1.
    otherrank = comsize - (rank+1)

    print *, rank, ': second: Waiting for initial data...'
    call MPI_RECV(inputdata, n*m, MPI_REAL, otherrank, firsttag, &
                  MPI_COMM_WORLD, rstatus, ierr)

    print *, rank, ': second: adding 1 and sending back.'
    processeddata = inputdata + 1 
    call MPI_SEND(processeddata, n*m, MPI_REAL, otherrank, backtag, &
                  MPI_COMM_WORLD, ierr)

    print *, rank, ': second: completed'

    call MPI_FINALIZE(ierr)

end program second

For clarity, stuff that the two programs must agree on could be ina module they both use, here protocol.f90: 为了清楚起见,这两个程序必须达成共识的东西可能是它们都使用的模块,此处为protocol.f90:

module protocol
    !! shared information like tag ids, etc goes here

    integer, parameter :: firsttag = 1
    integer, parameter :: backtag  = 2

    !! size of problem
    integer, parameter :: n = 10, m = 20 
end module protocol 

(A makefile for building the executables follows:) (用于生成可执行文件的makefile如下:)

all: first second

FFLAGS=-g -Wall
F90=mpif90

%.mod: %.f90
        $(F90) -c $(FFLAGS) $^    

%.o: %.f90
        $(F90) -c $(FFLAGS) $^    

first: protocol.mod first.o
        $(F90) -o $@ first.o protocol.o

second: protocol.mod second.o
        $(F90) -o $@ second.o protocol.o

clean:
        rm -rf *.o *.mod

and then you run the two programs as following: 然后运行两个程序,如下所示:

$ mpiexec -n 1 ./first : -n 1 ./second
           1 : second: Waiting for initial data...
           0 : first: finished computing; now sending to second.
           0 : first: Now waiting for return data...
           1 : second: adding 1 and sending back.
           1 : second: completed
           0 : first: recieved data from partner.
$

We could certainly give you a more relevant example if you give us more information about the workflow between the two programs. 如果您向我们提供有关两个程序之间工作流程的更多信息,我们当然可以为您提供一个更相关的示例。

Are you using binary (unformatted) file I/O? 您是否正在使用二进制(未格式化)文件I / O? Unless the data quantity is huge, that should be fast. 除非数据量很大,否则应该很快。

Otherwise you could use interprocess communication, but it would be more complicated. 否则,您可以使用进程间通信,但是它将更加复杂。 You might find code in C, which you could call from Fortran using the ISO C Binding. 您可能会在C中找到代码,可以使用ISO C绑定从Fortran调用该代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM