Issues implementing a simple Stan example

Hi everyone,

I am following the example posted here:
https://github.com/StanJulia/StanSample.jl/blob/master/example/keyword_bernoulli.jl

When I get to the following line of code I get an error:

sm = SampleModel("test_b", bernoulli_model, tmpdir);

This is the error it generates:


/home/charper/classes/MATH462/tmp/test_b.stan updated.

IOError: cd(""): no such file or directory (ENOENT)

Stacktrace:
 [1] uv_error
   @ ./libuv.jl:97 [inlined]
 [2] cd(dir::String)
   @ Base.Filesystem ./file.jl:89
 [3] cd(f::StanSample.var"#25#26"{IOBuffer, String, String}, dir::String)
   @ Base.Filesystem ./file.jl:109
 [4] SampleModel(name::String, model::String, tmpdir::String)
   @ StanSample ~/.julia/packages/StanSample/rqV3P/src/stanmodel/SampleModel.jl:104
 [5] top-level scope
   @ In[72]:1
 [6] eval
   @ ./boot.jl:373 [inlined]
 [7] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
   @ Base ./loading.jl:1196

For ease of reading I have copy and pasted the whole example below:

using StanSample

ProjDir = @__DIR__

bernoulli_model = "
data {
  int<lower=1> N;
  int<lower=0,upper=1> y[N];
}
parameters {
  real<lower=0,upper=1> theta;
}
model {
  theta ~ beta(1,1);
  y ~ bernoulli(theta);
}
";

data = Dict("N" => 10, "y" => [0, 1, 0, 1, 0, 0, 0, 0, 0, 1])

# Keep tmpdir across multiple runs to prevent re-compilation
tmpdir = joinpath(@__DIR__, "tmp")

sm = SampleModel("kw_bern", bernoulli_model, tmpdir);

sm |> display

rc = stan_sample(sm; data, num_threads=4, num_cpp_chains=4, num_chains=2, seed=12);

if success(rc)
  st = read_samples(sm)
  display(st)
  println()
  display(read_samples(sm, :dataframe))
end

When I check the size of test_b.stan, it is not zero.

Hi Chris, can you try without the ā€˜tmpdir’ argument?

Looks like you are on Windows.

Which version is StanSample are you using? I might have to disable the C++ threads on Windows by default. But that is not what caused above error.

Hi Goedman,

Im running Ubuntu 18 , but I was actually running this example through jupyter notebooks. I need to use Stan for a class project and the professor requires notebook submissions. However, your question made me wonder if it had something to do with the jupyter notebook platform, so I tried to run it locally and got the same error. I also rmoved the tempdir argument and once again got the same error.

I am using cmdstan version 2.28.2 and StanSample v6.1.1.

I do get the following warning when I first try to run the script:

ā”Œ Warning: Environment variable CMDSTAN_HOME not set. Use set_cmdstan_home!.
ā”” @ StanBase ~/.julia/packages/StanBase/kbRrd/src/StanBase.jl:53

But I have added the following line to my startup.jl file so I’m not sure why that is happening or if it matters for this problem:

const CmdStanDir = "/opt/cmdstan-2.17.1/";

Chris,

It expects either CMDSTAN (or JULIA_CMDSTAN_HOME) to point to the cmdstan installation directory,
not CmdStanDir.

How did you install cmdstan-2-17.1? That is pretty old. It certainly won’t support C++ threads.

Rob

Oh sorry that’s a typo, I copied that line from the online guide I used. The actual line in my script is

const CmdStanDir = "/opt/cmdstan-2.28.2/";

I have version 2.28.2 installed

No problem, you’d mentioned that earlier, so I was a bit confused.

Maybe you can try:

ENV["CMDSTAN"] = "/opt/cmdstan-2.28.2/"

or

CMDSTAN = "/opt/cmdstan-2.28.2/"

before creating the SampleModel.

Did you define a file /opt/cmdstan-2.28.2/make/local containing ā€œSTAN_THREADS=trueā€? If not you can use:

rc = stan_sample("your-model"; use_cpp_chains=false, [data | ...])

Rob

I really appreciate your help so far Goedman, unfortunately, I don’t think any of these solutions worked (I could have implemented them wrong).

I tried putting each of those top two lines (one at a time) at the top of my script after the ā€œusingā€ statements and received the same warning and error each time.

I do not have a file in /opt/cmdstan-2.28.2/make/local containing that string, however the stan_sample() function will not work because sm/ ā€œyour-modelā€ never gets made in the previous line because of the error that’s getting triggered.

I did find an example of the local file which I copied over and uncomented the line you mentioned. This is what my local file looks like. Are there other lines I should comment out? As it is, I still got the same error:

# To use this template, make a copy from make/local.example to make/local and uncomment options as n# To use this template, make a copy from make/local.example to make/local and uncomment options as needed.
# Be sure to run `make clean-all` before compiling a model to make sure everything gets rebuilt.

