Friday, March 15, 2013

Rcpp in NYC

Yesterday Dirk Eddelbuettel graced NYC with his presence to give a full-day workshop on Rcpp.  It was an epic in four parts (I, II, III, and IV).  I'm in the middle of putting some MCMC algorithms for mark-recapture movement data into a C++ library and writing the R interface so I thought it would be worth the effort to get down there and drink from the source of Rcpp knowledge. The source turned out to be a fire-hose, but Jared Lander plied us with bagels and Indian food (the Indian was my suggestion, but not as good as I remembered it) which helped with the endurance aspect. 

Interestingly, the overall content of the workshop was oriented toward people who had not committed much time to trying to figure out Rcpp and its associated tools on their own. Personally I would not spend that kind of money on a workshop if I weren't prepared to get the best return out of it, but hey, it's NYC. You can find $500 on the street*. Anyway, even if you walked in knowing only that you needed to interface R to a C++ library or just some small fast C++ function, you would have walked out happy.
 Some of the materials were old news to me but I did bring a long list of questions and Dirk tolerated them quite well.

The ones I asked were:

Q: I have a little personal library which creates objects (via "new") to encapsulate certain computations.  How do I make sure those don't disappear on me while I'm using them through R?  

A: Sounds like passing a pointer back to R (using Rcpp::XPtr) works and it won't have delete called on it till you 'rm' the object on the R side (assuming the destructor does the right thing.  That's my approach and it has Dirk's blessing. 

Q: How do I find out what "sugar" is available?

A: Headers.  Specifically for me:
It's on the obvious side but I didn't think to do it because it didn't work for as/wrap.

Q: How do I find out what's available for "Rcpp:as/wrap".

A: Headers... but they're not nearly as readable as the "sugar" headers.  I can confirm the "not as readable part"!  Dirk did do a thorough job of discussing how to write template specializations (part II, p. 38) for the as/wrap functions  which I am planning on using.  Neat thing is that these can be part of an R package which contains the interface to the C++ library, you don't need to modify the library itself.

Q: How do I convert an SEXP containing a nested list into nested std lib vectors?

A: Write template specializations for Rcpp::as/wrap (I'm on it!)

Some stuff which became obvious during the course of the talk:

Q: Best practises for using RNGScope?

A: Declare at the beginning of each code block which draws the random numbers.  It's a cheap operation.  This is not that relevant for me since I've been relying on TRNG (I don't want to link my code too heavily to R, I just want a wrapper).

Q: What's the scope of use for the "inline" package?

A: One to many small independent function which encapsulate operations.  I wouldn't use it for multiple objects which need to interact, it would just get to messy (to me!  maybe others have more tolerance for that).

Q: How do I write an interface to a class hierarchy, since I'm returning to R using RcppExport?

A: Rcpp::XPtr to the base class... and go from there.  There's probably a better answer but after Dirk's talk it became obvious I could turn my hierarchy into a bunch of smaller better-defined classes and avoid a lot of pain...

Another neat part of Rcpp is that  (depending on how the conversion from SEXP is handled, Rcpp's types are thin wrappers so changes to the vector cause changes in the R object visible from R (unless you use Rcpp::clone(x) to trigger a deep copy.  It's great if you want to run C++ functions on big objects you'd rather not copy and a likely pitfall for new Rcpp users. 

The presentation also had a really good discussion of Rcpp modules (part III, p. 64).  It lets you add some code to your C++ files which causes the interface functions for R to be generated automatically.  Seems really useful if you have a well developed interface at the C++ level but I'd rather do that (all my argument checking for type and consistency) at the R level.  Also seems great for very well defined small functions/classes which just need to be hooked to R fast.

After returning I took the opportunity to rewrite much of my (little) code to make it easier to test/maintain and having a clear idea of how to use Rcpp was key to this so I think my little trip down to NYC was time well spent for me**.

* Just don't ask why it's there.
** Also, the people, the people were very nice.

No comments:

Post a Comment