[Rcpp-devel] Linking to c++ files in a package without Rcpp overhead for faster computation
JJ Allaire
jj.allaire at gmail.com
Fri Mar 6 23:09:44 CET 2015
The overhead comes from the fact that the parameters are converted
to/from SEXP and pushed through a C interface. There's also overhead
that's associated with error checking, etc. This is a fixed overhead
so as more work gets done inside your C++ function the % overhead will
approach zero.
In terms of re-using code across packages, everything in your
inst/include directory is automatically added to the include search
path of any package that has a LinkingTo relationship to yours (and to
any sourceCpp module that does an Rcpp::depends on it). No absolute
paths are therefore necessary (R resolves the path to your package at
build time).
If you want to re-use Rcpp code across packages the most
straightforward way to do it is inside a header file (this has no
linking or associated C interface overhead, and has no versioning
problems). You can just define your function with the 'inline' keyword
and it can be re-used in an arbitrary number of other C++ files with
no linker conflicts.
J.J.
On Fri, Mar 6, 2015 at 5:03 PM, John Tipton <jtipton25 at gmail.com> wrote:
> Hey Rcpp developers,
>
> I am brand spanking new to the Rcpp community and I want to introduce myself
> with what is likely a very simple question that I haven't found an answer
> for yet. My question is on package development and linking c++ files from
> one package directly to another package without having to create a CCallable
> function . As a relatively experienced R programmer but novice c++
> programmer, I am still learning as I go so I created a minimal example below
> that I believe better illustrates my question.
>
> I am building a package with RStudio and I want to make available to another
> package the .h header files - (more explicitly the c++ subroutines in those
> headers) without the loss of computation speed shown below.
>
> My question can best be summarized with two parts
>
> 1) Why when I directly source testPack.h is the function call so much slower
> than when I define the function in the same .cpp file (i.e. why is fun1.cpp
> so much slower (~40%) than fun2.cpp in test.R)
>
> 2) How do I build a library in an automated fashion (maybe there is a
> CPPFLAGS variable?) so I can use the functionality of something like
> #include “path/to/file/hello_world2.h” in fun2.cpp without using an absolute
> path? I am building a large MCMC sampler so every bit of marginal speed gain
> is important. In other words, how can I replicate the behavior of fun2.cpp
> in a function that sources my library testPack
>
>
> I have the following files (outside my package) that provide testing. Thanks
> for any help.
>
> test.R
> fun1.cpp <- includes <testPack.h> header, runs slow
> fun2.cpp <- includes “hello_world2.h” header, runs faster
>
> I built a package skeleton in RStudio using Rcpp. Within the src directory I
> have the files
> hello_world2.h
> cpp_hello_world.cpp
>
>
> The files are as follows
> ##
> ##
> ##
> ———— begin test.R script ————
>
> library(rbenchmark)
> n <- 10000
> Rcpp::sourceCpp('~/test/fun1.cpp’)
> Rcpp::sourceCpp('~/test/fun2.cpp’)
>
> benchmark(fun1(n), fun2(n), replications = 500)
>
> ———— end test.R script ————
> ##
> ##
> ##
> ———— begin fun1.cpp ————
>
> #include <RcppArmadillo.h>
> #include <testPack.h>
> // [[Rcpp::depends(testPack)]]
> // [[Rcpp::depends(RcppArmadillo)]]
>
> //using namespace Rcpp;
>
> //[[Rcpp::export]]
> void fun1(const int& n) {
> for(int i = 0; i < n; i++){
> testPack::rcpp_hello_world();
> }
> }
>
> ———— end fun1.cpp ————
> ##
> ##
> ##
> ———— begin fun2.cpp ————
>
> #include <RcppArmadillo.h>
> #include <path/to/file/testPack/src/hello_world2.h>
>
> // [[Rcpp::depends(RcppArmadillo)]]
>
> //[[Rcpp::export]]
> void fun2(const int& n) {
> for(int i = 0; i < n; i++){
> rcpp_hello_world2();
> }
> }
>
> ———— end fun2.cpp ————
> ##
> ##
> ##
> ———— begin hello_world2.h ————
>
> Rcpp::List rcpp_hello_world2() {
>
> Rcpp::CharacterVector x = Rcpp::CharacterVector::create("foo", "bar");
> Rcpp::NumericVector y = Rcpp::NumericVector::create(0.0, 1.0);
> Rcpp::List z = Rcpp::List::create(x, y);
>
> return z ;
> }
>
> ———— end hello_world2.h ————
> ##
> ##
> ##
> ———— begin rcpp_hello_world.cpp ————
>
> #include <RcppArmadillo.h>
>
> // [[Rcpp::depends(RcppArmadillo)]]
> // [[Rcpp::interfaces(cpp)]]
>
> using namespace Rcpp;
>
> //[[Rcpp::export]]
> List rcpp_hello_world() {
>
> CharacterVector x = CharacterVector::create( "foo", "bar" ) ;
> NumericVector y = NumericVector::create( 0.0, 1.0 ) ;
> List z = List::create( x, y ) ;
>
> return z ;
> }
>
> ———— end rcpp_hello_world.cpp ————
>
> _______________________________________________
> Rcpp-devel mailing list
> Rcpp-devel at lists.r-forge.r-project.org
> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
More information about the Rcpp-devel
mailing list