Hello, I’m a student and my lab is developing an R package that uses RStan.
We’re trying to refactor the package structure, to go with that suggested by rstantools(v 1.5.1).
I’ve read the rstantools vignettes, and used the rstan_package_skeleton to create the basic directories and files.
I understand that RStan works like this: stan files are first translated to c++ code, then it is compiled into dso objects that can now be used to draw samples with.
I wonder what would be the way to provide “pre-translated” c++ code to the users.
Would it just be as simple as including the created .hpp files within the package before distributing the package? Or would I also need to edit some lines of code to make it use the pre-translated hpp files (instead of translating the raw stan files again)?
I’ve been trying to figure this out on my own, reading the code of stanc() and make_cc.R and others, but I just couldn’t wrap my head around which line of code it is I should be looking for.
Also, would including pre-translated c++ files in the package be recommended?
To my understanding the rstanarm package is not doing that, and instead translates and compiles all its stan files during package installation.
on each of your .stan files. The tools/make_cc.R file calls rstan::stanc to generate the C++ code implied by the Stan program and calls Rcpp::exposeClass to create the corresponding C++ class that can be called by the Modules mechanism in the Rcpp package. Once these .cc files are created, make then compiles them into a shared object that is included in the binary packages for Windows and Mac on CRAN.
So, you are probably thinking too long about something that does not need to be thought about that much. But if what you are really asking is “How can I include regular C++ code alongside the C++ code that is generated from the Stan programs?”, apparently that is now better supported by the aforementioned branch of rstantools and you basically just put your regular C++ code into src/ perhaps best with a .cpp extension.
So, would I have understood it correctly if I were to say:
The stan files in src/stan_files are passed through stanc() which generates C++ codes, which are then passed through exposeClass() to create Rcpp modules. (All of which are done by invoking make_cc.)
And then, R/stanmodels.R would create a list stanmodels that is a list of stanmodel class objects, which have a mk_cppmodule field to which the previously created Rcpp modules are each assigned?
Yes, I think that is right. But if it is wrong in some respect, it doesn’t really matter. For one thing, with the next version of rstantools, then Stan programs get put under inst/ . It took us a while to figure out how to get rstanarm to build, but once we incorporated that process into rstantools a lot of other people were able to copy it without knowing much more than
Write good Stan programs
Write wrapper functions that call sampling on those stanmodels that are in the stanmodels list
I’ve been meaning to post about this for some time but moved on to other things and forgot about it.
A few months ago I was developing a package using Stan and got frustrated with how the rstantools build process converts Stan to C++ files on the fly, and has to use complicated dynamic loading of the DSO.
So I modified the process and wrote a little package called stanmodularise with the following approach based on pre-translating the C++ files:
You write some Stan files in src/stan_files
You run modularise_stan_files() on your package (like devtools::document or Rcpp::compileAttributes). This creates header and C++ files in src/.
You compile/load/install with devtools::document/load_all/install as usual. If you update a stan file, you have to re-run modularise_stan_files() before recompiling
The advantages of this are: faster package recompilation, you don’t have to use local = FALSE, and the module loading process is simpler and more robust because it doesn’t use the dynamic loading step to discover the contents of the DSO (Rcpp attributes are used to register the model code instead).
The disadvantage is you have to remember to re-run modularise_stan_files() if you change a Stan model.
The package doesn’t do the nice things rstantools does like add to the LinkingTo, Makevars, etc, yet, because I figured it would be better contribute this to rstantools. Maybe this will do what you need, or at least provide a basis for an extension to rstantools. I also haven’t touched this since the C++14 changes.
I wouldn’t mind doing some work to add it to rstantools if it was considered useful, but it is quite a different approach and I wouldn’t presume to claim that it’s better overall; I just found it suited my projects a bit better.