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