[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