2014-07-18 13 views
10

Używam RStan do pobierania próbek z dużej liczby procesów Gaussa (GP), tj. Za pomocą funkcji stan(). Dla każdego GP, że pasuje, innym DLL zostanie załadowany, jak można zaobserwować, uruchamiając komendę R, wPrzekroczono maksymalną liczbę bibliotek DLL w R

getLoadedDLLs() 

Problem biegnę na to, bo muszę się zmieścić tak wiele unikalnych GPS, I” m przekroczeniu maksymalnej liczby DLL, który może być załadowany, przy której pojawia się następujący komunikat:

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

ile można stwierdzić, to jest w Rdynload.c kodu zasady R, taki jak :

#define MAX_NUM_DLLS 100 

Moje pytanie brzmi: co można zrobić, żeby to naprawić? Budowanie R ze źródła o większej MAX_NUM_DLLS nie jest opcją, ponieważ mój kod będzie prowadzony przez współpracowników, którzy nie będą się z tym dobrze czuli. Próbowałem naiwnego podejścia po prostu rozładować biblioteki DLL za pomocą dyn.unload() w nadziei, że zostaną one ponownie załadowane, gdy będą potrzebne ponownie. Wyładunek działa dobrze, ale gdy próbuję ponownie użyć dopasowanie, R dość zaskoczeniem wywala z błędem jak:

Ja również próbował odłączania RStan w nadziei, że DLL zostanie automatycznie rozładowywane, ale utrzymują się nawet po wyładowaniu pakietu (zgodnie z oczekiwaniami, biorąc pod uwagę następujące informacje w pomocy na temat odłączania: "odłączanie nie rozładuje ogólnie żadnego dynamicznie ładowanego skompilowanego kodu (DLL)").

Z tym pytaniem, Can Rcpp package DLLs be unloaded without restarting R? wydaje się, że library.dynam.unload() może mieć pewną rolę w roztworze, ale nie miałem żadnych sukcesów używając go do rozładunku DLL, i podejrzewam, że po rozładunku DLL bym napotkasz ten sam segfault, co poprzednio.

EDIT: dodanie minimalnej, w pełni funkcjonalny przykład:

Kod 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) 
} 

Kod ten wymaga, aby następująca definicja modelu znajdować się w katalogu roboczym w pliku GP-sim. Stan (model ten jest jednym z przykładów dołączonych 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); 
} 

Uwaga: kod ten zajmuje trochę czasu, aby uruchomić, ponieważ tworzy ~ 100 modeli Stan.

+1

Jestem zaskoczony, że inna biblioteka DLL jest ładowana dla każdego procesu. Zastanawiam się, czy najłatwiej byłoby zapobiec temu zjawisku. Czy możesz podać minimalny, ale w pełni funkcjonalny przykład kodu, który rejestruje twój problem? – nograpes

+2

To jest problem i ograniczenie projektu Stan (R). Rcpp właśnie pomaga stworzyć dynamicznie ładowalną bibliotekę; nie ma widoku na to, czy wskazane jest załadowanie 100 z nich. W końcu osiągniesz limit OS (poza zakodowanym ustalonym limitem R), podejrzewam. –

Odpowiedz

7

Nie mogę mówić o problemach dotyczących bibliotek dll, ale nie należy kompilować modelu za każdym razem. Możesz skompilować model raz i użyć go ponownie, co nie spowoduje tego problemu i przyspieszy twój kod.

Funkcja stan jest opakowaniem dla stan_model, które kompiluje model i metodę sampling, która pobiera próbki z modelu. Powinieneś raz uruchomić stan_model, aby skompilować model i zapisać go w obiekcie, a następnie użyć metody sampling na tym obiekcie do rysowania próbek.

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) 
} 

ta jest podobna do problemu prowadzenia łańcuchów równoległych, omówiony w Rstan wiki. Twój kod mógłby zostać przyspieszony przez zamianę pętli for na coś, co przetwarza próbkowanie równolegle.

+3

Dla kompletności, jeśli masz ważny powód do załadowania 100 plików DLL w sesji R, myślę, że możesz użyć funkcji 'dyn.unload', aby wyładować niektóre z nich za pomocą' dyn.unload (file.path (tempdir() , paste0 (get_stanmodel (stanfit) @ dso @ dso_filename, .Platform $ dynlib.ext))) ', gdzie' stanfit' jest obiektem wytworzonym przez funkcję 'sampling' lub' stan'. Lub możesz zamienić 'get_stanmodel (stanfit)' na obiekt utworzony przez 'stan_model'. Będziesz jednak bardzo ograniczony co do tego, co możesz później zrobić z obiektem 'stanfit' bez awarii R (bez' monitora', 'print',' log_prob', itp.) –

0

Oto, co używam do uruchamiania kilku modeli stan z rzędu (Win10, R 3.3.0).

Potrzebowałem nie tylko zwolnić pliki dll, ale także usunąć je i inne pliki tymczasowe. Wówczas nazwa pliku była dla mnie inna niż znaleziona w obiekcie stan, jak zasugerował Ben.

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])) 
Powiązane problemy