Dealing with Catalina

I don’t know if this matters, but when I download rstan (since I uninstalled it to see if that would work), it is going into an unfamiliar folder to me (The downloaded binary packages are in
/var/folders/bp/4z337q_5263ghp8njdx0_48h0000gp/T//RtmpRtWwIC/downloaded_packages), which is not the same folder that packages are saved to when I use the install.packages 'button" in the file, plots, packages, etc. pane (/Library/Frameworks/R.framework/Versions/3.5/Resources/library/[Default]).

That is fine. When you do

library(rstan)
example(stan_model, run.dontrun = TRUE)

what is the line that has the string error: (with the colon)?

What is

  Rv <- R.version
  GOOD <- file.path("Library", "Frameworks", "R.framework", "Versions", 
                     paste(Rv$major, substr(Rv$minor, 1, 1), sep = "."), 
                     "Resources", "lib", "libc++.1.dylib")
  GOOD

? Does that file really exist?

I think there are 2? One at the beginning and one at the end:

Error in compileCode(f, code, language = language, verbose = verbose) :
Compilation ERROR, function(s)/method(s) not created! In file included from file9327259324e.cpp:8:

and

Error in sink(type = “output”) : invalid connection

Oh, you mean in the actual stan model, sorry. The error does not specify a line. It says compilation error and then repeats the same string to show the file path where the file that did not compile is? I think.

Between those two. After about 500 lines of C++ code. After it says clang++ .... There will be error:

Sorry, I’m not sure where to look for this–guessing not in the console.

Thanks!

@bgoodri, something is fishy here. It does not consistently work, if I run this
bar.R (1.4 KB) model.stan (2.1 KB)

Every now and then it samples correctly and doesn’t throw an error. Also if it throws an error then it’s not a given that fix_Mac() will fix it… Could someone with Catalina run the above 5-10 times (each time restarting RStudio and not saving the environment in-between?

I’d be most grateful if you could tell me if you also see inconsistent behavior in that it samples correctly every now and then!

Sorry @bgoodri, but there’s something more going on here :(

@bgoodri & @torkar and on the sixth implementation:

SAMPLING FOR MODEL 'model' NOW (CHAIN 3).
Chain 3: 
Chain 3: Gradient evaluation took 2.2e-05 seconds
Chain 3: 1000 transitions using 10 leapfrog steps per transition would take 0.22 seconds.
Chain 3: Adjust your expectations accordingly!
Chain 3: 
Chain 3: 
Chain 3: Iteration:    1 / 2000 [  0%]  (Warmup)
[1] "Error in sampler$call_sampler(args_list[[i]]) : " "  c++ exception (unknown reason)"                
error occurred during calling the sampler; sampling not done

Shit, that’s what I was afraid of… Well, I don’t think @bgoodri will like this present when he wakes up…

This model does not sample ever on catalina but works fine on the previous version

functions {
    real gpareto_lpdf(vector y, real ymin, real k, real sigma) {
      // generalised Pareto log pdf 
      int N = rows(y);
      real inv_k = inv(k);
      if (k<0 && max(y-ymin)/sigma > -inv_k)
        reject("k<0 and max(y-ymin)/sigma > -1/k; found k, sigma =", k, sigma)
      if (sigma<=0)
        reject("sigma<=0; found sigma =", sigma)
      if (fabs(k) > 1e-15)
        return -(1+inv_k)*sum(log1p((y-ymin) * (k/sigma))) -N*log(sigma);
      else
        return -sum(y-ymin)/sigma -N*log(sigma); // limit k->0
    }
    real gpareto_cdf(vector y, real ymin, real k, real sigma) {
      // generalised Pareto cdf
      real inv_k = inv(k);
      if (k<0 && max(y-ymin)/sigma > -inv_k)
        reject("k<0 and max(y-ymin)/sigma > -1/k; found k, sigma =", k, sigma)
      if (sigma<=0)
        reject("sigma<=0; found sigma =", sigma)
      if (fabs(k) > 1e-15)
        return exp(sum(log1m_exp((-inv_k)*(log1p((y-ymin) * (k/sigma))))));
      else
        return exp(sum(log1m_exp(-(y-ymin)/sigma))); // limit k->0
    }
    real gpareto_lcdf(vector y, real ymin, real k, real sigma) {
      // generalised Pareto log cdf
      real inv_k = inv(k);
      if (k<0 && max(y-ymin)/sigma > -inv_k)
        reject("k<0 and max(y-ymin)/sigma > -1/k; found k, sigma =", k, sigma)
      if (sigma<=0)
        reject("sigma<=0; found sigma =", sigma)
      if (fabs(k) > 1e-15)
        return sum(log1m_exp((-inv_k)*(log1p((y-ymin) * (k/sigma)))));
      else
        return sum(log1m_exp(-(y-ymin)/sigma)); // limit k->0
    }
    real gpareto_lccdf(vector y, real ymin, real k, real sigma) {
      // generalised Pareto log ccdf
      real inv_k = inv(k);
      if (k<0 && max(y-ymin)/sigma > -inv_k)
        reject("k<0 and max(y-ymin)/sigma > -1/k; found k, sigma =", k, sigma)
      if (sigma<=0)
        reject("sigma<=0; found sigma =", sigma)
      if (fabs(k) > 1e-15)
        return (-inv_k)*sum(log1p((y-ymin) * (k/sigma)));
      else
        return -sum(y-ymin)/sigma; // limit k->0
    }
    real gpareto_rng(real ymin, real k, real sigma) {
      // generalised Pareto rng
      if (sigma<=0)
        reject("sigma<=0; found sigma =", sigma)
      if (fabs(k) > 1e-15)
        return ymin + (uniform_rng(0,1)^-k -1) * sigma / k;
      else
        return ymin - sigma*log(uniform_rng(0,1)); // limit k->0
    }
   real gparetoJacP2L2(vector y, real ymin, real k, real sigma) {
       // L2 Jacobian for GPD with ymin known
      int N = rows(y);
      real inv_k = inv(k);
      real prejac1 = sum((y-ymin).*(y-ymin)) * sum((1+(k/sigma)*(y-ymin)).*(1+(k/sigma)*(y-ymin)).*log1p((k/sigma)*(y-ymin)).*log1p((k/sigma)*(y-ymin)))
                     -sum((y-ymin).*(1+(k/sigma)*(y-ymin)).*log1p((k/sigma)*(y-ymin)))*sum((y-ymin).*(1+(k/sigma)*(y-ymin)).*log1p((k/sigma)*(y-ymin)));
      real prejac2=sum((y-ymin).*(y-ymin))*sum((y-ymin).*(y-ymin).*(y-ymin).*(y-ymin))
               -sum((y-ymin).*(y-ymin).*(y-ymin))*sum((y-ymin).*(y-ymin).*(y-ymin));
      if (k<0 && max(y-ymin)/sigma > -inv_k)
          reject("k<0 and max(y-ymin)/sigma > -1/k; found k, sigma =", k, sigma)
      if (sigma<=0)
         reject("sigma<=0; found sigma =", sigma)
      if (fabs(k) > 1e-15)
         return -log(k*k)+0.5*log(prejac1);
      else
         return -log(2)-2*log(sigma)+0.5*log(prejac2); // limit k->0
      }
}
data {
  real ymin;
  int<lower=0> N;
  vector<lower=ymin>[N] y;
}
transformed data {
  real ymax = max(y);
}
parameters {
  real<lower=0> sigma; 
  //real k;
  real<lower=-sigma/(ymax-ymin)> k; 
}
model {
  y ~ gpareto(ymin, k, sigma);
  target += gparetoJacP2L2(y, ymin, k, sigma); //Fiducial Jacobian
}
generated quantities {
  real<lower=0> y_sim=gpareto_rng(ymin, k, sigma);
}

The code to run the program is

n=1000
x=-log(runif(n))

library(rstan)
source('FixMAC.R')

fitted_model = stan_model(file='pareto_gfi.stan') 
fix_Mac(fitted_model)

stan_data <- list(y=x, N = n, ymin = 0)

stan_fit = sampling(fitted_model, data = stan_data)
plot(stan_fit,show_density=TRUE)
summary(stan_fit)

Always provide a complete minimum working example incl. data. Add file + data to your post as a file and people can easily reproduce it :)

Sorry - it was a few steps above. I edited my post.

1 Like

Rv ← R.version
GOOD ← file.path(“Library”, “Frameworks”, “R.framework”, “Versions”,

  •               paste(Rv$major, substr(Rv$minor, 1, 1), sep = "."), 
    
  •               "Resources", "lib", "libc++.1.dylib")
    

GOOD
[1] “Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libc++.1.dylib”
Rv
_
platform x86_64-apple-darwin15.6.0
arch x86_64
os darwin15.6.0
system x86_64, darwin15.6.0
status
major 3
minor 6.1
year 2019
month 07
day 05
svn rev 76782
language R
version.string R version 3.6.1 (2019-07-05)
nickname Action of the Toes

1 Like

@coatless: Should something be added to LDFLAGS in Makevars with Macs so that it links against the libc++ provided by CRAN? It seems that the fix @kevinushey suggested does not always work.

Perhaps the ~/.R/Makevars should have LDFLAGS set with

-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib

Thus, the full file would be:

# clang: start
CFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
CCFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
CXXFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
CPPFLAGS=-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
LDFLAGS=-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib
# clang: end

Under this configuration, I can successfully sample multiple times after running the fix_Mac() function given previously. c.f.

fix_Mac <- function(sm) {
  stopifnot(is(sm, "stanmodel"))
  dso_last_path <- sm@dso@.CXXDSOMISC$dso_last_path
  CLANG_DIR <- tail(n = 1, grep("clang[456789]", 
                                x = list.dirs("/usr/local", recursive = FALSE), 
                                value = TRUE))
  if (length(CLANG_DIR) == 0L) stop("no clang from CRAN found")
  LIBCPP <- file.path(CLANG_DIR, "lib", "libc++.1.dylib")
  if (!file.exists(LIBCPP)) stop("no unique libc++.1?.dylib found")
  Rv <- R.version
  GOOD <- file.path("/Library", "Frameworks", "R.framework", "Versions", 
                    paste(Rv$major, substr(Rv$minor, 1, 1), sep = "."), 
                    "Resources", "lib", "libc++.1.dylib")
  if (!file.exists(GOOD)) stop(paste(GOOD, "not found"))
  cmd <- paste(
    "install_name_tool",
    "-change",
    LIBCPP,
    GOOD,
    dso_last_path
  )
  system(cmd)
  dyn.unload(dso_last_path)
  dyn.load(dso_last_path)
  return(invisible(NULL))
}


stancode <- 'data {real y_mean;} parameters {real y;} model {y ~ normal(y_mean,1);}'
mod <- stan_model(model_code = stancode, verbose = TRUE)
fix_Mac(mod)

fit <- sampling(mod, data = list(y_mean = 0))
fit2 <- sampling(mod, data = list(y_mean = 5))

OK. I was kind of hoping with the -L... that the fix_Mac() would not be necessary. Do you get the unknown exception thing if you compile and sample without calling fix_Mac in between?

@kevinushey I am using someone else’s Mac that has Catalina and I can confirm that previously loading another package with compiled C++ code (such as readr) is sufficient to cause

library(readr) # or another package with compiled C++

Rcpp::sourceCpp(code = 
'
#include <Rcpp.h>
using namespace Rcpp; 

// [[Rcpp::export]]
int throw_exception() { 
  std::stringstream errmsg; errmsg << "this is an exception";
  throw std::domain_error(errmsg.str()); 
  return 0;
}
'
)

throw_exception()

to say

Error in thow_exception(): c++ exception (unknown reason)

instead of

Error in thow_exception(): this is an exception

However, if I don’t load any packages containing C++ previously, then I get the expected behavior. Is this a known issue? It doesn’t have anything directly to do with rstan code, but it may have a clue as to why we are having similar problems with dynamically loaded objects with C++ code generated by rstan.

This is using /usr/local/clang7/bin/clang++ and the ~/.R/Makevars file created by @coatless installer.

Can we confirm that all of these packages are using the expected C++ standard libraries? Here’s a script that should dump this all out:


packages <- loadedNamespaces()
result <- lapply(packages, function(package) {
  
  dir <- system.file("libs", package = package)
  libs <- list.files(dir, pattern = "[.]so$", full.names = TRUE)
  if (length(libs) == 0)
    return(FALSE)
  
  output <- system(paste("otool -L", libs, "| grep -s libc++ || true"), intern = TRUE)
  if (length(output) == 0)
    return(FALSE)
  
  writeLines(paste0(package, ":"))
  writeLines(output)
  
})

As an example, I get some packages showing a mix, for some packages I installed from sources:

Rcpp:
	/Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)
xml2:
	/Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)
roxygen2:
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 800.6.0)
htmltools:
	/Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)
digest:
	/Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)
fs:
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
testthat:
	/Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)
stringi:
	/Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)

When I do

library(readr)

followed by your function on that Catalina laptop I get

readr:
        /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)

Rcpp:
        /usr/lib/libc++1.1.dylib (compatibility version 1.0.0, current version 800.6.0)

After reinstalling Rcpp using /usr/local/clang7/bin/clang++l, it switched to

Rcpp:
        /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1.0.0)

but now

Rcpp::sourceCpp(code = 
'
#include <Rcpp.h>
using namespace Rcpp; 

// [[Rcpp::export]]
int throw_exception() { 
  std::stringstream errmsg; errmsg << "this is an exception";
  throw std::domain_error(errmsg.str()); 
  return 0;
}
'
)

throw_exception()

yields

Error in thow_exception(): c++ exception (unknown reason)

irrespective of whether any other packages are loaded