Has anybody tried / succeeded bulding a Stan model using emscripen?

264 views
Skip to first unread message

Rasmus Bååth

unread,
Nov 10, 2014, 7:07:11 PM11/10/14
to stan-...@googlegroups.com
I was lurking around on the Stan development mailing list when I came across the plans for WebStan post where the merits of compiling Stan models with emscripten were discussed. For those of you who doesn't know emscripten, it's a really cool project with the aims of making a compiler that takes, say, a c++ program (like a compiled Stan model) and compiles it down to javascript! If emscripten could compile Stan models we are inches from running Stan models in the browser :) So I've downloaded emscripten and tried to compile a simple Stan model but without any success (but I could have done all kinds of stupid mistakes). So my question(s):

Have anyone here tried compiling a Stan model using emscripten? Did it succeed? Is there some reason why it shouldn't work?

Was sort of hoping I could extend my javascript Gibbs sampling demo (http://www.sumsar.net/best_online/) with some Hamiltonian goodness...

Bob Carpenter

unread,
Nov 10, 2014, 7:39:04 PM11/10/14
to stan-...@googlegroups.com
I haven't tried it. We're using standard cross-platform C++03,
but with lots of template metaprogramming.

It might help if you could tell us what kind of problems you ran into.
I believe all of Stan could be modified to be used header only --- I think
Allen just did that for PyStan --- that'd probably make things easier
than trying to link multiple object files.

- Bob
> --
> You received this message because you are subscribed to the Google Groups "Stan users mailing list" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to stan-users+...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Ben Goodrich

unread,
Nov 10, 2014, 11:01:58 PM11/10/14
to stan-...@googlegroups.com
Hi Rasmus,

I think I tried a long time ago (that and pnacl). I don't remember it not working but to be useful for anything other than a PRNG demo, we would need a way to pass data to it. I'm sure a web interface to a Stan model could be built but I'm not very good at such things.

Ben

Rasmus Bååth

unread,
Nov 11, 2014, 5:21:59 AM11/11/14
to stan-...@googlegroups.com
I now managed to build a stan model using emscripten, the reason for me failing to build before was because I did not know what I was doing. To build a stan model using emscripten I performed the following steps:

  1. Install emscripten (http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html#sdk-download-and-install) and make sure it works using the test suit.
  2. Install CmdStan (http://mc-stan.org/cmdstan.html) according to the instructions there (including building it).
  3. Make a stan model file, here I used a standard Bernouli model (saved as bernouli.stan):
    data {
      int<lower=0> n;
      int<lower=0,upper=1> y[n];
    }
    parameters {
      real<lower=0,upper=1> theta;
    }
    model {
      theta ~ beta(1,1);
      for (i in 1:n)
        y[i] ~ bernoulli(theta);
    }
  4. Compile it using cmdstan with standard g++, but before doing that make sure you have removed cmdstan/bin/stan/agrad/rev/var_stack.o , cmdstan/bin/libstan.a and, in case you compiled the model before, the resulting Bernouli executable. (Here my cmdstan folder happened to be on my desktop and the bernouli.stan model was in the folder ../stan_test/)
    ~/Desktop/cmdstan> make ../stan_test/bernouli
    resulting in  the following print out (has here removed some lines):
    g++ -DBOOST_RESULT_OF_USE_TR1 -DBOOST_NO_DECLTYPE -DBOOST_DISABLE_ASSERTS -I src -I stan/src -isystem stan/lib/eigen_3.2.0 -isystem stan/lib/boost_1.54.0 -Wall -pipe -DEIGEN_NO_DEBUG   -c -O3 -o bin/stan/agrad/rev/var_stack.o stan/src/stan/agrad/rev/var_stack.cpp

    ar -rs bin/libstan.a bin/stan/agrad/rev/var_stack.o

    g++ -DBOOST_RESULT_OF_USE_TR1 -DBOOST_NO_DECLTYPE -DBOOST_DISABLE_ASSERTS -I src -I stan/src -isystem stan/lib/eigen_3.2.0 -isystem stan/lib/boost_1.54.0 -Wall -pipe -DEIGEN_NO_DEBUG  -lpthread  -O3 -o ../stan_test/bernouli src/cmdstan/main.cpp -include ../stan_test/bernouli.cpp -Lbin -lstan
  5. Copy this printout to a text editor and change the the following things
    • Replace g++ with emcc (if emcc is not on your path, you have to write out the whole path to it)
    • Replace ar with emar (again including the parth if necessary)
    • remove the dash (-) in front of the ar flag, that is -rs should become just rs .
    • remove the optimization by setting -O3 to -O0.
    • change -o ../stan_test/bernouli to -o ../stan_test/bernouli.js
  6. This should result in something like the following:
    ~/Desktop/emsdk_portable/emscripten/master/emcc -DBOOST_RESULT_OF_USE_TR1 -DBOOST_NO_DECLTYPE -DBOOST_DISABLE_ASSERTS -I src -I stan/src -isystem stan/lib/eigen_3.2.0 -isystem stan/lib/boost_1.54.0 -Wall -pipe -DEIGEN_NO_DEBUG   -c -O0 -o bin/stan/agrad/rev/var_stack.o stan/src/stan/agrad/rev/var_stack.cpp

    ~/Desktop/emsdk_portable/emscripten/master/emar rs bin/libstan.a bin/stan/agrad/rev/var_stack.o

    ~/Desktop/emsdk_portable/emscripten/master/emcc -DBOOST_RESULT_OF_USE_TR1 -DBOOST_NO_DECLTYPE -DBOOST_DISABLE_ASSERTS -I src -I stan/src -isystem stan/lib/eigen_3.2.0 -isystem stan/lib/boost_1.54.0 -Wall -pipe -DEIGEN_NO_DEBUG  -lpthread  -O0 -o ../stan_test/bernouli.js src/cmdstan/main.cpp -include ../stan_test/bernouli.cpp -Lbin -lstan
  7. Run this in the cmdstan base path and hopefully you will have produced a hefty 13 mb javascript file called bernouli.js.
  8. If you want to creat something you can run, replace change -o ../stan_test/bernouli.js with -o ../stan_test/bernouli.html this will create a html file that includes and runs the javascript code. In this case we would just get a printout saying that Stan is missing any input, but anyway :) Here is a link to my compiled Stan program if you want to see how it looks: 

There might be a much better way to do this, but this is what I managed. Some notes:

  • It should certainly be possible to change the make file included in CmdStan to do this automatically, I just thought it was easier to manually change the compile commands to see what was going on.
  • By using the modified commands above you create libstan.a and var_stack.o files that should probably be put somewhere else than in the CmdStan directory.
  • I managed to compile Stan using higher than -O1 optimization but when using -O2 I got an runtime error when running the javascript code (using bernouli.html):
    ReferenceError: DOT$ZERO is not defined
  • I havn't actually tried if the resulting Stan model works when running the actual model...

Rasmus Bååth

unread,
Nov 11, 2014, 5:24:38 AM11/11/14
to stan-...@googlegroups.com
Sorry, forgot to link to the compiled test program (which just prints out some help and an error message, but anyway, I think it is pretty cool). Here it is:

http://www.sumsar.net/files/bernouli.html

/Rasmus

Rasmus Bååth

unread,
Nov 11, 2014, 10:25:40 AM11/11/14
to stan-...@googlegroups.com
Update: Sampling is also working (not always, crashes sometimes "randomly", but often enough :). Check the updated demo, that now also prints out the samples for the Bernouli model, here: http://sumsar.net/files/bernouli.html

To get this working I made some small adjustments to the bernouli.html file generated by emcc. First I added a text area for output somewhere in the middle of the web page:

<div><pre id="output2" ></pre></div>

Then, in the javascript at the bottom of the file I changed this:

 var Module = {
        preRun: [],
        postRun: [],


Into this:

var Module = {
        arguments: ['sample', 'num_warmup=200', 'num_samples=200','data', 'file=testdata.R'],
        preRun: [function() {
          FS.writeFile('testdata.R', 'n <- 10 \n y <- c(0,1,0,0,0,0,0,0,0,1)');}
        ],
        postRun: [function() {
          var output2 = document.getElementById('output2');
          output2.innerHTML = FS.readFile("output.csv",  { encoding: "utf8" });
        }],


Here arguments are the command line arguments given to the compiled Stan model arguments. The preRun parts writes a temporary file testdata.R that contains the data the model is going to use using the emscripten file system API (http://kripken.github.io/emscripten-site/docs/api_reference/Filesystem-API.html#filesystem-api). Finally, the postRun part reads the generated csv file and inserts it into the document. Now the data is hard coded in the javascript, but it could also have been read from a form in the html document.

I don't really know how fast this is, or if it will work for larger models, but it is pretty cool that it works at all :)

/Rasmus

Rasmus Bååth

unread,
Nov 11, 2014, 11:22:54 AM11/11/14
to stan-...@googlegroups.com
Last update (promise). I just added so that a user could input data, only works once then you have to reload the page: http://sumsar.net/files/bernouli.html

The only was to see that this actually works is by looking at the column the theta variable (the one to the very right). If you set y <- c(0,0,0,0,1,0,0,1,0,0) you will get mostly low thetas while if you set y <- c(1,1,1,1,1,1,1,1,0,1) you'll get mostly theta > 0.5. In order to enable user input I commented away the call to run() at the very bottom of the javascript file that emcc generated (bernouli.js), this defers running the stan model until run() is called manually. Then I just added a data input, and a button calling run:

 <textarea id="datainput" rows="4" cols="50">n <- 10
y <- c(0,1,0,0,0,0,0,0,0,1)</textarea>
  <button type="button" onclick="run()">Click to run the model.</button>

And then read the data from the textarea instead from having it hard coded:

preRun: [function() {
          FS.writeFile('testdata.R',  document.getElementById('datainput').value );
             }
],

Bob Carpenter

unread,
Nov 11, 2014, 12:28:05 PM11/11/14
to stan-...@googlegroups.com
Neat.

When I try in Safari, it just keeps spinning a "downloading". Nevertheless,
it works when I hit "run".

Any idea where the crashes might be coming from?

Likely candidates for changing platforms would be exceptions or I/O.

We can get in and change the I/O channels if that would help.
CmdStan writes to std::cout and std::cerr, but we customize
for PyStan and RStan.

Modifying exception handling would be a bigger deal.

Otherwise, we're not doing anything too heavy other than all the
template metaprogramming to compile.

- Bob

Rasmus Bååth

unread,
Nov 11, 2014, 12:53:39 PM11/11/14
to stan-...@googlegroups.com
The spinning download button is due to the last version being an ugly hack... The piece of code that stops the loading animation is never run since I defer calling run() until the button is clicked. I also noticed that if you don't wait until the stan code has loaded (which now has nothing to do with the animation, you just have to wait 10-20 seconds) before you press the button you get an error, this should and could be handled better but this was just a short proof of concept.

I should have written down the errors I got, but I didn't. If I get them again I will report them here.

/rasmus

Rasmus Bååth

unread,
Nov 11, 2014, 1:05:10 PM11/11/14
to stan-...@googlegroups.com
Ok, so the error I get now and then (and I don't see a pattern) is this:

warning: a problem occurred in builtin C++ name demangling; build with  -s DEMANGLE_SUPPORT=1  to link in libcxxabi demangling

Uncaught abort() at Error
    at jsStackTrace (http://sumsar.net/files/bernouli.js:971:13)
    at stackTrace (http://sumsar.net/files/bernouli.js:988:22)
    at abort (http://sumsar.net/files/bernouli.js:229810:25)
    at Array.b3 (http://sumsar.net/files/bernouli.js:227752:32)
    at Array.__ZN4stan5agradL4gradEPNS0_9chainableE [stan::agrad?N(grad)] (http://sumsar.net/files/bernouli.js:7889:31)
    at Object.dynCall_vi (http://sumsar.net/files/bernouli.js:227466:36)
    at invoke_vi (http://sumsar.net/files/bernouli.js:7104:25)
    at __ZN4stan5agrad8gradientINS_5model16model_functionalIN24bernouli_model_namespace14bernouli_modelEEEEEvRKT_RKN5Eigen6MatrixIdLin1ELi1ELi0ELin1ELi1EEERdRSC_ [undefined stan::agrad::gradient<undefined stan::model::model_functional<bernouli_model_namespace::bernouli_model?>?>?_(void, undefined?T?&)] (http://sumsar.net/files/bernouli.js:80198:6)
    at Array.__ZN4stan5model8gradientIN24bernouli_model_namespace14bernouli_modelEEEvRKT_RKN5Eigen6MatrixIdLin1ELi1ELi0ELin1ELi1EEERdRS9_PNSt3__113basic_ostreamIcNSE_11char_traitsIcEEEE [undefined stan::model::gradient<bernouli_model_namespace::bernouli_model?>?_(void, undefined?T?&)] (http://sumsar.net/files/bernouli.js:26962:2)
    at Object.dynCall_viiiii (http://sumsar.net/files/bernouli.js:227452:38)
If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.


The sampling also gets really really slow when I add more datapoints, say

n <- 30
y <- c(0,1,0,0,0,0,0,0,0,1, 0,1,0,0,0,0,0,0,0,1, 0,1,0,0,0,0,0,0,0,1)


Though I guess javascript speed is not a top-priority for the Stan developers :)

Ben Goodrich

unread,
Nov 11, 2014, 1:42:33 PM11/11/14
to stan-...@googlegroups.com
On Tuesday, November 11, 2014 1:05:10 PM UTC-5, Rasmus Bååth wrote:
If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.

Can you build it with ASSERTIONS? And we would probably need to figure out how to build with more optimization. But it is good that it kind of works.

Ben

Rasmus Bååth

unread,
Nov 11, 2014, 4:55:22 PM11/11/14
to stan-...@googlegroups.com
I build with ASSERTIONS = 1 ang got the huge error message attached as a text file (I don't know what to make of it). Here is the start of it:

Invalid function pointer called with signature 'vi'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)

So i'm not sure how informative these error message are, could very well be something I do wrong at my side...

/Rasmus
long_emscripten_error_message.txt

Ben Goodrich

unread,
Nov 11, 2014, 5:33:36 PM11/11/14
to stan-...@googlegroups.com
I'm guessing an exception got thrown and either emscripten or Stan is not doing the right thing. Can you build with

-s DEMANGLE_SUPPORT=1

to maybe get better error messages?

Rasmus Bååth

unread,
Nov 11, 2014, 6:18:55 PM11/11/14
to stan-...@googlegroups.com
Ok, here are some more error messages with -s DEMANGLE_SUPPORT=1

Invalid function pointer called with signature 'vi'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this) bernouli.html:1256Module.printErr bernouli.html:1256nullFunc_vi bernouli.js:7138b3 bernouli.js:343115__ZN5boost14checked_deleteINS_16exception_detail10clone_implINS1_10bad_alloc_EEEEEvPT_ bernouli.js:245067__ZN5boost6detail17sp_counted_impl_pINS_16exception_detail10clone_implINS2_10bad_alloc_EEEE7disposeEv bernouli.js:245131__ZN5boost6detail15sp_counted_base7releaseEv bernouli.js:22533__ZN5boost6detail12shared_countD2Ev bernouli.js:22514__ZN5boost6detail12shared_countD1Ev bernouli.js:22498__ZN5boost10shared_ptrIKNS_16exception_detail10clone_baseEED2Ev bernouli.js:243944__ZN5boost10shared_ptrIKNS_16exception_detail10clone_baseEED1Ev bernouli.js:243546__ZN5boost13exception_ptrD2Ev bernouli.js:244357__ZN5boost13exception_ptrD1Ev bernouli.js:18175dynCall_vi bernouli.js:342794Runtime.dynCall bernouli.js:255callRuntimeCallbacks bernouli.js:1078exitRuntime bernouli.js:1120exit bernouli.js:350164callMain bernouli.js:350080doRun bernouli.js:350133(anonymous function) bernouli.js:350145

Uncaught abort() at Error
    at jsStackTrace (file:///home/rasmus/Desktop/stan_test/bernouli.js:979:13)
    at stackTrace (file:///home/rasmus/Desktop/stan_test/bernouli.js:996:22)
    at abort (file:///home/rasmus/Desktop/stan_test/bernouli.js:350200:25)
    at nullFunc_vi (file:///home/rasmus/Desktop/stan_test/bernouli.js:7138:465)
    at Array.b3 (file:///home/rasmus/Desktop/stan_test/bernouli.js:343115:32)
    at __ZN5boost14checked_deleteINS_16exception_detail10clone_implINS1_10bad_alloc_EEEEEvPT_ [void boost::checked_delete<boost::exception_detail::clone_impl<boost::exception_detail::bad_alloc_> >(boost::exception_detail::clone_impl<boost::exception_detail::bad_alloc_>*)] (file:///home/rasmus/Desktop/stan_test/bernouli.js:245067:30)
    at Array.__ZN5boost6detail17sp_counted_impl_pINS_16exception_detail10clone_implINS2_10bad_alloc_EEEE7disposeEv [boost::detail::sp_counted_impl_p<boost::exception_detail::clone_impl<boost::exception_detail::bad_alloc_> >::dispose()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:245131:2)
    at __ZN5boost6detail15sp_counted_base7releaseEv [boost::detail::sp_counted_base::release()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:22533:30)
    at __ZN5boost6detail12shared_countD2Ev [boost::detail::shared_count::~shared_count()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:22514:2)
    at __ZN5boost6detail12shared_countD1Ev [boost::detail::shared_count::~shared_count()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:22498:2)

Uncaught abort() at Error
    at jsStackTrace (file:///home/rasmus/Desktop/stan_test/bernouli.js:979:13)
    at stackTrace (file:///home/rasmus/Desktop/stan_test/bernouli.js:996:22)
    at Object.abort (file:///home/rasmus/Desktop/stan_test/bernouli.js:350200:25)
    at _abort (file:///home/rasmus/Desktop/stan_test/bernouli.js:6111:22)
    at _free (file:///home/rasmus/Desktop/stan_test/bernouli.js:333511:3)
    at __ZdlPv [operator delete(void*)] (file:///home/rasmus/Desktop/stan_test/bernouli.js:329547:2)
    at __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev [std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:249701:2)
    at Array.__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev [std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:249686:2)
    at Object.dynCall_vi (file:///home/rasmus/Desktop/stan_test/bernouli.js:342794:36)
    at invoke_vi (file:///home/rasmus/Desktop/stan_test/bernouli.js:7259:25)
    at __ZN4stan2gm18singleton_argumentIdED2Ev [stan::gm::singleton_argument<double>::~singleton_argument()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:207192:2)
    at __ZN4stan2gm13arg_toleranceD2Ev [stan::gm::arg_tolerance::~arg_tolerance()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:212839:2) bernouli.js:350093callMain bernouli.js:350093doRun bernouli.js:350133(anonymous function)

Uncaught abort() at Error
    at jsStackTrace (file:///home/rasmus/Desktop/stan_test/bernouli.js:979:13)
    at stackTrace (file:///home/rasmus/Desktop/stan_test/bernouli.js:996:22)
    at Object.abort (file:///home/rasmus/Desktop/stan_test/bernouli.js:350200:25)
    at _abort (file:///home/rasmus/Desktop/stan_test/bernouli.js:6111:22)
    at _free (file:///home/rasmus/Desktop/stan_test/bernouli.js:333819:3)
    at __ZN5Eigen8internal12aligned_freeEPv [Eigen::internal::aligned_free(void*)] (file:///home/rasmus/Desktop/stan_test/bernouli.js:45732:2)
    at __ZN5Eigen8internal24conditional_aligned_freeILb1EEEvPv [void Eigen::internal::conditional_aligned_free<true>(void*)] (file:///home/rasmus/Desktop/stan_test/bernouli.js:45722:2)
    at __ZN5Eigen8internal31conditional_aligned_delete_autoIdLb1EEEvPT_j [void Eigen::internal::conditional_aligned_delete_auto<double, true>(double*, unsigned int)] (file:///home/rasmus/Desktop/stan_test/bernouli.js:45712:2)
    at __ZN5Eigen12DenseStorageIdLin1ELin1ELi1ELi0EED2Ev [Eigen::DenseStorage<double, -1, -1, 1, 0>::~DenseStorage()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:45700:2)
    at __ZN5Eigen12DenseStorageIdLin1ELin1ELi1ELi0EED1Ev [Eigen::DenseStorage<double, -1, -1, 1, 0>::~DenseStorage()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:45686:2)
    at __ZN5Eigen15PlainObjectBaseINS_6MatrixIdLin1ELi1ELi0ELin1ELi1EEEED2Ev [Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >::~PlainObjectBase()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:45676:2)
    at __ZN5Eigen6MatrixIdLin1ELi1ELi0ELin1ELi1EED2Ev [Eigen::Matrix<double, -1, 1, 0, -1, 1>::~Matrix()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:45666:2)
    at Array.__ZN5Eigen6MatrixIdLin1ELi1ELi0ELin1ELi1EED1Ev [Eigen::Matrix<double, -1, 1, 0, -1, 1>::~Matrix()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:36704:2)
    at Object.dynCall_vi (file:///home/rasmus/Desktop/stan_test/bernouli.js:342794:36)
    at invoke_vi (file:///home/rasmus/Desktop/stan_test/bernouli.js:7259:25)
    at __ZN4stan4mcmc8ps_pointD2Ev [stan::mcmc::ps_point::~ps_point()] (file:///home/rasmus/Desktop/stan_test/bernouli.js:67143:4)

Ben Goodrich

unread,
Nov 11, 2014, 7:05:18 PM11/11/14
to stan-...@googlegroups.com
On Tuesday, November 11, 2014 6:18:55 PM UTC-5, Rasmus Bååth wrote:
Ok, here are some more error messages with -s DEMANGLE_SUPPORT=1

Invalid function pointer called with signature 'vi'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this) bernouli.html:1256Module.printErr bernouli.html:1256nullFunc_vi bernouli.js:7138b3 bernouli.js:343115__ZN5boost14checked_deleteINS_16exception_detail10clone_implINS1_10bad_alloc_EEEEEvPT_ bernouli.js:245067__ZN5boost6detail17sp_counted_impl_pINS_16exception_detail10clone_implINS2_10bad_alloc_EEEE7disposeEv bernouli.js:245131__ZN5boost6detail15sp_counted_base7releaseEv bernouli.js:22533__ZN5boost6detail12shared_countD2Ev bernouli.js:22514__ZN5boost6detail12shared_countD1Ev bernouli.js:22498__ZN5boost10shared_ptrIKNS_16exception_detail10clone_baseEED2Ev bernouli.js:243944__ZN5boost10shared_ptrIKNS_16exception_detail10clone_baseEED1Ev bernouli.js:243546__ZN5boost13exception_ptrD2Ev bernouli.js:244357__ZN5boost13exception_ptrD1Ev bernouli.js:18175dynCall_vi bernouli.js:342794Runtime.dynCall bernouli.js:255callRuntimeCallbacks bernouli.js:1078exitRuntime bernouli.js:1120exit bernouli.js:350164callMain bernouli.js:350080doRun bernouli.js:350133(anonymous function) bernouli.js:350145

I hate it when I'm right. Looks as if we'll have to disable Stan's exceptions when compiling with emscripten or figure out if there is some emscripten setting that will cause it not to mishandle them.

Ben

Bob Carpenter

unread,
Nov 12, 2014, 12:56:05 AM11/12/14
to stan-...@googlegroups.com
I guessed exceptions or I/O, so I was half right.

I don't see how we could disable Stan's exceptions without
a heroic refactoring effort. But even more importantly, I don't
think we should disable exceptions. I think it's the right way
to do what we're doing. An alternative would be a C-style hack
that, say, wrote to some designated location and then used a goto
to jump, but I don't think that's possible out of context, and I
don't want to have to start passing return codes and making returns
reference arguments and all the other ugliness that was error handling
in plain C.

- Bob

Daniel Lee

unread,
Nov 12, 2014, 12:59:24 AM11/12/14
to stan-...@googlegroups.com
If you wanted to hack the code-base, most of our exceptions are thrown through the dom_err() and dom_err_vec() functions. So, you could change that behavior for a fork or a branch to see if you can get it to work.... if you wanted to go through that effort. We still have a handful of functions that throw directly, but it should be down to under 10 other places that you might need to change.



Daniel

Allen Riddell

unread,
Nov 12, 2014, 6:43:15 AM11/12/14
to stan-...@googlegroups.com
Hi Rasmus,

Thanks for working on this! It would be great if we could run even one Stan
example in the browser.

Thanks,

-a

Bob Carpenter

unread,
Nov 13, 2014, 1:02:06 AM11/13/14
to stan-...@googlegroups.com
Absolutely --- this is super cool.

We've been thinking about servers, but there's
no way we could afford the compute cost.

We're supposed to be delivering web apps over the
next few years as part of an IES grant we have
to build models for education research, and this may
make it feasible to actually deploy them.

- Bob

Ben Goodrich

unread,
Nov 21, 2014, 12:32:03 PM11/21/14
to stan-...@googlegroups.com
Rasmus,

Can you pass the -ffast-math flag to LLVM via emscripten? That disables exceptions but last time I checked allowed Stan to sort of work when compiled with clang++ (although not with g++).

Ben

Ben Goodrich

unread,
Nov 21, 2014, 12:40:21 PM11/21/14
to stan-...@googlegroups.com
On Friday, November 21, 2014 12:32:03 PM UTC-5, Ben Goodrich wrote:
Rasmus,

Can you pass the -ffast-math flag to LLVM via emscripten? That disables exceptions but last time I checked allowed Stan to sort of work when compiled with clang++ (although not with g++).

Upon further review, don't do that. Instead pass to emcc

-s DISABLE_EXCEPTION_CATCHING=0

See

https://kripken.github.io/emscripten-site/docs/optimizing/Optimizing-Code.html#optimizing-code-exception-catching

Ben

Rasmus Bååth

unread,
Nov 21, 2014, 2:34:54 PM11/21/14
to stan-...@googlegroups.com
I actually used that flag in the last couple of builds (by mistake, it tagged along during a copy'n'paste of another flag). Since that actually seems to enable exception catching, I'm not completely sure what the result should be...

/ Rasmus

Ben Goodrich

unread,
Nov 21, 2014, 2:42:39 PM11/21/14
to stan-...@googlegroups.com
On Friday, November 21, 2014 2:34:54 PM UTC-5, Rasmus Bååth wrote:
I actually used that flag in the last couple of builds (by mistake, it tagged along during a copy'n'paste of another flag). Since that actually seems to enable exception catching, I'm not completely sure what the result should be...

I was hoping the problem was that Stan was throwing an exception but the javascript was not catching it. But if it is the case that the exception is caught but not handled correctly, then there is a bug somewhere.

In any event, upon further further review maybe try passing the -ffast-math flag to LLVM via emscripten to see if it is happier without exceptions.

Ben

Rasmus Bååth

unread,
Nov 21, 2014, 6:12:34 PM11/21/14
to stan-...@googlegroups.com
I still get exceptions. However, I'm not sure my setup is ideal for testing emscripten compilation of Stan. I'm still on Ubuntu 12.04 and the repositories are not up to date, so I might not use the latest version of everything. It might very well work better for somebody on a more updated system...

/Rasmus
Reply all
Reply to author
Forward
0 new messages