TBB_INTERFACE_NEW flag is not working

Hello,

I am running into the same issue as this thread

I can compile the model, but running expose_functions will result the same error. What could be the reason for stan not use TBB_INTERFACE_NEW=true flag, FWIW, the init_threadpool_tbb.hpp has these two lines in line 8-9 that should not include tbb_stddef.h if TBB_INTERFACE_NEW is defined:

#ifndef TBB_INTERFACE_NEW
#include <tbb/tbb_stddef.h>
library(brms)
library(data.table)
library(ChainLadder)
data(GenIns)

loss_data <- data.table(
  accident_year = rep(1991:2000, 10),
  dev = sort(rep(1:10, 10)),
  premium = rep(10000000+400000*0:9, 10),
  cum_loss = as.vector(GenIns),
  incr_loss = as.vector(cum2incr(GenIns))
)[order(accident_year, dev),
  `:=`(cum_lr = cum_loss/premium,
       incr_lr = incr_loss/premium)]

myFuns <- '
vector compartmentmodel(real t, vector y, vector theta) {
  vector[3] dydt;
  real ke = theta[1];
  real dr = theta[2];
  real kp1 = theta[3];
  real kp2 = theta[4];
  
  dydt[1] = pow(ke, dr) * pow(t, dr - 1) * exp(-t * ke)/tgamma(dr)
          - (kp1 + kp2) * y[1]; // Exposure
  dydt[2] = kp2 * (y[1] - y[2]); // Outstanding
  dydt[3] = (kp1 *  y[1] + kp2 * y[2]); // Paid
 
  return dydt;
}
real lossemergence(real t, real devfreq, real ke, real dr, 
                   real kp1, real kp2){
    vector[3] y0;
    array[1] vector[3] y;
    vector[4] theta;
    theta[1] = ke;
    theta[2] = dr;
    theta[3] = kp1;
    theta[4] = kp2;
    real out; 
    // Set initial values
    y0[1] = 0; // Exposure
    y0[2] = 0; // Outstanding
    y0[3] = 0; // Paid
    
    y = ode_rk45(compartmentmodel, y0, 0, rep_array(t, 1), theta);
    out = y[1, 3];
    
    if(t > devfreq){ // paid greater dev period 1
    y = ode_rk45(compartmentmodel, y0, 0, rep_array(t - devfreq, 1), theta);
    // incremental paid
     out = out - y[1, 3];
    }
    
    return(out);
}
'

frml <- bf(
  incr_lr ~ eta,
  nlf(eta ~ log(ELR * lossemergence(dev, 1.0, ke, dr, kp1, kp2))),
  nlf(ke ~ exp(oke * 0.5)),
  nlf(dr ~ 1 + 0.1 * exp(odr * 0.5)),
  nlf(kp1 ~ 0.5 * exp(okp1 * 0.5)),
  nlf(kp2 ~ 0.1 * exp(okp2 * 0.5)),
  ELR ~ 1 + (1 | accident_year), 
  oke  ~ 1 + (1 | accident_year), odr ~ 1 + (1 | accident_year), 
  okp1 ~ 1 + (1 | accident_year), okp2 ~ 1 + (1 | accident_year),
  nl = TRUE
)

mypriors <- c(
  prior(inv_gamma(4, 2), nlpar = 'ELR', lb = 0),
  prior(normal(0, 1), nlpar = 'oke'),
  prior(normal(0, 1), nlpar = 'odr'),
  prior(normal(0, 1), nlpar = 'okp1'),
  prior(normal(0, 1), nlpar = 'okp2'),
  prior(student_t(10, 0, 1), class = 'sd', nlpar = 'ELR'),
  prior(student_t(10, 0, 1), class = 'sd', nlpar = 'oke'),
  prior(student_t(10, 0, 1), class = 'sd', nlpar = 'odr'),
  prior(student_t(10, 0, 1), class = 'sd', nlpar = 'okp1'),
  prior(student_t(10, 0, 1), class = 'sd', nlpar = 'okp2'),
  #class = sigma for lognormal family to account for residual sd
  prior(student_t(10, 0, 1), class = 'sigma') 
)

fit <- brm(
  frml,
  data = loss_data, family = lognormal(), 
  prior = mypriors,
  stanvars = stanvar(scode = myFuns, block = 'functions'),
  backend = 'cmdstan',
  file = 'hierarchical-compartmental-model-wide-prior',
  file_refit = 'on_change',
  control = list(adapt_delta = 0.99)
)

