R / C++
Romain François
romain@r-enthusiasts.com
@romain_francois
• Use R since 2002
• Consultant
• Rcpp since 2010
• Rcpp11 since last
september
• C++ for performance
• Occasional comedy
Agenda
• R and C++
• Rcpp11
Success of Rcpp
• Thin wrapper around R/C api
• Users focus on what!
• Rcpp handles how
Example 1: Shiny
Example 2: dplyr
hflights %>%
group_by(Year, Month, DayofMonth) %>%
select(Year:DayofMonth, ArrDelay, DepDelay) %>%
summarise(
arr = mean(ArrDelay, na.rm = TRUE),
dep = mean(DepDelay, na.rm = TRUE)
) %>%
filter(arr > 30 | dep > 30)
int add( int a, int b){
return a + b ;
}
#include <Rcpp.h>
!
// [[Rcpp::export]]
int add( int a, int b){
return a + b ;
}
sourceCpp
#include <Rcpp.h>
!
// [[Rcpp::export]]
int add( int a, int b){
return a + b ;
}
> sourceCpp( "add.cpp" )
> add( 2L, 3L)
[1] 5
R data -> Rcpp classes
• vectors: NumericVector, IntegerVector, …
• lists: List
• functions: Function
• environments: Environment
• …
Rcpp objects are proxies
to R data structures
No additional memory
Example: NumericVector
// [[Rcpp::export]]
double sum( NumericVector x){
int n = x.size() ;
!
double res = 0.0 ;
for( int i=0; i<n; i++){
res += x[i] ;
}
!
return res ;
}
Example : lists
List res = List::create(
_["a"] = 1,
_["b"] = "foo"
);


res.attr( "class" ) = "myclass" ; !

int a = res["a"] ;

