Rmpi

Rmpi is a package that provides MPI bindings for the R programming language. In much the same way parallel code is written in other languages such as C or Fortran, R codes can run in parallel across multiple processors or nodes.
Version on gowonda :0.5-9
Rmpi requires the following module file and some prerequisites to run:

Location

/sw/R/2.13.0/lib64/R/library/Rmpi/libs

Usage :

 module load R/2.13.0 

Installation

mkdir -p /sw/R/2.13.0/lib64/R/library/Rmpi/src/
cp rmpi source here.
tar -zxvf Rmpi_0.5-9.tar.gz
cd /sw/R/2.13.0/lib64/R/library/Rmpi/src/Rmpi
vi README
(The installation instructions are here!)


cd /sw/R/2.13.0/lib64/R/library/Rmpi/src/
module purge
module load R/2.13.0
module load mpi/openMPI/1.4.3-gnu
R CMD INSTALL Rmpi_0.5-9.tar.gz --configure-args=--with-mpi=/sw/openMPI/1.4.3-gnu/ 2>&1 | tee rmpi_install.txt

>>>>>>>>>>>>>>>>>>>>>
* installing to library â/sw/R/2.13.0/lib64/R/libraryâ
* installing *source* package âRmpiâ ...
checking for gcc... gcc -std=gnu99
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc -std=gnu99 accepts -g... yes
checking for gcc -std=gnu99 option to accept ISO C89... none needed
Trying to find mpi.h ...
Found in /sw/openMPI/1.4.3-gnu//include
Trying to find libmpi.so or libmpich.a ...
Found libmpi in /sw/openMPI/1.4.3-gnu//lib
checking for openpty in -lutil... yes
checking for main in -lpthread... yes
configure: creating ./config.status
config.status: creating src/Makevars
** libs
gcc -std=gnu99 -I/sw/R/2.13.0/lib64/R/include -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -I/sw/openMPI/1.4.3-gnu//include  -DMPI2 -DOPENMPI -I/usr/local/include    -fpic  -g -O2 -c RegQuery.c -o RegQuery.o
gcc -std=gnu99 -I/sw/R/2.13.0/lib64/R/include -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -I/sw/openMPI/1.4.3-gnu//include  -DMPI2 -DOPENMPI -I/usr/local/include    -fpic  -g -O2 -c Rmpi.c -o Rmpi.o
gcc -std=gnu99 -I/sw/R/2.13.0/lib64/R/include -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -I/sw/openMPI/1.4.3-gnu//include  -DMPI2 -DOPENMPI -I/usr/local/include    -fpic  -g -O2 -c conversion.c -o conversion.o
gcc -std=gnu99 -I/sw/R/2.13.0/lib64/R/include -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -I/sw/openMPI/1.4.3-gnu//include  -DMPI2 -DOPENMPI -I/usr/local/include    -fpic  -g -O2 -c internal.c -o internal.o
gcc -std=gnu99 -shared -L/usr/local/lib64 -o Rmpi.so RegQuery.o Rmpi.o conversion.o internal.o -L/sw/openMPI/1.4.3-gnu//lib -lmpi -lutil -lpthread -L/sw/R/2.13.0/lib64/R/lib -lR
installing to /sw/R/2.13.0/lib64/R/library/Rmpi/libs
** R
** demo
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices ...
** testing if installed package can be loaded
* DONE (Rmpi)
>>>>>>>>>>>>>>>>>>>>>

Add the path to R module files

vi /sw/com/modulefiles/R/2.13.0

 module  display R/2.13.0
-------------------------------------------------------------------
/sw/com/modulefiles/R/2.13.0:

module-whatis    adds R-2.13.0 directories to PATH etc.
prepend-path     PATH /sw/R/2.13.0/lib64/pkgconfig
prepend-path     PATH /sw/R/2.13.0/bin
prepend-path     PATH /sw/R/2.13.0/lib64/R/library/Rmpi/R
prepend-path     PATH /sw/R/2.13.0/lib64/R/library/Rmpi/Meta
prepend-path     PATH /sw/R/2.13.0/lib64/R/library/Rmpi
prepend-path     PATH /sw/R/2.13.0/lib64/R/bin
prepend-path     PATH /sw/R/2.13.0/lib64
prepend-path     LD_LIBRARY_PATH /sw/R/2.13.0/lib64/R/lib
prepend-path     LD_LIBRARY_PATH /sw/R/2.13.0/lib64/R/library/Rmpi/libs
prepend-path     INCLUDE /sw/R/2.13.0/lib64/R/include
prepend-path     MANPATH /sw/R/share/man
-------------------------------------------------------------------