# Change the C++ compiler
# CXX=clang++

# Enable threading
 STAN_THREADS=true

# Enable the MPI backend (requires also setting (replace gcc with clang on Mac)
# STAN_MPI=true
# CXX=mpicxx
# TBB_CXX_TYPE=gcc

# Enable the OpenCL backend
# STAN_OPENCL=true

# Add flags that are forwarded to the Stan-to-C++ compiler (stanc3).
# This example enables pedantic mode
# STANCFLAGS+= --warn-pedantic

# Enable C++ compiler and linker optimization recommended by Stan developers.
# Can significantly slow down compilation.
# STAN_CPP_OPTIMS=true

# Remove range checks from the model for faster runtime. Use this flag with caution
# and only once the indexing has been validated. In case of any unexpected behavior
# remove the flag for easier debugging.
# STAN_NO_RANGE_CHECKS=true

# Adding other arbitrary C++ compiler flags
# CXXFLAGS+= -funroll-loops
~                             

Hi Chris,

That is really weird. So the problem is still

ā”Œ Warning: Environment variable CMDSTAN_HOME not set. Use set_cmdstan_home!.
ā”” @ StanBase ~/.julia/packages/StanBase/kbRrd/src/StanBase.jl:53

I don’t often do that inside the script , I always set it as an environment variable.

What do you get in Julia with:

ENV["CMDSTAN"]

In a script I use

StanBase.set_cmdstan_home!("/Users/rob/Projects/StanSupport/cmdstan")
"/Users/rob/Projects/StanSupport/cmdstan"

The ā€œSTAN_THREADS=trueā€ in the make/local file should be enough.

Do you mind sending me the terminal output when you run the script, just want to be sure I don’t miss anything. This is never that difficult.

Just did a quick experiment. I removed CMDSTAN from my .zshrc. So with a fresh new terminal and Julia CMDSTAN is not defined in Julia:

              _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.8.0-DEV.1477 (2022-02-09)
 _/ |\__'_|_|_|\__'_|  |  Commit 2118a08ae9 (0 days old master)
|__/                   |

julia> using StanSample
ā”Œ Warning: Environment variable CMDSTAN_HOME not set. Use set_cmdstan_home!.
ā”” @ StanBase ~/.julia/dev/StanBase/src/StanBase.jl:53

julia> isdefined(Main, :CMDSTAN)
false

julia> CMDSTAN="/Users/rob/Projects/StanSupport/cmdstan"
"/Users/rob/Projects/StanSupport/cmdstan"

julia> isdefined(Main, :CMDSTAN)
true

julia> CMDSTAN_HOME
""

julia> using StanSample

julia> CMDSTAN_HOME
""

julia> 

So I expect in your script you first have using StanSample and a bit later CMDSTAN = ...?

If I define CMDSTAN before using StanSample it is picked up in StanBase.init():

              _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.8.0-DEV.1477 (2022-02-09)
 _/ |\__'_|_|_|\__'_|  |  Commit 2118a08ae9 (0 days old master)
|__/                   |

julia> CMDSTAN="/Users/rob/Projects/StanSupport/cmdstan"
"/Users/rob/Projects/StanSupport/cmdstan"

julia> using StanSample

julia> CMDSTAN_HOME
"/Users/rob/Projects/StanSupport/cmdstan"

julia> 

Maybe this is what is happening?

Rob

1 Like

Oh, wow, putting the CMDSTAN command before the using statements fixed that error. I should just add that line to my start_up.jl, right?

Now I am getting a new error, where it looks like it doesn’t have permission to create a new file? I feel like we’re close! Thanks again for all the help so far.

ERROR: LoadError: 
Error when compiling SampleModel bernoulli:
<built-in>: fatal error: opening dependency file stan/src/stan/model/model_header_threads.d: Permission denied
compilation terminated.
Assembler messages:
Fatal error: can't create src/cmdstan/main_threads.o: Permission denied
make: *** [src/cmdstan/main_threads.o] Error 1

This looks like cmdstan is not properly installed.

Did you do all steps in the installation script, in particular the bernoulli example? Something like:

git clone https://github.com/stan-dev/cmdstan.git --recursive

# or e.g.

# git clone -b v2.28.2 https://github.com/stan-dev/cmdstan.git --recursive

cd cmdstan

# or:
# make clean-all
# make -B -j9 build

# or copy ./make/local from previous install

make -j9 build

make examples/bernoulli/bernoulli

./examples/bernoulli/bernoulli num_threads=4 sample num_chains=4 data file=examples/bernoulli/bernoulli.data.R

or 

./examples/bernoulli/bernoulli num_threads=6 sample num_chains=4 data file=examples/bernoulli/bernoulli.data.json

ls -l output*

bin/stansummary output_1.csv

