从R调用并行fortran MPI子例程

时间:2015-02-13 02:17:55

标签: r parallel-processing fortran mpi subroutine

我想在一个可以被R调用的子程序中编写一些并行的Fortran代码(我想从R读取数据并将其发送到并行的Fortran MPI)。但是,我注意到,当我将以下程序作为子程序运行(即代替“子程序”代替“程序”)时,代码不再编译(它在程序时编译)。我正在使用Linux中MPICHmpif90编译代码。

是否可以在Fortran的子程序中初始化和完成MPI?如果没有,是否仍然可以以某种方式从R调用并行的Fortran MPI?如果不是在Fortran中,可以在C中完成吗?

以下是代码:

module global
  integer numnodes,myid,mpi_err
  integer, parameter :: my_root=0
end module global

module fmpi
  include 'mpif.h'
end module fmpi

subroutine init
  use fmpi
  use global
  implicit none
  call MPI_INIT( mpi_err )
  call MPI_COMM_SIZE( MPI_COMM_WORLD, numnodes, mpi_err )
  call MPI_Comm_rank(MPI_COMM_WORLD, myid, mpi_err)
end subroutine init

program test
  use global
  use fmpi
  implicit none
  real*8:: dat(10)
  integer*4:: i
  call init
  if(myid == my_root) then
    do i=1,10
      dat(i) = i
    enddo
    print *,dat(1)
  endif
  call mpi_finalize(mpi_err)
end program test

2 个答案:

答案 0 :(得分:4)

这是一个简单的Fortran / MPI子程序,我想从R调用:

subroutine test(id, ierr)
  use mpi
  implicit none
  integer*4 id, ierr
  call MPI_Comm_rank(MPI_COMM_WORLD, id, ierr)
end subroutine test

要在Linux机器上从R调用它,我使用Open MPI包装器命令“mpif90”构建了一个共享对象文件:

$ mpif90 -fpic -shared -o test.so test.f90

我尝试使用“R CMD SHLIB”,但最终决定使用“mpif90”创建共享对象比获得“R CMD SHLIB”来处理MPI更容易。缺点是命令是特定的gfortran。对于不同的编译器,您可以通过使用“SHLIB”--dry-run选项获得一些帮助:

$ R CMD SHLIB --dry-run test.f90

这将显示用于使用编译器创建共享对象的命令。然后,您可以修改命令以使用“mpif90”来处理MPI标头和库。

这是一个调用Fortran test子例程的R脚本。它加载Rmpi(自动调用MPI_Init),加载包含我的Fortran子例程的共享对象,然后调用它:

# SPMD-style program: start all workers via mpirun
library(Rmpi)
dyn.load("test.so")

# This Fortran subroutine will use MPI functions
r <- .Fortran("test", as.integer(0), as.integer(0))

# Each worker displays the results
id <- r[[1]]
ierr <- r[[2]]
if (ierr == 0) {
  cat(sprintf("worker %d: hello\n", id))
} else {
  cat(sprintf("ierr = %d\n", ierr))
}

# Finalize MPI and quit
mpi.quit()

由于它是一个SPMD风格的程序,它不像许多Rmpi例子那样产生工作者。相反,所有工作都是通过mpirun启动的,这是执行C和Fortran MPI程序的典型方式:

$ mpirun -n 3 R --slave -f test.R

这会运行我的R脚本的三个实例,因此输出为:

worker 0: hello
worker 1: hello
worker 2: hello

我认为以这种方式构造代码可以很容易地从R和任意数量的Fortran子例程中使用MPI。

答案 1 :(得分:2)

应该可以安装这样做,但这不是最简单的事情。该过程通常涉及以下步骤。但首先,一些警告:R只能调用subroutines,因此您必须将主程序修改为子程序并传递上述参数。 此外,我会尝试使用Fortran首先处理非并行案例,然后尝试处理并行案例。

  • 安装gfortran。我的R(3.1.2)版本专门针对gfortran-4.8。我安装了gfortran-4.9,所以我创建了一个从4.9到4.9的符号链接,它似乎有效(例如ln -s gfortran-4.9 gfortran-4.8)

  • 安装Rmpi库。在命令行上有一些指令here,但只适用于Linux。因此,您可能需要单独下载并安装。你可以试试:

    &GT; r CMD INSTALL Rmpi​​_0.6-5.tar.gz

  • 创建程序的共享对象库。如果上面的代码是名称test.f90,请在命令行运行:

    $ r CMD SHLIB test.f90

  • 将共享对象加载到R:

    &GT; dyn.load( 'test.so')

  • 根据这个page,假设您要调用子程序(不是并行),运行子程序的实际调用应该是这样的:

    &GT; .Fortran(“test”,n = as.integer(5),x = as.double(rnorm(5)))

  • 从R 中启动MPI作业。您将不得不使用Rmpi接口从R中执行所有MPI初始化(mpi_init(),mpi_comm_size(),mpi_comm_rank())。有一个不错的教程here

    &GT;库(RMPI)

    &GT; mpi.spawn.Rslaves(nslaves = 4)