fit

x <- summarize_draws(
  as_draws_array(fit, variable = '^b', regex = TRUE),
  mean, sd, ~quantile2(.x, probs = c(0.025, 0.975)))

expose_functions(fit, vectorize = TRUE)
expose_functions(fit, vectorize = TRUE)
using C++ compiler: ‘x86_64-conda-linux-gnu-c++ (conda-forge gcc 12.3.0-13) 12.3.0’
x86_64-conda-linux-gnu-c++ -std=gnu++17 -I"/opt/conda/envs/reserve/lib/R/include" -DNDEBUG   -I"/workspaces/reserve/.cache/R/renv/v5/R-4.3/x86_64-conda-linux-gnu/Rcpp/1.0.12/5ea2700d21e038ace58269ecdbeb9ec0/Rcpp/include" -I"/tmp/RtmpPvsatH/sourceCpp-x86_64-conda-linux-gnu-1.0.12" -DNDEBUG -D_FORTIFY_SOURCE=2 -O2 -isystem /opt/conda/envs/reserve/include -I/opt/conda/envs/reserve/include -Wl,-rpath-link,/opt/conda/envs/reserve/lib   -std=c++17 -D_REENTRANT -Wno-sign-compare -Wno-ignored-attributes -I'/opt/conda/envs/reserve/bin/cmdstan//opt/conda/envs/reserve/include/' -O3 -I'/opt/conda/envs/reserve/bin/cmdstan/src' -I'/opt/conda/envs/reserve/bin/cmdstan/stan/src' -I'/opt/conda/envs/reserve/bin/cmdstan/stan/lib/rapidjson_1.1.0/' -I'/opt/conda/envs/reserve/bin/cmdstan/lib/CLI11-1.9.1/' -I'/opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/' -I'/opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/lib/eigen_3.4.0' -I'/opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/lib/boost_1.84.0' -I'/opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/lib/sundials_6.1.1/include' -I'/opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/lib/sundials_6.1.1/src/sundials' -I"/workspaces/reserve/.cache/R/renv/v5/R-4.3/x86_64-conda-linux-gnu/cmdstanr/0.8.1/e3409949f3437c53affcf4447c9aaace/cmdstanr/include" -fpic  -fvisibility-inlines-hidden  -fmessage-length=0 -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /opt/conda/envs/reserve/include -fdebug-prefix-map=/home/conda/feedstock_root/build_artifacts/r-base-split_1718533472036/work=/usr/local/src/conda/r-base-4.3.3 -fdebug-prefix-map=/opt/conda/envs/reserve=/usr/local/src/conda-prefix  -c file16d712924aa12.cpp -o file16d712924aa12.o
In file included from /opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/stan/math/prim/core.hpp:4,
                 from /opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/stan/math/rev/core/Eigen_NumTraits.hpp:5,
                 from /opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/stan/math/rev/core/typedefs.hpp:7,
                 from /opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/stan/math/rev/core/chainable_object.hpp:6,
                 from /opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/stan/math/rev/core.hpp:10,
                 from /opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/stan/math/rev.hpp:10,
                 from /opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/stan/math.hpp:19,
                 from /opt/conda/envs/reserve/bin/cmdstan/stan/src/stan/model/model_header.hpp:4,
                 from file16d712924aa12.cpp:2:
/opt/conda/envs/reserve/bin/cmdstan/stan/lib/stan_math/stan/math/prim/core/init_threadpool_tbb.hpp:9:10: fatal error: tbb/tbb_stddef.h: No such file or directory
    9 | #include <tbb/tbb_stddef.h>
      |          ^~~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [/opt/conda/envs/reserve/lib/R/etc/Makeconf:200: file16d712924aa12.o] Error 1
Error in Rcpp::sourceCpp(code = code, env = env, verbose = verbose, ...) : 
  Error 1 occurred building shared library.

I also see the output of cmdstan_make_local()

r$> cmdstan_make_local()
[1] "TBB_CXX_TYPE=gcc"                        
[2] "TBB_INTERFACE_NEW=true"                  
[3] "TBB_INC=/opt/conda/envs/reserve/include/"
[4] "TBB_LIB=/opt/conda/envs/reserve/lib/"    
[5] "PRECOMPILED_HEADERS=false"               
[6] "STAN_HAS_CXX17=true"                     
[7] "CPPFLAGS_SUNDIALS += -fPIC"              

