R
Introduction
R is a language and environment for statistical computing and graphics. It is a GNU project which provides a wide variety of statistical (linear and nonlinear modelling, classical statistical tests, time-series analysis, classification, clustering, ...) and graphical techniques, and is highly extensible.
See the main WestGrid software table for the version currently installed on WestGrid systems.
Some brief notes are given below about submitting R jobs on WestGrid systems.
R on Glacier
Selecting the R version
There are several versions of R installed on Glacier. As of this writing (Dec. 14, 2010) if you just type "R", you get version 2.7.1, since the installation directory /global/software/R-2.7.1/gcc/bin/R is on the default PATH. However, version 2.12.0 is also available. You can access it by changing your PATH or by typing the full path to the R binary.
There are actually two variations on version 2.12.0, one compiled with GCC 3 compilers and one with GCC 4. These are /global/software/R-2.12.0/bin/R and /global/software/R-2.12.0/gcc4/bin/R, respectively. So, for example, to access the GCC 4 version, you can type:
Using Rmpi for Parallel Jobs
For parallel R with the Rmpi package on Glacier, it appears that one must use LAM MPI. As such, lamrun, not mpiexec is used to start the R program. Here is an example job script showing the use of LAM MPI to run a parallel R job. The file r.in contains the R commands to run. Rmpi is discussed in the Bugaboo/Snowpatch section below.
#PBS -S /bin/bash
cd $PBS_O_WORKDIR
echo "Current working directory is `pwd`"
echo "Node file: $PBS_NODEFILE :"
echo "---------------------"
cat $PBS_NODEFILE
echo "---------------------"
NUM_PROCS=`/bin/awk 'END {print NR}' $PBS_NODEFILE`
echo "Running on $NUM_PROCS processors."
R=/global/software/R-2.12.0/gcc4/bin/R
echo $R
export LAMRSH="/usr/bin/ssh"
lamboot -v $PBS_NODEFILE
# With slaves being created within R, only the master process should be started.
/usr/bin/lamrun -np 1 $R --slave CMD BATCH r.in
lamhalt
Submitting R Jobs
This section was written with Bugaboo and Snowpatch in mind, but, most of the material applies to other installations of R. Like other jobs on WestGrid systems, R jobs are run by submitting an appropriate script for batch scheduling using the qsub command. See documentation on running batch jobs for more information.
Running a Serial R Job
Any submission script for a serial program can be used with R. For example:
#PBS -r n
#PBS -m bea
#PBS -M jsbach@nowhere.ca
#PBS -l walltime=24:00:00
#PBS -l procs=1
cd $PBS_O_WORKDIR
R --vanilla < myRscript.R
will do for a small memory job on most WestGrid systems.
Using Rmpi for Parallel Jobs
mpiexec serial_prog
- Load the Rmpi package;
- Use functions from the Rmpi package to distribute the workload between processors.
- Initially only the master process is started
- Then the master process spawns the slaves handing out different tasks to each of the slaves
- At the end the master closes down the slaves
- And then finishes itself
#PBS -N Rmpi-hello
#PBS -l walltime=10:00
#PBS -l procs=10
cd $PBS_O_WORKDIR
mpiexec -n 1 R --vanilla < Rmpi-hello.R
if (!is.loaded("mpi_initialize")) {
library("Rmpi")
}
library(rsprng)
# In case R exits unexpectedly, have it automatically clean up
# resources taken up by Rmpi (slaves, memory, etc...)
.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()
}
print("Please use mpi.quit() to quit R")
.Call("mpi_finalize")
}
}
# Spawn as many slaves as possible
mpi.spawn.Rslaves()
# Tell all slaves to return a message identifying themselves
mpi.remote.exec(paste("I am",mpi.comm.rank(),"of",mpi.comm.size()))
# Tell all slaves to close down, and exit the program
mpi.close.Rslaves()
mpi.quit()
All the mpi.xxxx functions are defined in the Rmpi package. Sample code of this parallel R program is the single line:
# Load the R MPI package if it is not already loaded.
if (!is.loaded("mpi_initialize")) {
library("Rmpi")
}
# load all packages that are needed
library(xyz)
# In case R exits unexpectedly, have it automatically clean up
# resources taken up by Rmpi (slaves, memory, etc...)
.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()
}
print("Please use mpi.quit() to quit R")
.Call("mpi_finalize")
}
}
# Spawn as many slaves as possible
mpi.spawn.Rslaves()
<insert own R MPI program code here>
# Tell all slaves to close down, and exit the program
mpi.close.Rslaves()
mpi.quit()
You have to provide everything that replaces <insert own R MPI program code here> in the above.
mpi.spawn.Rslaves(nslaves=type.convert(Nprocs)-1)
Please note at the time of this wriring, some systems (including Checkers, Glacier and Lattice) do not support the PBS_NP environment variable, so, the number of processors has to be derived from other PBS variables, such as PBS_NODEFILE.
It is strongly suggested to experiment first before running a fullblown Rmpi calculation that is difficult to debug:
- Run your serial R program first before even attempting to use Rmpi.
Debug the serial R program until it runs without problems. - Come up with a scheme of how to distribute work between slaves.
- Implement that scheme using Rmpi.
- Test the Rmpi program using only a small number of processors.
- Try using as many processors as appear to be reasonable.
Updated 2011-09-18.