Other Notes from the Install Guide

NOTE: If your site has a different MPI such as MPICH installed, Rmpi
   could still detect it and disable MPI-2 related functions
   automatically. Unless you remove the part of checking lam-mpi in zzz.R.in
   file in R directory, you need to create a file lamnodes and put the line
        echo "FAKE lamnodes"
   Make sure lamnodes is executable and in the path. Try
        mpirun -np 1 R
   to start a master R and load Rmpi.

   If your cluster does not have MPI_Comm_spawn enabled so you cannot
   use mpi.spawn.Rslaves, there are two ways to launch multiple Rs.
   a). Save Rprofile in inst (will be in the root directory of Rmpi
       after installation) as .Rprofile in the working or root directory.
       Then run, for example,
                mpirun -n 9 R --no-save -q
       This will create one master and 8 slaves. Those slaves will behave as
       though mpi.spawn.Rslaves has been used.
   b). To run multiple Rs without using .Rprofile, add the following line
                R_PROFILE=${R_HOME}/library/Rmpi/Rprofile; export R_PROFILE
       in the R shell script (after "export R_HOME") and rename it, say, Rmpi.
       Then one can use
                mpiexec -n 9 Rmpi --no-save -q
       assuming that Rmpi is in the PATH.

Important note regarding closing R slaves

Final note: It is extremely important that users should close R slaves
   and Rmpi properly before quiting R. Basically, use mpi.close.Rslaves to
   close R slaves and use mpi.exit to exit Rmpi environment or use
   mpi.quit to quit Rmpi and R together.

   To safe guard at site level, administrator can add the .Last function
   to Rprofile.site as

