Превышено максимальное количество DLL в R

Я использую RStan для выборки из большого числа гауссовских процессов (GPs), то есть используя функцию stan(). Для каждого GP, который мне подходит, загружается другая DLL, что видно из запуска команды R

getLoadedDLLs()

Проблема, с которой я сталкиваюсь, заключается в том, что, поскольку мне нужно установить столько уникальных GP, я превысил максимальное количество DLL, которые могут быть загружены, после чего я получаю следующую ошибку:

Error in dyn.load(libLFile) : 
unable to load shared object '/var/folders/8x/n7pqd49j4ybfhrm999z3cwp81814xh/T//RtmpmXCRCy/file80d1219ef10d.so':
maximal number of DLLs reached...

Насколько я могу судить, это устанавливается в Rdynload.c базового R-кода следующим образом:

#define MAX_NUM_DLLS 100

Итак, мой вопрос: что можно сделать, чтобы исправить это? Строение R из источника с большим MAX_NUM_DLLS не является вариантом, так как мой код будет запускаться сотрудниками, которые не будут удобны в этом процессе. Я пробовал наивный подход просто выгружать библиотеки DLL, используя dyn.unload() в надежде, что они просто будут перезагружены, когда они понадобятся снова. Разгрузка работает отлично, но когда я пытаюсь снова использовать подгонку, R довольно неудивительно падает с ошибкой, например:

*** caught segfault ***
address 0x121366da8, cause 'memory not mapped'

Я также попытался отсоединить RStan в надежде, что библиотеки DLL будут автоматически выгружены, но они сохраняются даже после разгрузки пакета (как и ожидалось, учитывая следующее в справке для отсоединения: "Отключение вообще не выгружает динамически загружаемый скомпилированный код (DLL)" ).

Из этого вопроса Можно ли выгрузить DLL файлы пакета Rcpp без перезагрузки R?, кажется, что library.dynam.unload() может иметь определенную роль в решении, но я не знаю, t имел какой-либо успех, используя его для выгрузки DLL, и я подозреваю, что после выгрузки DLL я столкнулся с тем же самым segfault, что и раньше.

EDIT: добавление минимального, полнофункционального примера:

Код R:

require(rstan)

x <- c(1,2)
N <- length(x)

fits <- list()
for(i in 1:100)
{
    fits[i] <- stan(file="gp-sim.stan", data=list(x=x,N=N), iter=1, chains=1)
}

Этот код требует, чтобы следующее определение модели находилось в рабочем каталоге в файле gp-sim.stan(эта модель является одним из примеров, включенных в Stan):

// Sample from Gaussian process
// Fixed covar function: eta_sq=1, rho_sq=1, sigma_sq=0.1

data {
  int<lower=1> N;
  real x[N];
}
transformed data {
   vector[N] mu;
   cov_matrix[N] Sigma;
   for (i in 1:N) 
     mu[i] <- 0;
   for (i in 1:N) 
     for (j in 1:N)
       Sigma[i,j] <- exp(-pow(x[i] - x[j],2)) + if_else(i==j, 0.1, 0.0);
 }
 parameters {
   vector[N] y;
 }
 model {
   y ~ multi_normal(mu,Sigma);
 }

Примечание. Этот код занимает довольно много времени для запуска, поскольку он создает модели ~ 100 Stan.

Ответ 1

Я не могу говорить о проблемах, связанных с DLL, но вам не нужно собирать эту модель каждый раз. Вы можете скомпилировать модель один раз и повторно использовать ее, что не вызовет этой проблемы, и это ускорит ваш код.

Функция stan является оболочкой для stan_model, которая компилирует модель и метод sampling, который извлекает образцы из модели. Вы должны запустить stan_model один раз, чтобы скомпилировать модель и сохранить ее для объекта, а затем использовать метод sampling для этого объекта для рисования образцов.

require(rstan)

x <- c(1,2)
N <- length(x)

fits <- list()
mod <- stan_model("gp-sim.stan")
for(i in 1:100)
{
    fits[i] <- sampling(mod, data=list(x=x,N=N), iter=1, chains=1)
}

Это похоже на проблему запуска параллельных цепей, обсуждаемых в Rstan wiki. Ваш код мог бы ускориться, заменив цикл for тем, что параллельно обрабатывает выборку.

Ответ 2

Вот, что я использую для запуска нескольких моделей stan в строке (Win10, R 3.3.0).

Мне нужно было не только выгружать DLL файлы, но и удалять их и другие временные файлы. Затем имя файла для меня отличалось от найденного в объекте stan, как предположил Бен.

 dso_filenames <- dir(tempdir(), pattern=.Platform$dynlib.ext)
  filenames  <- dir(tempdir())
  for (i in seq(dso_filenames))
    dyn.unload(file.path(tempdir(), dso_filenames[i]))
  for (i in seq(filenames))
    if (file.exists(file.path(tempdir(), filenames[i])) & nchar(filenames[i]) < 42) # some files w/ long filenames that didn't like to be removeed
      file.remove(file.path(tempdir(), filenames[i]))