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

Я использую RStan для выборки из большого количества гауссовских процессов (GP), то есть с помощью функции 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() мог бы сыграть некоторую роль в решении, но я не добился успеха, используя его для выгрузки DLL, и я подозреваю, что после выгрузки DLL я столкнусь с тем же segfault, что и раньше. .

РЕДАКТИРОВАТЬ: добавление минимального полнофункционального примера:

Код 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 стандартных моделей.


person Doug Jackson    schedule 18.07.2014    source источник
comment
Я удивлен, что для каждого процесса загружается другая DLL. Интересно, будет ли проще всего предотвратить это. Можете ли вы предоставить минимальный, но полностью функциональный пример кода, отражающего вашу проблему?   -  person nograpes    schedule 18.07.2014
comment
Это проблема и ограничение (R) Stan. Rcpp просто помогает создать динамически загружаемую библиотеку; он не имеет представления о целесообразности загрузки сотен из них. Я подозреваю, что в конце концов вы достигнете предела ОС (сверх установленного вами жестко заданного предела R).   -  person Dirk Eddelbuettel    schedule 19.07.2014


Ответы (2)


Я не могу говорить о проблемах, связанных с 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)
}

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

person jrnold    schedule 18.07.2014
comment
Для полноты картины, если у вас была веская причина для загрузки 100 DLL в сеансе R, я думаю, вы могли бы использовать функцию dyn.unload, чтобы выгрузить некоторые из них с помощью dyn.unload(file.path(tempdir(), paste0(get_stanmodel(stanfit)@dso@dso_filename, .Platform$dynlib.ext))), где stanfit - это объект, созданный функциями sampling или stan. Или вы можете заменить get_stanmodel(stanfit) объектом, созданным stan_model. Однако вы были бы очень ограничены в том, что вы могли бы впоследствии делать с объектом stanfit без сбоя R (без monitor, print, log_prob и т. Д.) - person Ben Goodrich; 19.07.2014

Вот что я использую для запуска нескольких моделей 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]))
person Frederic H.    schedule 09.06.2016