.Last <- function(){
    if (is.loaded("mpi_initialize")){
        if (mpi.comm.size(1) > 0){
            print("Please use mpi.close.Rslaves() to close slaves.")
            mpi.close.Rslaves(comm=1)
        }
        print("Please use mpi.quit() to quit R")
        .Call("mpi_finalize")
    }



test runs

Source: https://www.stanford.edu/group/farmshare/cgi-bin/wiki/index.php/Rmpi

Save following as .Rprofile. This should be in the current directory from where you submit your Rmpi jobs

cat /sw/R/2.13.0/share/Rprofile

# This R profile can be used when a cluster does not allow spawning or a job
# scheduler is required to launch any parallel jobs. Saving this file as
# .Rprofile in the working directory or root directory. For unix platform, run
# mpirexec -n [cpu numbers] R --no-save -q
# For windows platform with mpich2, use mpiexec wrapper and specify a working
# directory where .Rprofile is inside.
# Cannot be used as Rprofile.site because it will not work

# Following system libraries are not loaded automatically. So manual loads are
# needed.


.libPaths(c("/sw/R/2.13.0/lib64/R/library", "/sw/R/2.13.0/lib64/R/library/Rmpi/libs"))

library(utils)
library(stats)
library(datasets)
library(grDevices)
library(graphics)
library(methods)

if (!invisible(library(Rmpi,logical.return = TRUE))){
    warning("Rmpi cannot be loaded")
    q(save = "no")
}

options(error=quote(assign(".mpi.err", FALSE, env = .GlobalEnv)))

if (mpi.comm.size(0) > 1)
    invisible(mpi.comm.dup(0,1))

if (mpi.comm.rank(0) > 0){
    #sys.load.image(".RData",TRUE)
    options(echo=FALSE)
    .comm <- 1
    mpi.barrier(0)
    repeat
        try(eval(mpi.bcast.cmd(rank=0,comm=.comm)),TRUE)
        #try(eval(mpi.bcast.cmd(rank=0,comm=.comm),env=sys.parent()),TRUE)
        #mpi.barrier(.comm)
    if (is.loaded("mpi_comm_disconnect"))
        mpi.comm.disconnect(.comm)
    else mpi.comm.free(.comm)
        mpi.quit()
}

if (mpi.comm.rank(0)==0) {
    #options(echo=TRUE)
    mpi.barrier(0)
    if(mpi.comm.size(0) > 1)
        slave.hostinfo(1)
}

.Last <- function(){
    if (is.loaded("mpi_initialize")){
        if (mpi.comm.size(1) > 1){
            print("Please use mpi.close.Rslaves() to close slaves")
            mpi.close.Rslaves(comm=1)
        }
    }
    print("Please use mpi.quit() to quit R")
    mpi.quit()
}

Let's assume you have a directory called: $HOME/pbs/rmpitest. You will need to copy the above script into this directory:

cp /sw/R/2.13.0/share/Rprofile $HOME/pbs/rmpitest/.Rprofile

Here is a very short R program. Save this as Rmpitest.R in $HOME/pbs/rmpitest directory

# Tell all slaves to return a message identifying themselves
mpi.remote.exec(paste(Sys.info()[c("nodename")],"checking in as",mpi.comm.rank(),"of",mpi.comm.size()))

# Tell all slaves to close down, and exit the program
mpi.close.Rslaves()
mpi.quit()

PBS submit script (rmpi.submit)

#!/bin/bash
#####################################################################
### This section defines options for the pbs batching system
#####################################################################
#PBS -m abe
#PBS -M YourEmail@griffith.edu.au
#PBS -q workq
#PBS -l walltime=10:30:00
#PBS -N rmpi64
### Number of nodes:Number of CPUs:Number of threads per node
#PBS -l select=2:ncpus=2:mpiprocs=2:mem=1g
NPROCS=4
source $HOME/.bashrc

###Load the R and openmpi
module load R/2.13.0
module load mpi/openMPI/1.4.3-gnu
 


#####################################################################
### This section is for my debugging purposes (not required)
#####################################################################
echo "This jobs runs on the following processors:"
echo `cat $PBS_NODEFILE`
echo Running on host `hostname`
echo Time is `date`

#####################################################################
### This section is setting up and running your executable or script
#####################################################################
cd $HOME/pbs/rmpitest/
mpirun -np $NPROCS -machinefile $PBS_NODEFILE R --no-save -q < Rmpitest.R

qsub rmpi.submit
374100.pbsserver

cat rmpi64.o374100
This jobs runs on the following processors:
n002 n002 n002 n002
Running on host n002
Time is Thu May 31 13:04:12 EST 2012
master (rank 0, comm 1) of size 4 is running on: n002
slave1 (rank 1, comm 1) of size 4 is running on: n002
slave2 (rank 2, comm 1) of size 4 is running on: n002
slave3 (rank 3, comm 1) of size 4 is running on: n002
> # Tell all slaves to return a message identifying themselves
> mpi.remote.exec(paste(Sys.info()[c("nodename")],"checking in as",mpi.comm.rank(),"of",mpi.comm.size()))
$slave1
[1] "n002 checking in as 1 of 4"

$slave2
[1] "n002 checking in as 2 of 4"

$slave3
[1] "n002 checking in as 3 of 4"

>
> # Tell all slaves to close down, and exit the program
> mpi.close.Rslaves()
[1] 1
> mpi.quit()


Sample pbs script

cd <YourRscriptDirectory>
cp /sw/R/2.13.0/share/.Rprofile .
(Impt: The step is needed. You will need to copy the above script into the directory that has the R script you will be running)
Next submit the job:
qsub <pbsScript>

Where your pbs script (pbsScript) could look like this

#!/bin/bash
#####################################################################
### This section defines options for the pbs batching system
#####################################################################
#PBS -m abe
#PBS -M YourEmail@griffith.edu.au
#PBS -q mpi
#PBS -l walltime=10:00:00
#PBS -N Rmpi64
### Number of nodes:Number of CPUs:Number of threads per node
#PBS -l select=2:ncpus=2:mpiprocs=2:mem=1g
NPROCS=4
source $HOME/.bashrc

###Load the R and openmpi
module load R/2.13.0
module load mpi/openMPI/1.4.3-gnu
 
#####################################################################
### This section is for my debugging purposes (not required)
#####################################################################
echo "This jobs runs on the following processors:"
echo `cat $PBS_NODEFILE`
echo Running on host `hostname`
echo Time is `date`

#####################################################################
### This section is setting up and running your executable or script
#####################################################################
cd <YourRscriptDirectory>
mpirun -np $NPROCS -machinefile $PBS_NODEFILE R --no-save -q < <MyRscript>.R

Reference:

1. http://rc.usf.edu/trac/doc/wiki/Rmpi
2. https://www.stanford.edu/group/farmshare/cgi-bin/wiki/index.php/Rmpi