As of EGRET
version 2.6.1, we’ve added the dependency
foreach
, which can allow the modelEstimation
function to be run in parallel. Depending on the available cores, this
could significantly speed up the WRTDS calculations. By default, the
code is still run serially (ie…not in parallel).
The directions in this vignette show how to take advantage of multiple cores on a single computer. The concept can be extended to cluster computing (for example: HTConder, SLURM (for USGS YETI), Alces Flight,…), but the specific directions for those systems are not covered in this vignette.
The WRTDS routine in the modelEstimation
function is the
only major process that is improved with parallel processing in the
EGRET
package. Confidence intervals and trend calculations
in the EGRETci
package are also updated with parallel
capabilities via the foreach
package. See the vignette
“Running EGRETci in Parallel” in EGRETci
for more
details.
In order to run WRTDS in parallel and get a computationally efficient
advantage, you will first need a computer with multiple cores. Most
newer computers are multi-core. To check how many cores your computer
has, use the detectCores()
function in the
parallel
packages (which is shipped with the base R
installation):
library(parallel)
detectCores()
## [1] 12
There is some overhead involved in going from serial to parallel computing, so you should not expect a 1:1 speed-up. If your computer only has 2 cores, you might not see any improvements in efficiency.
Once you’ve checked that your computer has multiple cores, you need
to register how many cores you want to use. There are a few ways to do
this. It will depend on your operating system and general workflow what
exactly is the best way to do this. There are currently 3 main packages
that you can use to parallelize the modelEstimation
function: doParallel
, doSNOW
, and
doMC
.
The doParallel
package recommend to most new users
because it works best on all three major operating systems (Windows,
Mac, Linux). However, doMC
can be more efficient on Linux.
Therefore, we recommend doParallel
, but will show workflows
for both of the packages.
It is recommended to use at most
detectCores(logical = FALSE) - 1
cores for your
calculations. This leaves one core available for other computer
processes. Most modern CPU’s can handle registering all the cores on
your computer without issue. In fact, you could register more
cores than are physically on your computer, but could be inefficient.
When using the function detectCores
, we recommend
specifying logical = FALSE
because that will find the
number of physical cores on your computer. logical=TRUE
includes multithreading, which we have found to generally not improve
the efficiency in these calculations.
Note: the packages doParallel
or doMC
are
suggested for EGRET
. This means they are not
automatically installed with the EGRET
installation. You
will need to install separately the package of your choice.
Important for all workflows, when the processing is
completed, you need to stop the cluster registration with the
stopCluster
function.
We will now show 3 examples using the “Choptank River” example data:
library(EGRET)
library(parallel)
<- Choptank_eList
eList <- detectCores(logical = FALSE) - 1 nCores
The most generalized workflow uses the doParallel
package:
library(doParallel)
library(parallel)
<- makeCluster(nCores)
cl registerDoParallel(cl)
<- modelEstimation(eList, verbose = FALSE, run.parallel = TRUE)
eList stopCluster(cl)
library(doMC)
library(parallel)
<- makeCluster(nCores)
cl registerDoMC(cl)
<- modelEstimation(eList, verbose = FALSE, run.parallel = TRUE)
eList stopCluster(cl)
If you plan to use the modelEstimation
function
frequently, it will be worth trying a simple benchmark test to determine
if running the code in parallel makes sense on your system. While
significantly more robust benchmark testing is available from several R
packages (see microbenchmark
for example), a very simple
test can be done with the system.time
function:
library(doParallel)
library(parallel)
library(EGRET)
<- Choptank_eList
eList
<- detectCores(logical = FALSE) - 1
nCores
system.time({
<- makeCluster(nCores)
cl registerDoParallel(cl)
<- modelEstimation(eList, verbose = FALSE, run.parallel = TRUE)
eList stopCluster(cl)
})
user system elapsed
9.11 0.95 33.34
system.time({
<- modelEstimation(eList, verbose = FALSE, run.parallel = FALSE)
eList })
user system elapsed
60.05 0.05 60.51
If the timing of the parallel code is not significantly faster (or even slower!) than the regular non-parallel code, it is not worth running in parallel on your current computer.