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

时间:2011-02-23 17:04:32

标签: io fortran tcp transfer

我们目前正在使用文件I / O,但需要更好/更快的方式。示例代码将不胜感激。

2 个答案:

答案 0 :(得分:1)

通过使用文件进行传输,您已经实现了一种消息传递形式,因此我认为这对于此类程序来说是最自然的选择。现在,您可以自己编写一些在可用时使用共享内存的东西,以及在没有时使用TCP / IP的东西 - 或者您可以只使用已经这样做的库,如MPI,它可以广泛使用,可以利用共享内存如果你在同一台机器上运行,但也会扩展到让你在不同的机器上完全运行它们而不用你改变你的代码。

因此,作为一个程序将数据发送到第二个然后等待数据的简单示例,我们有两个程序如下; first.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

和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

为清楚起见,两个程序必须达成一致的东西可以是他们都使用的模块,这里是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 

(用于构建可执行文件的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

然后按以下方式运行这两个程序:

$ 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.
$

如果您向我们提供有关两个计划之间工作流程的更多信息,我们当然可以给您一个更相关的示例。

答案 1 :(得分:0)

您使用的是二进制(无格式)文件I / O吗?除非数据量很大,否则应该很快。

否则你可以使用进程间通信,但它会更复杂。您可以在C中找到代码,您可以使用ISO C Binding从Fortran调用它。