This is just the script I use. Here -j9 specifies the number of threads available in your processor. You can drop that term, just takes a bit longer.

hmmm I might be out of my depth here, this workflow is very different than expected. I downloaded a tar file for cmd-stan2.28.2. I extracted it to my opt directory in the following way:

$ cd /opt
$ sudo tar -zxvf /tmp/cmdstan-2.17.1.tar.gz
$ cd cmdstan-2.17.1

and then from here I just sudo make build.

After that I added the packages in Julia, and I thought the workflow from there would be largely contained within julia.

I am kind of confused by what is described in your work flow. I need to be making and building all of my models in the directory in which I installed cmdstan? I need to run make every time I want to use it? I am really sorry, I feel like I don’t understand what I am doing at all…or how any of this works.

And I’m not expecting you to break it down any further! I feel like there are some basic things I need to read up on. I appreciate your help so far, I think this just comes down to a fundamental gap in CS knowledge for me.

Yes, I agree this is confusing. Anything I have in my scripts is after cmdstan is installed properly.

I’m still taking back by the cmdstan-2.17.1. But in any case, after your make build it should have come back with ā€œcmdstan-2.28.2 builtā€. To recreate that message do:

make clean-all
make build

Then, still in the tarred cmdstan directory, you should be able to do:

$ make examples/bernoulli/bernoulli
$ ./examples/bernoulli/bernoulli sample data file=examples/bernoulli/bernoulli.data.R

Once cmdstan is installed, the Julia side is all you need. No need to rebuild cmdstan.

I see. I apologize for the version confusion, I was writing that down from some old notes, I used the correct version number when I did it on my machine!

I think that makes sense. Do I need to clean and rebuild before every time I want to run a Julia script with Stan? Or are we just doing this as a test case to look at how I have installed cmd-stan on my machine?

You don’t have to touch the cmdstan build again unless you would like to install an upgrade (the Stan team releases a couple of updates each year but you don’t need to always install the updates).

Just to make sure, try running the Bernoulli example from the tarred cmdstan dir, no need to rebuild.

I’ll be out the next couple of hours, will be back later today. Let’s finish this!

No rush! Its mid-term season where I am, so I am in and out of things as well. I think we’re really close!

I cleaned and re built and received the correct build message. When I tried to run the make examples/bernoulli/bernoulli I still received permission errors. When I used sudo make I had no problems. It worked! In order to be able to run it from my julia script, I changed the permissions on my /opt directory using chmod 755 /opt. Now when I run the julia script I get a new error:

ERROR: LoadError: 
Error when compiling SampleModel bernoulli:
/home/linuxbrew/.linuxbrew/bin/ld: stan/lib/stan_math/lib/tbb/libtbb.so.2: undefined reference to `__cxa_init_primary_exception@CXXABI_1.3.11'
/home/linuxbrew/.linuxbrew/bin/ld: stan/lib/stan_math/lib/tbb/libtbb.so.2: undefined reference to `std::__exception_ptr::exception_ptr::exception_ptr(void*)@CXXABI_1.3.11'
collect2: error: ld returned 1 exit status
make: *** [/home/charper/test/tmp/bernoulli] Error 1

Stacktrace:
 [1] SampleModel(name::String, model::String, tmpdir::String)
   @ StanSample ~/.julia/packages/StanSample/rqV3P/src/stanmodel/SampleModel.jl:110
 [2] top-level scope
   @ ~/test/stan_test.jl:28
 [3] include(fname::String)
   @ Base.MainInclude ./client.jl:451
 [4] top-level scope
   @ REPL[1]:1
in expression starting at /home/charper/test/stan_test.jl:28

Here is the local julia file I am trying to run in case it helps:

CMDSTAN="/opt/cmdstan-2.28.2/"

using StanSample, MCMCChains
using StatsPlots

ProjDir=@__DIR__

bernoullimodel = "
data { 
  int<lower=1> N; 
  int<lower=0,upper=1> y[N];
} 
parameters {
  real<lower=0,upper=1> theta;
} 
model {
  theta ~ beta(1,1);
  y ~ bernoulli(theta);
}
";

observed_data = Dict("N" => 10, "y" => [0, 1, 0, 1, 0, 0, 0, 0, 0, 1])

# Default for tmpdir is to create a new tmpdir location
# To prevent recompilation of a Stan progam, choose a fixed location,
tmpdir=joinpath(@__DIR__,"tmp")

sm = SampleModel("bernoulli", bernoullimodel,tmpdir);

rc = stan_sample(sm, data=observed_data);

if success(rc)
  chns = read_samples(sm, :mcmcchains)
  
  # Describe the results
  chns |> display
  
  # Optionally, read samples as a a DataFrame
  df=read_samples(sm, :dataframe)
  first(df, 5)
  println()
  
  df = read_summary(sm)
  df[df.parameters .== :theta, [:mean, :ess]]
end