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
}
};
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 ,
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
2 pointer 1 11.157 16.14616
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