[Rcpp-devel] Cost of function pointer dereferencing

Davor Cubranic cubranic at stat.ubc.ca
Fri Dec 24 18:26:11 CET 2010


Thanks for prompting me to start experimenting with inline and finer 
points of C++! It's something I've wanted to do for a while. I'm glad 
you find it useful, this whole template stuff is still pretty new to me. 

Davor

On December 24, 2010 03:08:36 am romain at r-enthusiasts.com wrote:
> Thanks. I'll use that.
> 
>  Le jeu 23/12/10 22:51, "Davor Cubranic" cubranic at stat.ubc.ca a écrit:
> > After a bit of googling, I figured out how to write the templated
> > functor. It's very simple:
> > incw <- '
> > template<double Func(double) >
> > struct Ftor {
> > inline double operator () (double x) const {
> > return Func(x);
> > }
> > };
> > Ftor<exp> ftor;
> > '
> > fw <- cxxfunction( , '
> > double x ;
> > for( int j=0; j<1000; j++){
> > for( int i=0; i<1000000; i++){
> > x = ftor(2.0) ;
> > }
> > }
> > return wrap( x ) ;
> > ', plugin = "Rcpp", includes = incw , verbose=TRUE)
> > 
> > And it's still (insignificantly) faster than the static call:
> > 
> > test replications elapsed  relative user.self sys.self user.child
> > 3 functor            1   0.463  1.000000     0.464    0.001        
> >  0 1  static            1   0.468  1.010799     0.464    0.000    
> >      0 2 pointer            1  15.960 34.470842    15.824    0.017
> >          0
> > 
> > Davor
> > 
> > On 2010-12-23, at 9:54 AM, Davor Cubranic wrote:
> > > I tried using a functor, calling 'exp' in its
> > 
> > operator(), and it was even faster than static (albeit very
> > 
> > slightly):
> > >      test replications elapsed  relative user.self
> > 
> > sys.self user.child
> > 3  functor            1   0.465  1.000000     0.464
> > 
> >   0.000          0
> > 
> > 1   static            1   0.472  1.015054     0.464
> > 
> >   0.001          0
> > 
> > 2  pointer            1  15.855 34.096774    15.815
> > 
> >   0.007          0
> >   
> > > Just add 'fw' below to your benchmark:
> > > 
> > > incw <- '
> > > 
> > >   class Ftor {
> > >   
> > >   public:
> > >     inline double operator () (double x) const
> > 
> > {
> > 
> >       return exp(x);
> >       
> > >     }
> > >   
> > >   };
> > >   const Ftor ftor = Ftor();
> > > 
> > > '
> > > fw <- cxxfunction( , '
> > > double x ;
> > > for( int j=0; j<1000; j++){
> > > for( int i=0; i<1000000; i++){
> > > 
> > >   x = ftor(2.0) ;
> > > 
> > > }
> > > }
> > > return wrap( x ) ;
> > > ', plugin = "Rcpp", includes = incw ,
> > 
> > verbose=TRUE)
> > 
> > > Maybe you could create a functor for each basic
> > 
> > function and use that in a common loop implementation.
> > 
> > > I also tried templatizing Ftor on the function it
> > 
> > delegates to, so that you could do something like Ftor<exp>(), but
> > I couldn't get it to compile. Your template-fu is far better than
> > mine, so maybe you'll be able to wrangle it into shape and have
> > even more succint code.
> > 
> > > Davor
> > > 
> > > 
> > > On 2010-12-23, at 8:45 AM, <roma
> > 
> > in at r-enthusiasts.com> <roma
> > 
> > in at r-enthusiasts.com> wrote:
> > >> Hello,
> > >> 
> > >> Since I've been playing with efficiency of
> > 
> > various operators for numeric vectors (+,-,/,*), I'm now looking at
> > other functions such as exp, sqrt, etc ...
> > 
> > >> The way we currently implement exp for vectors
> > 
> > requires that we keep a function pointer for the atomic exp and
> > that we dereference the function pointer each time. It turns out
> > that this has some
> > 
> > cost :
> > >>    test replications elapsed relative user.self
> > 
> > sys.self user.child sys.child
> > 
> >> 1  static            1   0.691  1.00000
> > 
> > 0.691    0.000          0         0
> > 
> >> 2 pointer            1  11.157 16.14616
> > 
> > 11.144    0.012          0         0
> > 
> > >> Reproduced by this code:
> > >> 
> > >> require( Rcpp )
> > >> require( inline )
> > >> 
> > >> fx <- cxxfunction( , '
> > >> double x ;
> > >> for( int j=0; j<1000; j++){
> > >> for( int i=0; i<1000000; i++){
> > >> 
> > >>   x = exp(2.0) ;
> > >> 
> > >> }
> > >> }
> > >> return wrap( x ) ;
> > >> ', plugin = "Rcpp" )
> > >> 
> > >> inc <- '
> > >> 
> > >>   double (*fun)(double) = exp ;
> > >> 
> > >> '
> > >> fy <- cxxfunction( , '
> > >> double x ;
> > >> for( int j=0; j<1000; j++){
> > >> for( int i=0; i<1000000; i++){
> > >> 
> > >>   x = (*fun)(2.0) ;
> > >> 
> > >> }
> > >> }
> > >> return wrap( x ) ;
> > >> ', plugin = "Rcpp", includes = inc )
> > >> 
> > >> 
> > >> require( rbenchmark )
> > >> benchmark(
> > >> 
> > >>   order = "relative",
> > >>   static = fx(),
> > >>   pointer = fy(),
> > >>   replications = 1L
> > >> 
> > >> )
> > >> 
> > >> Romain
> > 
> > _______________________________________________
> > 
> >> Rcpp-devel mailing list
> >> 
> > >> Rcpp-devel at lists.r-forge.r-project.org
> >> 
> >> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rc
> > 
> > pp-devel
> > 
> > 
> > _______________________________________________
> > Rcpp-devel mailing list
> > 
> > > Rcpp-devel at lists.r-forge.r-project.org
> > 
> > https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rc
> > pp-devel


More information about the Rcpp-devel mailing list