Monte Carlo simulations provide a powerful computational approach to address a wide variety of problems in several domains, such as physical sciences, engineering, computational biology and finance. The independent-samples and large-scale nature of Monte Carlo simulations make the corresponding computation suited for parallel execution, at least in theory. In practice, pseudo-random number generators (RNGs) are intrinsically sequential. This often prevents having a parallel Monte Carlo algorithm that is playing fair, meaning that results are independent of the architecture, parallelization techniques and number of parallel processes.
rTRNG is an R package for advanced parallel Random
Number Generation in R. It relies on TRNG (Tina’s
Random Number Generator), a state-of-the-art C++ pseudo-random number
generator library for sequential and parallel Monte Carlo simulations.
In particular, parallel random number engines provided by TRNG
can be manipulated by jump
and split
operations. These allow to jump
ahead by an arbitrary
number of steps and to split
a sequence into any desired
sub-sequence(s), thus enabling techniques such as
block-splitting and leapfrogging suitable to parallel
algorithms.
Package rTRNG provides the R users with access to the functionality of the underlying TRNG C++ library, both in R and as part of other projects combining R with C++.
The TRNG.Random functionality (see ?TRNG.Random
)
provides a base-R-like access to TRNG random number engines by setting
and manipulating the current engine in use.
library(rTRNG)
TRNGkind("yarn2")
TRNGseed(117)
TRNGjump(5) # advance by 5 the internal state
TRNGsplit(3, 2) # subsequence: one element every 3 starting from the 2nd
Random variates from the current engine are then generated using
functions r<dist>_trng
, e.g. runif_trng
for the uniform distribution.
Random number engines can be explicitly created and manipulated using
reference objects from a number of classes (see
?TRNG.Engine
), e.g. yarn2
.
The engine object is then passed as engine
argument of
any r<dist>_trng
function.
The parallel nature of TRNG random number engines allows
fair-playing multi-threaded generation of random variates, with
guaranteed equivalence to a purely-sequential generation. Parallel
generation is available in r<dist>_trng
with argument
parallelGrain > 0
and relies on
RcppParallel
, where the number of parallel threads is
controlled via RcppParallel::setThreadOptions
.
C++ code using the C++ TRNG library and headers shipped with
rTRNG can easily be compiled, specifying the
Rcpp::depends
attribute that allows
Rcpp::sourceCpp
to link correctly against the library.
Moreover, Rcpp::plugins(cpp11)
is needed to enforce the
C++11 standard required by TRNG >= 4.22.
// [[Rcpp::depends(rTRNG)]]
// TRNG >= 4.22 requires C++11
// [[Rcpp::plugins(cpp11)]]
#include <Rcpp.h>
#include <trng/yarn2.hpp>
#include <trng/uniform_dist.hpp>
using namespace Rcpp;
using namespace trng;
// [[Rcpp::export]]
NumericVector exampleCpp() {
yarn2 rng;
rng.seed(117);
// alternative: yarn2 rng(117);
rng.jump(5);
rng.split(3, 1); // note the C++ 0-based index for the subsequence
NumericVector x(10);
uniform_dist<> unif(0, 1);
for (unsigned int i = 0; i < 10; i++) {
x[i] = unif(rng);
}
return x;
}
/*** R
exampleCpp()
*/
## [1] 0.9085960 0.8689441 0.3540530 0.7378240 0.0052939 0.5866284 0.6862086
## [8] 0.7088267 0.6622958 0.8182121
Creating an R package with C++ code using the TRNG library and headers through rTRNG is achieved by
Imports: rTRNG
and LinkingTo: rTRNG
to the DESCRIPTION fileimportFrom(rTRNG, TRNG.Version)
CXX_STD = CXX11
rTRNG::LdFlags()
PKG_LIBS += $(shell ${R_HOME}/bin/Rscript -e "rTRNG::LdFlags()")
PKG_LIBS += $(shell "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" -e "rTRNG::LdFlags()")
C++ code using the TRNG library (sourced via
Rcpp::sourceCpp
or part of an R package) might fail on
certain systems due to issues with building and linking against
rTRNG. This is typically the case for
macOS, and can generally be checked by running