[英]Call parallel fortran MPI subroutine from R
我想在一個可以被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
這是一個簡單的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變得容易。
應該可以安裝這樣做,但這不是最簡單的事情。 該過程通常涉及以下步驟。 但首先,一些警告:R只能調用子程序 ,因此您必須將主程序修改為子程序並傳遞上述參數。 此外,我會嘗試使用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庫 。 有一些說明這里做在命令行上,但僅適用於Linux工作。 因此,您可能需要單獨下載並安裝。 你可以試試:
> r CMD INSTALL Rmpi_0.6-5.tar.gz
創建程序的共享對象庫 。 如果上面的代碼是名稱test.f90,則在命令行運行:
$ r CMD SHLIB test.f90
將共享對象加載到R:
> dyn.load('test.so')
根據這個頁面 ,假設你要調用子程序(不是並行),運行子程序的實際調用應該是這樣的:
> .Fortran(“test”,n = as.integer(5),x = as.double(rnorm(5)))
從R內啟動MPI作業 。 您將不得不使用Rmpi接口從R中執行所有MPI初始化(mpi_init(),mpi_comm_size(),mpi_comm_rank())。 有一個像樣的教程在這里 :
>圖書館(Rmpi)
> mpi.spawn.Rslaves(nslaves = 4)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.