Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
My first attempt of using Rcpp andRcppArmadillo
Andy Leung
University of British Columbia
March 22, 2012
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Outline
1. Motivation
2. How to use it?I Where can I get it?I How to compile it?
3. Main Rcpp classesI List of classesI Coversion between R and C++I Some syntatic sugarI Small examples
4. Extending to RcppArmadilloI List of classesI Member functions and variablesI Examples
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Outline
1. Motivation
2. How to use it?I Where can I get it?I How do I compile it?
3. Main Rcpp classesI List of classesI Coversion between R and C++I Some syntatic sugarI Small examples
4. Extending to RcppArmadilloI List of classesI Member functions and variablesI Examples
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Motivation
PROS CONS
I SPEED!!
I SPEED!!
I and SPEED!!
I “Steep” learning curve
I Bugs bite
I Less readable code
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Speed Example: Mahalanobis distance
Example: Compute mahalanobis distance (xi − µ)TΣ−1(xi − µ) forobservations xi , i = 1, ..., n given µ and Σ
Let’s skip all the syntax etc. but focus on speed result. We’ll comeback to this example.
## Using R
mahalanobis_R <- function(X, Mu, Sigma){
md <- rep(NA, nrow(X) )
for(i in 1:nrow(X) )
md[i] <- mahalanobis(X[i,], center=Mu, cov=Sigma)
return(md)
}
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Speed Example: Mahalanobis distance
## Using RcppArmadillo
code <- ’arma::mat x = Rcpp::as<arma::mat>(X);
arma::mat mu = Rcpp::as<arma::mat>(Mu);
arma::mat sigma = Rcpp::as<arma::mat>(Sigma);
int n = x.n_rows;
arma::vec md(n);
for (int i=0; i<n; i++){
arma::mat x_i = x.row(i) - mu;
arma::mat Y = arma::solve( sigma, arma::trans(x_i) );
md(i) = arma::as_scalar(x_i * Y);
}
return wrap(md);’
mahalanobis_RcppArma <- cxxfunction( signature(X="numeric",
Mu="numeric", Sigma="numeric"), code, plugin="RcppArmadillo")
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Speed Example: Mahalanobis distance (n=1000, p=4)
> ## Some speed test results
> benchmark(
+ mahalanobis_R(X, c(Mu), Sigma),
+ mahalanobis_RcppArma(X, Mu, Sigma),
+ columns=c("test", "replications","elapsed", "relative"),
+ replications=100,
+ order="relative")
test replications elapsed relative
2 mahalanobis_RcppArma(X, Mu, Sigma) 100 0.14 1.0000
1 mahalanobis_R(X, c(Mu), Sigma) 100 27.63 197.3571
Approximately 200 times faster!!
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Outline
1. Motivation
2. How to use it?I Where can I get it?I How do I compile it?
3. Main Rcpp classesI List of classesI Coversion between R and C++I Some syntatic sugarI Small examples
4. Extending to RcppArmadilloI List of classesI Member functions and variablesI Examples
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
How to use it?
I Available as an R package on CRANhttp://cran.r-project.org/web/packages/Rcpp/index.html
http://cran.r-project.org/web/packages/RcppArmadillo/index.html
I Depends on R version (≥ 2.12.0 for Rcpp v0.9.10 and ≥2.14.0 for RcppArmadillo v0.2.35)
I Compiling using R CMD SHLIB and inline
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
How to compile it?
Compiling using R CMD SHLIB is not that trivial...For instance,
RCPP_CXXFLAGS=‘Rscript -e ’Rcpp:::CxxFlags()’‘
RCPP_LIBS=‘Rscript -e ’Rcpp:::LdFlags()’‘
export PKG_CPPFLAGS="-I ~/R/x86_64-unknown-linux-gnu-library/2.10/RcppArmadillo/include/ ${RCPP_CXXFLAGS}"
export PKG_LIBS="-larmadillo -llapack ${RCPP_LIBS}"
R CMD SHLIB file.cpp
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
How to compile it?
Compiling using inline is a lot easier! As all the linking andloading will be taken care of by the R function cxxfunction(...):
code <- ’NumericVector xx(x);
NumericVector yy(x);
int nn = as<int>(n);
for(int i=0; i<nn; i++) xx=xx*yy;
return wrap(xx);’
fun <- cxxfunction(signature(x="numeric", n="integer"),
body=code, plugin="Rcpp")
No more libraries path specifying and shared library loading!
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Outline
1. Motivation
2. How to use it?I Where can I get it?I How do I compile it?
3. Main Rcpp classesI List of classesI Coversion between R and C++I Some syntatic sugarI Small examples
4. Extending to RcppArmadilloI List of classesI Member functions and variablesI Examples
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Main Rcpp classes
Main Rcpp Classes R typeof
I IntegerVector / Matrix
I NumericVector / Matrix
I LogicalVector / Matrix
I CharacterVector / Matrix
I List
I DataFrame
I Environment
I Function
I ...
I integer
I numeric
I logical
I character
I list
I list?
I environment
I function
I ...
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Example 1: Fibonacci sequence
R, C++ conversion: as / wrap
code <- ’int nn = as<int>(n);
NumericVector xx(nn);
for(int i=0; i<nn; i++){
if(i == 0) { xx[i] = 0; }
else if(i == 1){ xx[i] = 1; }
else { xx[i] = xx[i-1] + xx[i-2]; }
}
return wrap(xx);’
fun <- cxxfunction(signature(n="integer"),
body=code, plugin="Rcpp")
fun(20)
[1] 0 1 1 2 3 5 8 13 21 34 55 89
[13] 144 233 377
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Example 2: Matrix multiplication (element-wise)
In R is simple...
matrix(1:9, 3,3)*matrix(1:9, 3,3)
[,1] [,2] [,3]
[1,] 1 16 49
[2,] 4 25 64
[3,] 9 36 81
In Rcpp...
code <- ’
NumericMatrix X = as<NumericMatrix>(mX);
return wrap(X*X);
’
fun <- cxxfunction(signature(mX="numeric"),
body=code, plugin="Rcpp")
fun( matrix(1:9, 3,3) )
[1] 1 4 9 16 25 36 49 64 81
## Return a vector?
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Example 2 (contd): Matrix multiplication (element-wise)
This way we can obtain the same matrix as in R, but not thattrivial...
## This template class is an example pulled out
## from Rcpp-FAQ.pdf from CRAN
inc <- ’template <typename T>
class square:
public std::unary_function<T,T> {
public:
T operator()( T t) const { return t*t ;}
}; ’
code <- ’NumericMatrix X = as<NumericMatrix>(mX);
std::transform( X.begin(), X.end(), X.begin(), square<double>());
return wrap(X); ’
fun <- cxxfunction(signature(mX="numeric"),
body=code, include=inc, plugin="Rcpp")
fun( matrix(1:9, 3,3) )
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Example 3: Matrix determinant and inversion
Access R functions from C++...code <- ’RNGScope scope; // properly deal with RNG settings
NumericMatrix xx(5, 5); // create 5 by 5 matrix
for(int i; i < 5; i++)
xx(i, _) = rnorm(5, 0, 1); // feature of Rcpp sugar
// Compute determinant
Environment base("package:base");
Function det = base["det"];
double dt = as<double>( det( wrap(xx) ) );
// Matrix inversion
Function solve = base["solve"];
NumericMatrix xxinv = as<NumericMatrix>( solve( wrap(xx) ) );
return List::create(Named("xx")=xx, Named("dt")=dt,
Named("xxinv")=xxinv); // Export a list
’Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Example 3 (contd): Matrix determinant and inversion
Just to show we indeed export a list...
fun <- cxxfunction(body=code, plugin="Rcpp")
(res <- fun())
$xx
[,1] [,2] [,3] [,4] [,5]
[1,] 0.85519655 -0.3439182 0.3155362 -0.897272594 -1.5510895
[2,] 0.06791312 0.8708584 1.1557379 -0.679489824 0.8083568
...
$dt
[1] -7.656185
$xxinv
[,1] [,2] [,3] [,4] [,5]
[1,] -0.01776536 0.58595182 -0.79460866 -0.2917635 -0.5765320
[2,] 0.39741299 -0.08875792 0.16766251 0.5927874 -0.1591927
...
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
More about Rcpp syntactic sugar
Reference:Dirk Eddelbuettel and Romain Francois. Rcpp syntactic sugar,2012. URL http://cran.r-project.org/web/packages/Rcpp/
vignettes/Rcpp-sugar.pdf. R package version 0.9.10.
Romain Francois and Dirk Eddelbuettel. Rcpp Quick ReferenceGuide, 2011. URL http://cran.r-project.org/web/
packages/Rcpp/vignettes/Rcpp-quickref.pdf. R packageversion 0.9.8.
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Outline
1. Motivation
2. How to use it?I Where can I get it?I How do I compile it?
3. Main Rcpp classesI List of classesI Coversion between R and C++I Some syntatic sugarI Small examples
4. Extending to RcppArmadilloI List of classesI Member functions and variablesI Examples
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Extending to RcppArmadilloBack to Example 2: Matrix multiplication (element-wise)
In RcppArmadillo...
code <- ’arma::mat X = as<arma::mat>(mX);
return wrap( X%X );’
fun <- cxxfunction(signature(mX="numeric"),
body=code, plugin="RcppArmadillo")
fun( matrix(1:9, 3,3) )
[,1] [,2] [,3]
[1,] 1 16 49
[2,] 4 25 64
[3,] 9 36 81
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Main Armadillo classes
Matrices:
I mat (double), umat (unsigned integer), imat (signed integer),fmat (float)
Vectors:
I vec, uvec, ivec, fvec
Cubes:
I cube, ucube, icube, fcube
Main member functions and variables
I .n rows (mat), .n cols (mat), .n elem (vec, mat, cube),.n slice (cube), element access/initialization via ()
For more please refer tohttp://arma.sourceforge.net/docs.html
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Back to our earlier Example: Mahalanobis distance
code <- ’arma::mat x = Rcpp::as<arma::mat>(X);
arma::mat mu = Rcpp::as<arma::mat>(Mu);
arma::mat sigma = Rcpp::as<arma::mat>(Sigma);
int n = x.n_rows;
arma::vec partial(n);
for (int i=0; i<n; i++){
arma::mat x_i = x.row(i) - mu;
arma::mat Y = arma::solve( sigma, arma::trans(x_i) );
partial(i) = arma::as_scalar(x_i * Y);
}
return wrap(partial);’
mahalanobis_RcppArma <- cxxfunction( signature(X="numeric",
Mu="numeric", Sigma="numeric"), code, plugin="RcppArmadillo")
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
More Example: Partial Mahalanobis distance
Compute partial mahalanobis distance
(x(ui )i − µ(ui ))T (Σ(ui ))−1(x
(ui )i − µ(ui )) for observations
xi , i = 1, ..., n given µ and Σ where ui denotes the available entriesof observation xi .
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
More Example (contd): Partial Mahalanobis distance
Let’s start with code in R...
partial_R <- function(x, Sigma){
n <- nrow(x)
p <- ncol(x)
md <- rep(0, n)
for(i in 1:n){
y <- x[i,]
u <- !is.na(y)
y.obs <- y[u]
Sigma.obs <- Sigma[u,u]
md[i] <- y.obs %*% solve(Sigma.obs) %*% y.obs
}
return(md)
}
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
More Example (contd): Partial Mahalanobis distance
Now using RcppArmadillo...
code <- ’try{
using namespace Rcpp;
using namespace arma;
mat x_mu_diff = as<mat>(X_mu_diff);
umat x_nonmiss = as<umat>(X_nonmiss);
mat sigma = as<mat>(Sigma);
int n = x_mu_diff.n_rows;
int p = x_mu_diff.n_cols;
vec partialVec(n);
uvec pp = sum(x_nonmiss, 1);
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
More Example (contd): Partial Mahalanobis distance
for(int i = 0; i < n; i++){
mat sigma_nonmiss( pp(i), pp(i) );
mat xi(1, pp(i) );
if( pp(i) < p ){
int mm = 0;
for(int j=0; j<p; j++){
int nn=mm;
if(x_nonmiss(i,j) == 1){
for(int k=j; k<p; k++){
if( x_nonmiss(i,k) == 1 ){
sigma_nonmiss(mm, nn) = sigma(j,k);
sigma_nonmiss(nn, mm) = sigma(k,j);
nn++;
}
}
xi(0,mm) = x_mu_diff(i, j);
mm++;
}
}
} else{
sigma_nonmiss = sigma;
xi = x_mu_diff.row(i);
}
mat Y = solve( sigma_nonmiss, xi.t());
partialVec(i) = as_scalar(xi * Y);
}
return wrap(partialVec);
} catch( std::exception& __ex__ ){
forward_exception_to_r( __ex__ );
} catch(...){
::Rf_error( "c++ exception " "(unknown reason)" );
}
’
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
More Example (contd): Partial Mahalanobis distance
else{
sigma_nonmiss = sigma;
xi = x_mu_diff.row(i);
}
mat Y = solve( sigma_nonmiss, xi.t());
partialVec(i) = as_scalar(xi * Y);
}
return wrap(partialVec);
} catch( std::exception& __ex__ ){
forward_exception_to_r( __ex__ );
} catch(...){
::Rf_error( "c++ exception " "(unknown reason)" );
}
’
partial_Rcpp <- cxxfunction(signature(X_mu_diff="numeric",
X_nonmiss="integer", Sigma="numeric"), code, plugin="RcppArmadillo")
(I admit this code is indeed too long in a presentation like this...)
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
More Example (contd): Partial Mahalanobis distance
Again, let’s look at the speed of the two code...Create a multivariately normal distributed (mean 0 and cov. Σ)data set with n = 1000, p = 3 and 10% missingnessp <- 3; n <- 1000; mis <- 0.1
A <- matrix(rnorm(p*p), p, p)
x <- x.na <- matrix(rnorm(n*p), n, p) %*% A
x.nonmiss <- matrix(1, n, p)
for(i in 1:round((n*mis))) {
nn <- sample(1:n, 1)
pp <- sample(1:p, 1)
x.nonmiss[nn, pp] <- 0
x.na[nn, pp] <- NA
}
pp <- apply(x.nonmiss, 1, sum)
x <- x[which(pp != 0),]
x.na <- x.na[which(pp != 0),]
x.nonmiss <- x.nonmiss[which(pp != 0),]
sigma <- cov(x)
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
More Example (contd): Partial Mahalanobis distance
Speed results:stopifnot( round(partial_R(x.na, sigma), 7) ==
round(partial_Rcpp(x, x.nonmiss, sigma), 7) )
## n = 1000, p = 3, 10% missingness
benchmark( partial_R(x.na, sigma),
partial_Rcpp(x, x.nonmiss, sigma),
columns=c("test", "replications","elapsed", "relative"),
replications=100, order="relative")
test replications elapsed relative
2 partial_Rcpp(x, x.nonmiss, sigma) 100 0.06 1.0000
1 partial_R(x.na, sigma) 100 17.47 291.1667
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
More Example (contd): Partial Mahalanobis distance
Speed results if we increase our dimension:## n = 1000, p = 10, 10% missingness
test replications elapsed relative
2 partial_Rcpp(x, x.nonmiss, sigma) 100 0.59 1.00000
1 partial_R(x.na, sigma) 100 21.58 36.57627
## n = 1000, p = 25, 10% missingness
test replications elapsed relative
2 partial_Rcpp(x, x.nonmiss, sigma) 100 2.19 1.00000
1 partial_R(x.na, sigma) 100 36.10 16.48402
## n = 1000, p = 50, 10% missingness
test replications elapsed relative
2 partial_Rcpp(x, x.nonmiss, sigma) 100 12.59 1.000000
1 partial_R(x.na, sigma) 100 104.33 8.286736
Question: why the contrast is decreasing?
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Last Speed Example: Matrix multiplication
Best answer so far: [on white board]code <- ’
arma::mat x = Rcpp::as<arma::mat>(X);
int n = as<int>(N);
for (int i=0; i<n; i++)
arma::mat y = x*x;
return R_NilValue;
’
fun_Rcpp <- cxxfunction(signature(X="numeric", N="integer"),
body=code, plugin="RcppArmadillo")
fun_R <- function(x, n) for(i in 1:n) y <- x %*% x return(NULL)
## Simple setup
n <- 1000
p <- 5
x <- matrix(rnorm(p^2), p,p)
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
Last Speed Example: Matrix multiplication
Speed results if we increase our dimension:##n = 1000, p = 3
test replications user.self elapsed relative
1 fun_Rcpp(x, n) 100 0.02 0.02 1.0
2 fun_R(x, n) 100 0.17 0.17 8.5
##n = 1000, p = 10
test replications user.self elapsed relative
1 fun_Rcpp(x, n) 100 0.28 0.28 1.000000
2 fun_R(x, n) 100 0.52 0.51 1.821429
##n = 1000, p = 50
test replications user.self elapsed relative
1 fun_Rcpp(x, n) 100 23.26 24.10 1.000000
2 fun_R(x, n) 100 28.47 34.26 1.421577
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
My first attempt of using Rcpp and RcppArmadillo
More examples:May try slides from Rcpp workshop / master class held by DirkEddelbuettel and Romain Francois
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo
Outline Motivation How to use it? Main Rcpp classes Extending to RcppArmadillo
My first attempt of using Rcpp and RcppArmadillo
Thank you! Any questions?
Andy Leung University of British Columbia
My first attempt of using Rcpp and RcppArmadillo