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