[Rcpp-devel] R.e. First foray into Rcpp and comparison of speed with R

Darren Cook darren at dcook.org
Sat Sep 3 03:54:03 CEST 2011


> There is a noNA() wrapper for Rcpp sugar to push performance -- NA checking
> is implemented on access 'because that is how R does' (and our first task to
> reproduce numbers you'd get at the R prompt) but if you know what you are
> doing and are aware of possible pitfalls you can skip this. See
> inst/examples/ConvolveBenchmarks/ and particularly convolve11_cpp.cpp.

That file has this line:
   xab[ r ] += noNA(xa[i]) * noNA(xb) ;

noNA() creates a Nona object, which basically returns a direct pointer
to the data, not going through the R access mechanism. I got lost in the
source at that point and could not find where the NA check actually
takes place. Is it back in the R core?

Anyway, I extended Christian Gunning's example with a noNA version
[1], then an STL version [2] that uses std::vector, then a C/C++ pointer
version [3]. [4] shows my compiler options (all defaults).

        test replications elapsed relative user.self
     bracket           50   5.151 1.001556      5.14
 bracket_cpp           50   5.145 1.000389      5.13
bracket_noNA           50   5.144 1.000194      5.14
 bracket_stl           50   5.143 1.000000      5.14
      parens           50  44.815 8.713786     44.80


I upped the repetitions to 50 and shutdown a few apps on my computer
during the test run to get better results. The stl version is
consistently fastest, but basically there is nothing to choose between them.

Surprisingly the cpp version is consistently slower than the stl
version, though only by a fraction each time. Definitely nothing to
justify the extra fragility (see the "Best way to return raw array" thread).

Darren


[1]:
src1na<-'
int nn=as<int>(n);
NumericVector ret(nn);
for (int i=0; i<nn; i++) {
    for (int j=0; j<nn; j++) {
        ret[i] = noNA( ret[i] )+1;
    }
};
return(ret);
'

[2]:
src1stl<-'
int nn=as<int>(n);
std::vector<double> ret(nn);
for (int i=0; i<nn; i++) {
    for (int j=0; j<nn; j++) {
        ret[i] = ret[i] +1;
    }
};
return wrap(ret);
'

[3]:
src1cpp<-'
int nn=as<int>(n);
double *p=new double[nn];
for (int i=0; i<nn; i++) {
    double *q=&p[i];
    *q=0;   //Because new[] does not initialize memory
    for (int j=0; j<nn; j++) {
        *q=*q+1;
    }
};
NumericVector ret(p,p+nn);
delete[] p;
return ret;
'

[4]:
g++ -I/usr/share/R/include
-I"/usr/local/lib/R/site-library/Rcpp/include"   -fpic  -O3 -pipe  -g -c
file731577fd.cpp -o file731577fd.o
g++ -shared -o file731577fd.so file731577fd.o
-L/usr/local/lib/R/site-library/Rcpp/lib -lRcpp
-Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib -L/usr/lib64/R/lib -lR

gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)



-- 
Darren Cook, Software Researcher/Developer

http://dcook.org/work/ (About me and my work)
http://dcook.org/blogs.html (My blogs and articles)


More information about the Rcpp-devel mailing list