stanc compiler command

45 views
Skip to first unread message

Bob Carpenter

unread,
Mar 16, 2012, 1:58:03 PM3/16/12
to stan...@googlegroups.com
We're going to get rid of the demo/gm compiler and
replace it with what is now in src/demo/stanc.cpp.

Daniel will be able to make the move easier than I
will without disrupting the build and test process.
We'll need a new build target for the executables that
go along with Stan, like stanc.

Right now, I left demo/gm as is so as not to disrupt
the tests or anyone else, and put stanc in demo/stanc.cpp.


Here's what it does now:

-----------------------------------------------
~/stan>demo/stanc --help

stanc version alpha.0

USAGE: stanc [options] <model_file>

OPTIONS:

--help Display this information

--version Display stanc version number

--name=<string> Model name
(default = "anon_model")

--o=<file> Output file for generated C++ code
(default = "$name.cpp")
-----------------------------------------------

Here's an example of compiling the Wishart sampler:

--------------------------------
~/stan>demo/stanc --name=wishart --o=wish.cpp
src/models/basic_distributions/wishart.stan
Model name=wishart
Input file=src/models/basic_distributions/wishart.stan
Output file=wish.cpp
~/stan>
--------------------------------

- Bob

Ben Goodrich

unread,
Mar 16, 2012, 3:06:01 PM3/16/12
to stan...@googlegroups.com
On Friday, March 16, 2012 1:58:03 PM UTC-4, Bob Carpenter wrote:
Here's what it does now:

-----------------------------------------------
~/stan>demo/stanc --help

stanc version alpha.0

USAGE:  stanc [options] <model_file>

OPTIONS:

   --help              Display this information

   --version           Display stanc version number

   --name=<string>     Model name
                           (default = "anon_model")

   --o=<file>          Output file for generated C++ code
                           (default = "$name.cpp")
-----------------------------------------------


Are we going to add something like --mode=<"stand-alone" | "R">?

 

Marcus Brubaker

unread,
Mar 16, 2012, 3:21:17 PM3/16/12
to stan...@googlegroups.com
I like the idea of having a mode flag.  One thing I've been thinking of adding is a MEX generator for a Matlab interface to either the model alone or the sampler as well (like you're doing with the R interface).  The former would of great use for people wanting to do MCMC methods development in Matlab.  Having a mode flag would make this much easier.

Cheers,
Marcus


Bob Carpenter

unread,
Mar 16, 2012, 3:29:41 PM3/16/12
to stan...@googlegroups.com
On 3/16/12 3:06 PM, Ben Goodrich wrote:
> Are we going to add something like --mode=<"stand-alone" | "R">?

I don't think we'll need any extra functionality
in the models for R. If we do, we can add it without
changing the compiler options.

Will having a main() defined screw up the dynamic
linking? If so, then we'll need a standalone
option to signal we want a main() function.

We may also need to monkey with the namespaces. Right
now, the model's name and its namespace name are
generated together. We may need to fix both in order
to write the R side of the code.

- Bob

Bob Carpenter

unread,
Mar 16, 2012, 3:34:34 PM3/16/12
to stan...@googlegroups.com
We have an outstanding NSF proposal in which
we proposed to build interfaces for R, MATLAB,
and Python.

We can always add more functions to the generated
class. What I don't want to add is any dependencies
from Stan on anything in R, MATLAB or Python. I
think all of that should be factored in the R-, MATLAB-
and Python-specific interface code. I'm particularly
concerned about (a) ease of compilation/installation,
and (b) licensing issues.

Right now, we only have two dependencies from a
user's perspective: Eigen and Boost.

The R interface will add a dependency to R.

The test framework has a dependency on googletest,
but it's not needed to build or run.

- Bob

On 3/16/12 3:21 PM, Marcus Brubaker wrote:


> On Fri, Mar 16, 2012 at 3:06 PM, Ben Goodrich <goodri...@gmail.com <mailto:goodri...@gmail.com>> wrote:
>
> On Friday, March 16, 2012 1:58:03 PM UTC-4, Bob Carpenter wrote:
>
> Here's what it does now:
>

> ------------------------------__-----------------


> ~/stan>demo/stanc --help
>
> stanc version alpha.0
>
> USAGE: stanc [options] <model_file>
>
> OPTIONS:
>
> --help Display this information
>
> --version Display stanc version number
>
> --name=<string> Model name
> (default = "anon_model")
>
> --o=<file> Output file for generated C++ code
> (default = "$name.cpp")

> ------------------------------__-----------------

Ben Goodrich

unread,
Mar 16, 2012, 3:52:17 PM3/16/12
to stan...@googlegroups.com

On Friday, March 16, 2012 3:29:41 PM UTC-4, Bob Carpenter wrote:
On 3/16/12 3:06 PM, Ben Goodrich wrote:
 > Are we going to add something like --mode=<"stand-alone" | "R">?

