JJ Allaire
July 1st, 2013
Origins of S
Languages in R and CRAN
Native Code: Problems and Opportunities
Can We Have the Best of Both Worlds?
On May 5th, 1976, a group of users from the statistics research group at Bell Labs discussed creating a new system for statistical computing. Some of the requirements:
Language | Percent |
---|---|
C | 52% |
Fortran | 26% |
R | 22% |
librestats (8/27/11)
Language | Percent |
---|---|
R | 48% |
C/C++ | 46% |
Fortran | 5% |
Perl | 1% |
librestats (8/29/11)
Native Code
Interpeted Code
What's Difficult About C++?
#include <R.h>
#include <Rinternals.h>
SEXP reverse(SEXP x) {
SEXP res;
int i, r, P=0;
PROTECT(res = Rf_allocVector(
REALSXP, Rf_length(x)));
for(i=Rf_length(x), r=0; i>0; i--, r++)
REAL(res)[r] = REAL(x)[i-1];
UNPROTECT(1);
return res;
}
R System/Library Developers
R Users
We can do better for R users!
R users need a system that:
The Rcpp Package
Why “Attributes”?
Interactive C++ with sourceCpp
Some Examples
// Matrix of 4 rows & 5 columns
NumericMatrix xx(4, 5);
// Fill with value
int xsize = xx.nrow() * xx.ncol();
for (int i = 0; i < xsize; i++) {
xx[i] = 7;
}
// Assign to single element
xx(0,1) = 4;
NumericVector x = NumericVector::create(
-2.0, -1.0, 1.0, 2.0);
NumericVector xAbs = abs( x );
NumericVector xCeiling = ceiling( x );
NumericVector xFloor = floor( x );
bool b = all( x < 3.0 ).is_true();
// lookup rnorm function
Environment stats("package:stats");
Function rnorm = stats["rnorm"];
// call rnorm function
rnorm(100,
_["mean"] = 10.2,
_["sd"] = 3.2);
// raise an R error
if (failed)
stop("an unexpected error occurred!");
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double piCpp(int N) {
NumericVector x = runif(N);
NumericVector y = runif(N);
NumericVector d = sqrt(x*x + y*y);
return 4.0 * sum(d < 1.0) / N;
}
> sourceCpp("pi.cpp")
> piCpp(1000)
[1] 3.048
Attributes are annotations added to source code to express intent or automatically generate code (i.e. compiler extensions). They are part of the C++11 standard.
[[omp::parallel]]
void someFunction() {}
In R we use compilers that don't (yet) support C++11, so attributes are added as specially formatted comments:
// [[Rcpp::export]]
sourceCpp
is a function that sources C++ files just as the source
function sources R files[[Rcpp::export]]
attribute are made available to Rset.seed(42)
y <- rnorm(100000)
benchmark(runSumCpp(y, 4500),
runSumR(y, 4500),
order = "relative")[,1:4]
reps time rel
1 runSumCpp(y, 4500) 100 0.082 1.00
2 runSumR(y, 4500) 100 33.717 411.18
http://gallery.rcpp.org/articles/transforming-a-matrix/
sourceCpp("matrix.cpp")
m <- matrix(c(1,2,3, 11,12,13),
nrow = 2, ncol=3)
matrixSqrt(m)
[,1] [,2] [,3]
[1,] 1.000000 1.732051 3.464102
[2,] 1.414214 3.316625 3.605551
http://gallery.rcpp.org/articles/creating-xts-from-c++/
library(xts)
sourceCpp("xts.cpp")
foo <- createXts(1, 4)
foo
[,1]
1970-01-02 1
1970-01-03 2
1970-01-04 3
1970-01-05 4
You can use the [[Rcpp::depends]]
attribute to declare a dependency on an R package.
The inclusion of the [[Rcpp::depends]]
attribute causes sourceCpp
to configure the build environment to compile and link against the package
Dependencies are discovered both by scanning for package include directories and by invoking inline plugins if they are available for a package.
http://gallery.rcpp.org/articles/fast-linear-model-with-armadillo/
[[Rcpp::plugins]]
attribute loads inline plugins Code built with sourceCpp
can be seamlessly moved into packages for sharing with a wider audience via the compileAttributes() function:
Rcpp::compileAttributes()
Scans all C++ files in the src
directory of the package looking for [[Rcpp::export]]
attributes and writes the following files with R and C++ bindings:
R/RcppExports.R
src/RcppExports.cpp
Source file identical to what we'd use with sourceCpp
Need to call compileAttributes
right before building the package
Tools that automatically call compileAttributes
:
Also supports transposing roxygen2 comments
Two talks worth watching to get a flavor for what's happening in modern C++:
Not Your Father's C++ Herb Sutter (Chair, ISO C++ Standards Committee) http://goo.gl/N9YbS
Clang: Defending C++ from Murphy's Million Monkey's
Chandler Carruth (Google)
http://goo.gl/ixNGP
Contains a wealth of articles (all with full source code) demonstrating the use of Rcpp.