2014-07-18 17 views
10

Sto usando RStan per campionare da un gran numero di processi gaussiani (GP), cioè utilizzando la funzione stan(). Per ogni GP che mi adatto, un'altra DLL viene caricato, come si può vedere eseguendo il comando RNumero massimo superato di DLL in R

getLoadedDLLs() 

Il problema che sto funzionando in è che, perché ho bisogno di adattarsi così tanti medici unici, I' m supera il numero massimo di DLL che possono essere caricati, a questo punto viene visualizzato il seguente errore:

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

per quanto posso dire, questo è impostato in Rdynload.c del codice di base R, come segue :

#define MAX_NUM_DLLS 100 

Quindi, la mia domanda è, cosa si può fare per risolvere questo problema? Costruire R dalla sorgente con un MAX_NUM_DLLS maggiore non è un'opzione, in quanto il mio codice verrà eseguito da collaboratori che non si sentiranno a proprio agio con tale processo. Ho provato l'approccio ingenuo di scaricare semplicemente le DLL usando dyn.unload() nella speranza che si ricaricassero appena saranno nuovamente necessari. Lo scarico funziona bene, ma quando provo ad usare di nuovo la misura, R si blocca abbastanza sorprende con un errore simile:

Ho anche provato staccando RStan nella speranza che le DLL verrebbero scaricati automaticamente, ma persistono anche dopo aver scaricato il pacchetto (come previsto, visto quanto segue nella guida per il detach: "il distacco non in genere scarica alcun codice compilato (DLL) caricato dinamicamente").

Da questa domanda, Can Rcpp package DLLs be unloaded without restarting R?, sembra che library.dynam.unload() potrebbe avere un qualche ruolo nella soluzione, ma non ho avuto alcun successo di usarlo per scaricare le DLL, e ho il sospetto che dopo lo scarico della DLL mi piacerebbe correre in lo stesso segfault di prima.

EDIT: aggiunta di un minimo, ad esempio completamente funzionale:

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

Questo codice richiede che la seguente definizione del modello sia nella directory di lavoro in un file gp-sim. stan (questo modello è uno degli esempi inclusi con 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); 
} 

Nota: questo codice prende un po 'di tempo per l'esecuzione, in quanto è la creazione di ~ 100 modelli Stan.

+1

Sono sorpreso che un'altra DLL venga caricata per ogni processo. Mi chiedo se sarebbe più facile evitare che ciò accada in primo luogo. Puoi fornire un esempio di codice minimale, ma perfettamente funzionante che cattura il tuo problema? – nograpes

+2

Questo è un problema di progettazione (R) Stan e limitazione. Rcpp aiuta solo a creare la libreria caricabile dinamicamente; non ha la possibilità di caricare 100 di essi. Alla fine avrò un limite del sistema operativo (oltre il limite R hardcoded che hai identificato) sospetto. –

risposta

7

Non riesco a parlare per i problemi relativi alle DLL, ma non è necessario compilare il modello ogni volta. Puoi compilare il modello una sola volta e riutilizzarlo, il che non causerà questo problema e accelererà il tuo codice.

La funzione stan è un involucro per stan_model che compila il modello e il metodo sampling che trae campioni dal modello. È necessario eseguire stan_model una volta per compilare il modello e salvarlo su un oggetto, quindi utilizzare il metodo sampling su quell'oggetto per disegnare campioni.

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

Questo è simile al problema di gestire catene parallele, discusso nel Rstan wiki. Il tuo codice potrebbe essere accelerato sostituendo il ciclo for con qualcosa che elabori il campionamento in parallelo.

+3

Per completezza, se hai avuto un valido motivo per caricare 100 DLL in una sessione R, penso che potresti usare la funzione 'dyn.unload' per scaricarne alcuni con' dyn.unload (file.path (tempdir()) , paste0 (get_stanmodel (stanfit) @ dso @ dso_filename, .Platform $ dynlib.ext))) ', dove' stanfit' è un oggetto prodotto dalle funzioni 'sampling' o' stan'. Oppure puoi sostituire 'get_stanmodel (stanfit)' con l'oggetto prodotto da 'stan_model'. Tuttavia, sareste molto limitati su cosa potreste fare successivamente con l'oggetto 'stanfit' senza arrestare R (nessun' monitor', 'print',' log_prob', ecc.) –

0

Ecco, cosa uso per eseguire diversi modelli stan in una riga (Win10, R 3.3.0).

Ho bisogno non solo di scaricare i file dll ma anche di eliminarli e altri file temporanei. Quindi, il nome del file per me era diverso da quello trovato nell'oggetto stan, come suggeriva 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]))