I don't think we'll need any extra functionality
in the models for R.  If we do, we can add it without
changing the compiler options.

Will having a main() defined screw up the dynamic
linking?  If so, then we'll need a standalone
option to signal we want a main() function.

I think you can dynamically load and unload a function called main, but it could potentially name-clash with a function in some other (poorly written) package. R tries to mitigate name clashes by using package namespaces, but in this case the user's model code would be generated by our R package rather than being a part of our R package.

It isn't clear to me how stanc is going to generate C++ code that is suitable for calling from R without some sort of flag. In other words, how would it know to not read the data from the dump file and not take the options from the command line but instead take the data pass-by-reference and options pass-by-value coming from R?

It also seems like it would be feasible to have stanc generate R / MATLAB / Python compatible code without explicitly making dependencies on R / MATLAB / Python. Clearly, the generated C++ code wouldn't run (and possibly not even compile) without them, but users could print the code and stick it on their refrigerators if they wanted.

Ben

Marcus Brubaker

unread,
Mar 16, 2012, 4:09:13 PM3/16/12
to stan...@googlegroups.com


The mode flag would really be about generating code which would compile and create different interfaces.  It shouldn't place any licensing or dependency requirements for people not using those interfaces.  E.g., in Matlab mode instead of generating a main() function it might generte a mexFunction() function which would handle the book keeping and conversions between matlab and the C++ matrix/vector classes.

A standalone option would be a way to support this (e.g., don't generate a main function, just produce the model) but that would req

Marcus Brubaker

unread,
Mar 16, 2012, 4:10:18 PM3/16/12
to stan...@googlegroups.com
(Bugger, accidentally sent before finishing...)

A standalone option would be a way to support this (e.g., don't generate a main function, just produce the model) but that would require an extra step to finally get to compilable code for an interface.  Seems like an unneeded hurdle.

Cheers,
Marcus

Bob Carpenter

unread,
Mar 16, 2012, 6:40:09 PM3/16/12
to stan...@googlegroups.com

On 3/16/12 3:52 PM, Ben Goodrich wrote:
>
> On Friday, March 16, 2012 3:29:41 PM UTC-4, Bob Carpenter wrote:

x


> Will having a main() defined screw up the dynamic
> linking? If so, then we'll need a standalone
> option to signal we want a main() function.
>
> I think you can dynamically load and unload a function called main, but it could potentially name-clash with a function
> in some other (poorly written) package. R tries to mitigate name clashes by using package namespaces, but in this case
> the user's model code would be generated by our R package rather than being a part of our R package.

That's exactly my thinking about main() and namespaces. It
seems bad manners to export one.

Then, if we always generate the same class name for
every model, we could have a fixed .cpp file to run
models with the main() pre-built.

> It isn't clear to me how stanc is going to generate C++ code that is suitable for calling from R without some sort of
> flag. In other words, how would it know to not read the data from the dump file and not take the options from the
> command line but instead take the data pass-by-reference and options pass-by-value coming from R?

The command that calls the compile model file does a lot of
what you're thinking about, not the model file itself.

The generated model has a constructor which takes a reference to
an implementation of stan::io::var_context. The var_context
abstract base class just specifies how to read names and
dimensions and values. The stan::io::dump class extends
var_context and is constructed with a reference to an
input stream from which R dump format data is read. We'll
do the same thing for R, writing a class that extends var_context,
but is constructed with a reference to an R list or environment
or whatever you guys think is the right currency of exchange
for what R2WinBUGS passes in as data.

> It also seems like it would be feasible to have stanc generate R / MATLAB / Python compatible code without explicitly
> making dependencies on R / MATLAB / Python. Clearly, the generated C++ code wouldn't run (and possibly not even compile)
> without them, but users could print the code and stick it on their refrigerators if they wanted.

I know there's some latitude here (how much, I don't
think has been properly worked out legally), but I'd
just as soon keep things segregated just for code
modularity.

- Bob

Bob Carpenter

unread,
Mar 16, 2012, 6:49:00 PM3/16/12
to stan...@googlegroups.com
Can't we put all of that in the glue code
rather than in the generated model?

I probably got us off on the wrong foot putting
the main() in there to begin with. I'm really
thinking of the model as something that computes
a log probability function, knows the names of its
variables and how to transform/print them.

I'm pretty sure that for R, we can do everything
in the glue code and load the model dynamically.
Ben sent an example earlier of how R uses this
kind of mechanism to let you dynamically replace
their base random number generators.

- Bob


On 3/16/12 4:10 PM, Marcus Brubaker wrote:
> On Fri, Mar 16, 2012 at 4:09 PM, Marcus Brubaker <marcus.a...@gmail.com <mailto:marcus.a...@gmail.com>> wrote:

Ben Goodrich

unread,
Mar 16, 2012, 8:15:20 PM3/16/12
to stan...@googlegroups.com
I am beginning to see how it could work if the model is always called awesome_model or something and whose class inherits from stan::io::var_context.

There are a couple of other things that we would need to deal with somehow where stan's current behavior is inconsistent with the requirements for R packages. One is that compiled code called from R is not supposed to write to cout or cerr because neither is visible to any user who uses any of the various R GUIs. The R headers define a Rprintf function and Rcpp defines Rcout, which should be used. Another situation is error throwing, which has to be done in a particular way to avoid crashing the R process. Maybe this can be done with the policy business that I do not understand but a flag was the first thing that came to mind.

Ben

Bob Carpenter

unread,
Mar 17, 2012, 2:41:17 PM3/17/12
to stan...@googlegroups.com

On 3/16/12 8:15 PM, Ben Goodrich wrote:
> I am beginning to see how it could work if the model is always called awesome_model or something and whose class
> inherits from stan::io::var_context.

We specifically need a class that looks something
like this:

class r_context : public var_context {
private:
Rcpp::Environment _env;
public:
r_context(Rcpp::Environment env)
: _env(env) {
}

bool contains_r(const string& var_name);

vector<double> vals_r(const string& var_name);

vector<size_t> dims_r(const string& var_name);

... same thing for integer values ...
}

I set everything up here to be row-major (and so on
for higher dimensions) so it'd be easy to use from R.

What the command-line invocation does is pass in
a context created out of a var_context created from
a dump, which also implements var_context:

class dump : public var_context {
... some storage ...
public:
dump(istream& in) { ... read and store vars ... }

...
}

This reads values from an input stream presumed to
be in S-plus/R "dump" format.

>
> There are a couple of other things that we would need to deal with somehow where stan's current behavior is inconsistent
> with the requirements for R packages.


> One is that compiled code called from R is not supposed to write to cout or cerr
> because neither is visible to any user who uses any of the various R GUIs. T

The only thing that should be writing to std out and std err
is the command. The API itself should not have any functions
that ever write to std out or std err.

For instance, the parser stores error info in a string
rather than printing.

> The R headers define a Rprintf function and
> Rcpp defines Rcout, which should be used. Another situation is error throwing, which has to be done in a particular way
> to avoid crashing the R process. Maybe this can be done with the policy business that I do not understand but a flag was
> the first thing that came to mind.

What we'll do for this is have the R glue code
catch any exceptions thrown by the Stan API and handle
them in a way appropriate to R. No need to monkey
with any of the underlying code. That's the beauty of
exceptions if used the right way.

Here's the drill in a nutshell:

1. Throw an exception if you run into a problem
you can't handle.

2. If you call a function that throws an exception
you can't handle, pass it on (perhaps catching it first
then throwing an exception of a different type).

