[Rcpp-devel] Why inline function is much faster than .Call?

Peng Yu pengyu.ut at gmail.com
Mon Aug 27 18:31:27 CEST 2012


Hi,

The following code shows that inline function is over 10 times faster
than .Call and calling .Call directly is slower than call .Call by
wrapping it in another function. Is this expected?

~/dvcs_src/rexample/Rexample/cran/inline/cxxfunction/dyn.load$ cat test.cpp
#include <Rcpp.h>

RcppExport SEXP test(SEXP bold_eta_theta) {
  using namespace Rcpp;
  NumericMatrix x(bold_eta_theta);
  NumericMatrix result(x.nrow(), x.ncol()+1);

  for(unsigned i = 0; i < x.nrow(); ++ i) {
    double row_max=0;
    for(unsigned j = 0; j < x.ncol(); ++ j) {
      if(x(i, j) > row_max) row_max = x(i, j);
    }
    double row_exp_sum=0;
    for(unsigned j = 0; j < x.ncol(); ++ j) {
      double tmp = exp(x(i, j) - row_max);
      result(i,j) = tmp;
      row_exp_sum += tmp;
    }
    double tmp = exp(-row_max);
    result(i, x.ncol()) = tmp;
    row_exp_sum += tmp;

    for(unsigned j = 0; j < result.ncol(); ++ j) {
      result(i,j) /= row_exp_sum;
    }
  }
  return wrap(result);
}

~/dvcs_src/rexample/Rexample/cran/inline/cxxfunction/dyn.load$ cat main.R
dyn.load('test.so')
test=function(xx) {
  .Call('test', xx)
}

suppressPackageStartupMessages(library(inline))
test_inline=cxxfunction(
  signature(xx='numeric')
  , body='
  Rcpp::NumericMatrix x(xx);
  Rcpp::NumericMatrix result(x.nrow(), x.ncol()+1);

  for(unsigned i = 0; i < x.nrow(); ++ i) {
    double row_max=0;
    for(unsigned j = 0; j < x.ncol(); ++ j) {
      if(x(i, j) > row_max) row_max = x(i, j);
    }
    double row_exp_sum=0;
    for(unsigned j = 0; j < x.ncol(); ++ j) {
      double tmp = exp(x(i, j) - row_max);
      result(i,j) = tmp;
      row_exp_sum += tmp;
    }
    double tmp = exp(-row_max);
    result(i, x.ncol()) = tmp;
    row_exp_sum += tmp;

    for(unsigned j = 0; j < result.ncol(); ++ j) {
      result(i,j) /= row_exp_sum;
    }
  }
  return wrap(result);
  '
  , plugin='Rcpp'
  )


xx=matrix(1:6, nrow=2)

library(microbenchmark)
microbenchmark(test(xx))
microbenchmark(test_inline(xx))
microbenchmark(.Call('test', xx))

~/dvcs_src/rexample/Rexample/cran/inline/cxxfunction/dyn.load$ Rscript main.R
> dyn.load('test.so')
> test=function(xx) {
+   .Call('test', xx)
+ }
>
> suppressPackageStartupMessages(library(inline))
> test_inline=cxxfunction(
+   signature(xx='numeric')
+   , body='
+   Rcpp::NumericMatrix x(xx);
+   Rcpp::NumericMatrix result(x.nrow(), x.ncol()+1);
+
+   for(unsigned i = 0; i < x.nrow(); ++ i) {
+     double row_max=0;
+     for(unsigned j = 0; j < x.ncol(); ++ j) {
+       if(x(i, j) > row_max) row_max = x(i, j);
+     }
+     double row_exp_sum=0;
+     for(unsigned j = 0; j < x.ncol(); ++ j) {
+       double tmp = exp(x(i, j) - row_max);
+       result(i,j) = tmp;
+       row_exp_sum += tmp;
+     }
+     double tmp = exp(-row_max);
+     result(i, x.ncol()) = tmp;
+     row_exp_sum += tmp;
+
+     for(unsigned j = 0; j < result.ncol(); ++ j) {
+       result(i,j) /= row_exp_sum;
+     }
+   }
+   return wrap(result);
+   '
+   , plugin='Rcpp'
+   )
>
>
> xx=matrix(1:6, nrow=2)
>
> library(microbenchmark)
> microbenchmark(test(xx))
Unit: microseconds
      expr                     min                      lq
     median                      uq                     max
1 test(xx) 69.51999999999999602096 70.02899999999999636202
72.79200000000000159162 73.49150000000000204636
196.9259999999999877218
> microbenchmark(test_inline(xx))
Unit: microseconds
             expr                     min                      lq
            median                      uq                     max
1 test_inline(xx) 4.413999999999999701572 4.633000000000000007105
4.749500000000000277112 4.894000000000000127898
74.78600000000000136424
> microbenchmark(.Call('test', xx))
Unit: microseconds
               expr                    min                      lq
             median                      uq                     max
1 .Call("test", xx) 95.9890000000000043201 96.81999999999999317879
100.1795000000000044338 101.0649999999999977263
211.9449999999999931788
>
>


-- 
Regards,
Peng


More information about the Rcpp-devel mailing list