r$> cmdstan_path()
[1] "/opt/conda/envs/reserve/bin/cmdstan"

r$> check_cmdstan_toolchain()
The C++ toolchain required for CmdStan is setup properly!

Looking at the message from exposure_functions output

I think there may be something wrong with this line, seems like there are two directories concatenated together. But I am not sure if this is the issue, or how to fix it if it’s the issue.

-D_REENTRANT -Wno-sign-compare -Wno-ignored-attributes -I'/opt/conda/envs/reserve/bin/cmdstan//opt/conda/envs/reserve/include/'

I believe cmdstanr’s expose function does not use the cmdstan build system, which would lead to this @andrjohns

Ah interesting! We use make print-CXXFLAGS to get the flags to pass to Rcpp when exposing functions, is there a different/better make target which would capture the additional flags here?

Defines are technically “supposed” to go in CPPFLAGS not CXXFLAGS, but I’m not sure if Stan actually does this in practice or not.

Edit: yes, they’re in the pre processor flags. You will probably want both CPPFLAGS and CXXFLAGS, as well as possibly LDLIBS and LDFLAGS if you’re not already using those for linking

Edit: yes, they’re in the pre processor flags. You will probably want both CPPFLAGS and CXXFLAGS

Perfect, will do. Thanks!

1 Like

Sorry I am not very familiar with how stan works behind the scene. It sounds like there is a solution for this issue? Is there a short term fix on user’s end before it’s actually fixed in cmdstanr/cmdstan?

I’ve got a PR for the fix now, once the CI passes and I merge it in you can just install cmdstanr from Github and all should work

I’ll ping you here once it’s ready

EDIT: @EKtheSage You can now install the github version:

remotes::install_github("stan-dev/cmdstanr")

And re-run your model

@andrjohns Thanks for the update. I re-compiled my model and now exposure_functions have another error:

r$> expose_functions(fit, vectorize = TRUE)

 *** caught segfault ***
address 0x7f8091aed008, cause 'invalid permissions'

Traceback:
 1: dyn.load("/tmp/RtmpXJ3uw2/sourceCpp-x86_64-conda-linux-gnu-1.0.12/sourcecpp_4cdd7639b3d0/sourceCpp_2.so")
 2: eval(ei, envir)
 3: eval(ei, envir)
 4: withVisible(eval(ei, envir))
 5: source(scriptPath, local = env)
 6: Rcpp::sourceCpp(code = code, env = env, verbose = verbose, ...)
 7: force(code)
 8: force(code)
 9: with_envvar(c(R_MAKEVARS_USER = makevars_file), {    set_makevars(new, path, makevars_file, assignment = assignment)    force(code)})
10: withr::with_makevars(c(USE_CXX14 = 1, PKG_CPPFLAGS = cppflags,     PKG_CXXFLAGS = paste0(cxxflags, cmdstanr_includes, collapse = " "),     PKG_LIBS = libs), Rcpp::sourceCpp(code = code, env = env,     verbose = verbose, ...))
11: force(code)
12: withr::with_path(repair_path(file.path(cmdstan_path(), "stan/lib/stan_math/lib/tbb")),     withr::with_makevars(c(USE_CXX14 = 1, PKG_CPPFLAGS = cppflags,         PKG_CXXFLAGS = paste0(cxxflags, cmdstanr_includes, collapse = " "),         PKG_LIBS = libs), Rcpp::sourceCpp(code = code, env = env,         verbose = verbose, ...)))
13: rcpp_source_stan(mod_stan_funs, env, verbose)
14: compile_functions(function_env, verbose, global)
15: expose_stan_functions(self$functions, global, verbose)
16: stanmodel$expose_functions()
17: withCallingHandlers(expr, message = function(c) if (inherits(c,     classes)) tryInvokeRestart("muffleMessage"))
18: suppressMessages(stanmodel$expose_functions())
19: .expose_functions_cmdstanr(stanmodel, vectorize = vectorize,     env = env, ...)
20: expose_functions.brmsfit(fit, vectorize = TRUE)
21: expose_functions(fit, vectorize = TRUE)

Possible actions:
1: abort (with core dump, if enabled)
2: normal R exit
3: exit R without saving workspace
4: exit R saving workspace

I was able to solve it by using the information on this thread

Basically need to set STAN_THREADS=TRUE in make/local and rebuild cmdstan.

cmdstan_make_local(
  cpp_options = list(
    'STAN_THREADS' = TRUE
  )
)

rebuild_cmdstan()
1 Like