3. If you call a function that throws an exception
you can handle, handle it and don't throw an exception.

This limits the exception throwing to its source
and the handling to some higher level where it can be handled.

The API is written to respect these principles.
If NUTS gets a lower-level math error, it treats it as a 0
probability, handles that case, and doesn't rethrow.
Everything else either just throws (1) or propagates (2).

The command-line invocation of Stan handles exceptions
by catching them and printing them as diagnostics.

The R invocation of Stan will have to handle exceptions in
the same way, reporting errors through R rather than printing
to standard output.

- Bob

Daniel Lee

unread,
Mar 20, 2012, 2:49:34 PM3/20/12
to stan...@googlegroups.com
The compiler has now moved to bin/stanc.

To compile, you can type:
~/stan> make bin/stanc
or under windows:
~/stan> make binstanc.exe

The test-bugs target and targets for individual models now use bin/stanc.

One thing I have not done is to have bin/stanc automatically recompile
if one of its dependencies has changed. Please let me know if this is
worth the effort and I'll put it in.

demo/gm, demo/stanc have been removed.

Daniel

Bob Carpenter

unread,
Mar 20, 2012, 3:05:03 PM3/20/12
to stan...@googlegroups.com

On 3/20/12 2:49 PM, Daniel Lee wrote:
> The compiler has now moved to bin/stanc.
>
> To compile, you can type:
> ~/stan> make bin/stanc
> or under windows:
> ~/stan> make binstanc.exe

Presumably there was a backslash in the windows one, as in

make bin\stanc.exe?

This makes me realize there's going to have to be Windows
and Unix versions of my doc. Or a big translation key up
front.

> The test-bugs target and targets for individual models now use bin/stanc.
>
> One thing I have not done is to have bin/stanc automatically recompile
> if one of its dependencies has changed. Please let me know if this is
> worth the effort and I'll put it in.

If it's not too much effort, it makes development easier.
But it's no big deal and won't be used from a client
perspective.

> demo/gm, demo/stanc have been removed.

Fantastic. That's one of the last to-do items
for the code organization.

- Bob


Reply all
Reply to author
Forward
0 new messages