res["b"] = 42 ;
Example: R function
Function rnorm( "rnorm" ) ;
!
NumericVector x = rnorm(
10,
_["mean"] = 30,
_["sd"] = 100
);
Rcpp11
Rcpp11
• C++ = C++11
• Smaller code base (than Rcpp)
• Header only
#include <Rcpp.h>
!
// [[Rcpp::export]]
int foo(){
return 2 ;
}
Rcpp
Rcpp11
0 1 2 3
Less code -> faster compiles
!
Interface simplification
NumericVector constructors
Vector() {
Vector( const Vector& other){
Vector( SEXP x ) {
!
Vector( const GenericProxy<Proxy>& proxy ){
explicit Vector( const no_init& obj) {
Vector( const int& size, const stored_type& u ) {
Vector( const std::string& st ){
Vector( const char* st ) {
Vector( const int& siz, stored_type (*gen)(void) ) {
Vector( const int& size ) {
Vector( const Dimension& dims) {
Vector( const Dimension& dims, const U& u) {
Vector( const VectorBase<RTYPE,NA,VEC>& other ) {
Vector( const int& size, const U& u) {
Vector( const sugar::SingleLogicalResult<NA,T>& obj ) {
Vector( const int& siz, stored_type (*gen)(U1), const U1& u1) {
Vector( const int& siz, stored_type (*gen)(U1,U2), const U1& u1, const U2& u2) {
Vector( const int& siz, stored_type (*gen)(U1,U2,U3), const U1& u1, const U2& u2, const U3& u3) {
Vector( InputIterator first, InputIterator last){
Vector( InputIterator first, InputIterator last, int n) {
Vector( InputIterator first, InputIterator last, Func func) {
Vector( InputIterator first, InputIterator last, Func func, int n){
Vector( std::initializer_list<init_type> list ) {
23 constructors in Rcpp
NumericVector constructors
11 constructors in Rcpp
Vector(){
Vector( const Vector& other){
Vector( Vector&& other){
!
explicit Vector(int n) {
explicit Vector(R_xlen_t n) {
!
Vector( R_xlen_t n, value_type x ) {
Vector( std::initializer_list<value_type> list ){
Vector( std::initializer_list<traits::named_object<value_type>> list ){
!
Vector( const SugarVectorExpression<eT, Expr>& other ) {
Vector( const LazyVector<RT,Expr>& other ) {
Vector( const GenericProxy<Proxy>& proxy ){
NumericVector constructors
Vector( const int& siz, stored_type (*gen)(U1), const U1& u1) -> replicate
double fun( int power ){
return pow(2.0, power) ;
}
!
// Rcpp
NumericVector x(10, fun, 10.0) ;
// Rcpp11
NumericVector x = replicate(10, fun, 10.0) ;
NumericVector constructors
std::vector<double> v = /* ... */ ;
!
// Rcpp
NumericVector x(v.begin(), v.end()) ;
// Rcpp11
NumericVector x = import(begin(v), end(v)) ;
NumericVector x = import(v) ;
Vector( InputIterator first, InputIterator last) -> import
Some examples
NumericVector ctors
// C++ uniform initialization
NumericVector x = {1.0, 2.0, 3.0} ;
!
// init with given size
NumericVector y( 2 ) ; // data is not initialized
NumericVector y( 2, 3.0 ) ; // initialize all to 3.0
!
// fuse several vectors (similar to c in R)
NumericVector z = fuse(x, y) ;
NumericVector z = fuse(x, y, 3.0) ;
create
// old school NumericVector::create (Rcpp style).
NumericVector x = NumericVector::create(1.0, 2.0, 3.0) ;
NumericVector x = NumericVector::create(
_["a"] = 1.0, _["b"] = 2.0, _["c"] = 3.0
) ;
!
!
// create as a free function. Rcpp11 style
NumericVector x = create(1.0, 2.0, 3.0) ;
NumericVector x = create(
_["a"] = 1.0, _["b"] = 2.0, _["c"] = 3.0
) ;
sapply + lambda
sapply + lambda
#include <Rcpp11>
!
// [[export]]
NumericVector foo( NumericVector x ){
return sapply(x, [](double d){
return exp(d * 2) ;
});
}
x <- 1:3
sapply( x, function(d){
exp(d*2) ;
})
sapply + lambda + …
#include <Rcpp11>
!
// [[export]]
NumericVector foo( NumericVector x ){
auto fun = [](double d, double y, double z){
return exp(d * y) + z ;
} ;
return sapply(x, fun, 3.0, 4.6);
}
x <- 1:3
sapply( x, function(d, y, z){
exp(d*y) + z ;
}, 3.0, 4.6 )
Rcpp11 release cycle
• Available from CRAN:
!
• Evolves quickly. Get it from github
!
• Next Release: 3.1.1 (same time as R 3.1.1) in a
few days (I've been travelling)
> install.packages( "Rcpp11" )
> install_github( "Rcpp11/Rcpp11" )
attributes companion package
• Standalone impl of Rcpp attributes
[[Rcpp::export]], sourceCpp, compileAttributes
!
• Only available from github:
> install_github( "Rcpp11/attributes" )
Use Rcpp11 in your package
• Write your .cpp files
#include <Rcpp11>
!
// [[export]]
void foo( … ) { … } // your code
SystemRequirements: C++11
LinkingTo: Rcpp11
library(attributes)
compileAttributes( "mypkg" )
• Express dep on C++11 and Rcpp11 headers
• Generate the boiler plate
Header only
• No runtime dependency
!
• Snapshot the code base
!
• Better control for package authors
Romain François
romain@r-enthusiasts.com @romain_francois
Questions ?

Rcpp11 genentech

  • 1.
    R / C++ RomainFrançois romain@r-enthusiasts.com @romain_francois
  • 9.
    • Use Rsince 2002 • Consultant • Rcpp since 2010 • Rcpp11 since last september • C++ for performance • Occasional comedy
  • 13.
    Agenda • R andC++ • Rcpp11
  • 17.
    Success of Rcpp •Thin wrapper around R/C api • Users focus on what! • Rcpp handles how
  • 18.
  • 19.
    Example 2: dplyr hflights%>% group_by(Year, Month, DayofMonth) %>% select(Year:DayofMonth, ArrDelay, DepDelay) %>% summarise( arr = mean(ArrDelay, na.rm = TRUE), dep = mean(DepDelay, na.rm = TRUE) ) %>% filter(arr > 30 | dep > 30)
  • 20.
    int add( inta, int b){ return a + b ; }
  • 22.
    #include <Rcpp.h> ! // [[Rcpp::export]] intadd( int a, int b){ return a + b ; }
  • 23.
    sourceCpp #include <Rcpp.h> ! // [[Rcpp::export]] intadd( int a, int b){ return a + b ; } > sourceCpp( "add.cpp" ) > add( 2L, 3L) [1] 5
  • 24.
    R data ->Rcpp classes • vectors: NumericVector, IntegerVector, … • lists: List • functions: Function • environments: Environment • …
  • 25.
    Rcpp objects areproxies to R data structures No additional memory
  • 26.
    Example: NumericVector // [[Rcpp::export]] doublesum( NumericVector x){ int n = x.size() ; ! double res = 0.0 ; for( int i=0; i<n; i++){ res += x[i] ; } ! return res ; }
  • 27.
    Example : lists Listres = List::create( _["a"] = 1, _["b"] = "foo" ); 
 res.attr( "class" ) = "myclass" ; !
 int a = res["a"] ;
 res["b"] = 42 ;
  • 28.
    Example: R function Functionrnorm( "rnorm" ) ; ! NumericVector x = rnorm( 10, _["mean"] = 30, _["sd"] = 100 );
  • 29.
  • 30.
    Rcpp11 • C++ =C++11 • Smaller code base (than Rcpp) • Header only
  • 32.
    #include <Rcpp.h> ! // [[Rcpp::export]] intfoo(){ return 2 ; } Rcpp Rcpp11 0 1 2 3 Less code -> faster compiles
  • 33.
  • 34.
    NumericVector constructors Vector() { Vector(const Vector& other){ Vector( SEXP x ) { ! Vector( const GenericProxy<Proxy>& proxy ){ explicit Vector( const no_init& obj) { Vector( const int& size, const stored_type& u ) { Vector( const std::string& st ){ Vector( const char* st ) { Vector( const int& siz, stored_type (*gen)(void) ) { Vector( const int& size ) { Vector( const Dimension& dims) { Vector( const Dimension& dims, const U& u) { Vector( const VectorBase<RTYPE,NA,VEC>& other ) { Vector( const int& size, const U& u) { Vector( const sugar::SingleLogicalResult<NA,T>& obj ) { Vector( const int& siz, stored_type (*gen)(U1), const U1& u1) { Vector( const int& siz, stored_type (*gen)(U1,U2), const U1& u1, const U2& u2) { Vector( const int& siz, stored_type (*gen)(U1,U2,U3), const U1& u1, const U2& u2, const U3& u3) { Vector( InputIterator first, InputIterator last){ Vector( InputIterator first, InputIterator last, int n) { Vector( InputIterator first, InputIterator last, Func func) { Vector( InputIterator first, InputIterator last, Func func, int n){ Vector( std::initializer_list<init_type> list ) { 23 constructors in Rcpp
  • 35.
    NumericVector constructors 11 constructorsin Rcpp Vector(){ Vector( const Vector& other){ Vector( Vector&& other){ ! explicit Vector(int n) { explicit Vector(R_xlen_t n) { ! Vector( R_xlen_t n, value_type x ) { Vector( std::initializer_list<value_type> list ){ Vector( std::initializer_list<traits::named_object<value_type>> list ){ ! Vector( const SugarVectorExpression<eT, Expr>& other ) { Vector( const LazyVector<RT,Expr>& other ) { Vector( const GenericProxy<Proxy>& proxy ){
  • 36.
    NumericVector constructors Vector( constint& siz, stored_type (*gen)(U1), const U1& u1) -> replicate double fun( int power ){ return pow(2.0, power) ; } ! // Rcpp NumericVector x(10, fun, 10.0) ; // Rcpp11 NumericVector x = replicate(10, fun, 10.0) ;
  • 37.
    NumericVector constructors std::vector<double> v= /* ... */ ; ! // Rcpp NumericVector x(v.begin(), v.end()) ; // Rcpp11 NumericVector x = import(begin(v), end(v)) ; NumericVector x = import(v) ; Vector( InputIterator first, InputIterator last) -> import
  • 38.
  • 39.
    NumericVector ctors // C++uniform initialization NumericVector x = {1.0, 2.0, 3.0} ; ! // init with given size NumericVector y( 2 ) ; // data is not initialized NumericVector y( 2, 3.0 ) ; // initialize all to 3.0 ! // fuse several vectors (similar to c in R) NumericVector z = fuse(x, y) ; NumericVector z = fuse(x, y, 3.0) ;
  • 40.
    create // old schoolNumericVector::create (Rcpp style). NumericVector x = NumericVector::create(1.0, 2.0, 3.0) ; NumericVector x = NumericVector::create( _["a"] = 1.0, _["b"] = 2.0, _["c"] = 3.0 ) ; ! ! // create as a free function. Rcpp11 style NumericVector x = create(1.0, 2.0, 3.0) ; NumericVector x = create( _["a"] = 1.0, _["b"] = 2.0, _["c"] = 3.0 ) ;
  • 41.
  • 42.
    sapply + lambda #include<Rcpp11> ! // [[export]] NumericVector foo( NumericVector x ){ return sapply(x, [](double d){ return exp(d * 2) ; }); } x <- 1:3 sapply( x, function(d){ exp(d*2) ; })
  • 43.
    sapply + lambda+ … #include <Rcpp11> ! // [[export]] NumericVector foo( NumericVector x ){ auto fun = [](double d, double y, double z){ return exp(d * y) + z ; } ; return sapply(x, fun, 3.0, 4.6); } x <- 1:3 sapply( x, function(d, y, z){ exp(d*y) + z ; }, 3.0, 4.6 )
  • 44.
    Rcpp11 release cycle •Available from CRAN: ! • Evolves quickly. Get it from github ! • Next Release: 3.1.1 (same time as R 3.1.1) in a few days (I've been travelling) > install.packages( "Rcpp11" ) > install_github( "Rcpp11/Rcpp11" )
  • 45.
    attributes companion package •Standalone impl of Rcpp attributes [[Rcpp::export]], sourceCpp, compileAttributes ! • Only available from github: > install_github( "Rcpp11/attributes" )
  • 46.
    Use Rcpp11 inyour package • Write your .cpp files #include <Rcpp11> ! // [[export]] void foo( … ) { … } // your code SystemRequirements: C++11 LinkingTo: Rcpp11 library(attributes) compileAttributes( "mypkg" ) • Express dep on C++11 and Rcpp11 headers • Generate the boiler plate
  • 47.
    Header only • Noruntime dependency ! • Snapshot the code base ! • Better control for package authors
  • 48.