Call parallel fortran MPI subroutine from R

孤人 提交于 2019-12-04 11:07:50

Here is a simple Fortran/MPI subroutine that I want to call from 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

To call this from R on a Linux machine, I built a shared object file using the Open MPI wrapper command "mpif90":

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

I tried to use "R CMD SHLIB", but eventually decided that it was easier to get "mpif90" to create a shared object than to get "R CMD SHLIB" to deal with MPI. The downside is that the command is gfortran specific. For a different compiler, you might get some help by using the "SHLIB" --dry-run option:

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

This will display the commands that it would have used to create the shared object using your compiler. You can then modify the commands to use "mpif90" in order to handle the MPI headers and libraries.

Here is an R script that calls the Fortran test subroutine. It loads Rmpi (which automatically calls MPI_Init), loads the shared object containing my Fortran subroutine, and then calls it:

# 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()

Since it's an SPMD-style program, it doesn't spawn workers, like many Rmpi examples. Instead, all of the workers are started via mpirun, which is the typical way of executing C and Fortran MPI programs:

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

This runs three instances of my R script, so the output is:

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

I think that structuring the code in this way makes it easy to use MPI from R and from any number of Fortran subroutines.

It should be possible to install do this, but it's not the simplest thing to do. The process would generally involve the steps below. But first, some caveats: R is only able to call subroutines, so your going to have to modify your main program to a subroutine and pass the arguments as above. Also, I would try to get a non-parallel case working first with Fortran, then try to handle the parallel case.

  • Install gfortran. My version of R (3.1.2) looks specifically for gfortran-4.8. I had gfortran-4.9 installed, so I created a symbolic link from 4.9 to 4.9 and it seemed to work (e.g. ln -s gfortran-4.9 gfortran-4.8)

  • Install the Rmpi libs. There are some instructions here to do it on the command line, but will only work for Linux. So, you may have to download it separately and install. You might try:

    > r CMD INSTALL Rmpi_0.6-5.tar.gz

  • Create a shared object library of your program. If your code above is name test.f90, at the command line run:

    $ r CMD SHLIB test.f90

  • Load the shared object into R:

    > dyn.load('test.so')

  • According to this page, assuming you were going to be making a call to a subroutine (not in parallel), the actual call to run the subroutine should be something like:

    > .Fortran("test", n=as.integer(5), x=as.double(rnorm(5)))

  • Launch the MPI job from within R. You're going to have to do all the MPI init stuff (mpi_init(), mpi_comm_size(), mpi_comm_rank()) from within R using the Rmpi interface. There is a decent tutorial here:

    > library(Rmpi)

    > mpi.spawn.Rslaves(nslaves=4)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!