2015-02-16 11 views
14

Ecco un esempio di esempio per illustrare il mio problema.Utilizzo di source() all'interno di cicli foreach paralleli

library(foreach) 
library(doMC) 
registerDoMC(cores=2) 

foreach(i = 1:2) %dopar%{ 
    i + 2 
} 
[[1]] 
[1] 3 

[[2]] 
[1] 4 

Fin qui tutto bene ...

Ma se il codice i + 2 viene salvato nel file addition.R e che io chiamo il file utilizzando source() poi

> foreach(i = 1:2) %dopar%{ 
+ source("addition.R") 
+ } 
Error in { : task 1 failed - "object 'i' not found" 
+3

Provare questo 'source (" addtition.R ", local = T)' per valutare la sorgente nell'ambiente in cui è chiamato – NicE

+0

I find source() chiama in% dopar% blocchi rallenta notevolmente il calcolo, come i processi figli devono ottenere quel file sorgente attraverso il networking –

risposta

10

non posso pienamente riprodurre la vostra giocattolo, ma ho avuto un problema di soppressione, che sono stato in grado di risolvere:

source(file, local = TRUE) 

che dovrebbe analizzare la sorgente nell'ambiente locale, cioè riconoscendo i.

3

Il commento di NiceE e la risposta di Sosel riguardano già questo; quando si chiama source(file), il valore predefinito è source(file, local = FALSE), il che significa che il codice nel file di origine sta valutando nell'ambiente globale ("area di lavoro dell'utente") e non esiste, cfr. ?source. Si noti che non vi è alcuna variabile i nell'ambiente globale. La soluzione è assicurarsi che il file sia fornito nell'ambiente che lo chiama, cioè per utilizzare source(file, local = TRUE).

Soluzione:

library("foreach") 

y <- foreach(i = 1:2) %dopar% { 
    i + 2 
} 
str(y) 

doMC::registerDoMC(cores = 2L) 
y <- foreach(i = 1:2) %dopar% { 
    source("addition.R", local = TRUE) 
} 
str(y) 

Esempio dello stesso problema con un for() ciclo:

Il fatto che source() viene valutata nel contesto globale che è diverso dall'ambiente chiamante dove i vite può anche essere illustrato utilizzando un ciclo for regolare eseguendo il ciclo for in un altro ambiente rispetto al globale, ad es all'interno di una funzione o per:

local({ 
    for(i in 1:2) { 
    source("addition.R") 
    } 
}) 

che dà:

Error in eval(ei, envir) : object 'i' not found 

Ora, la ragione per cui le suddette foreach(i = 1:2) %dopar% { source("addition.R") } opere con registerDoSEQ()se e solo se chiamato dal contesto globale, è che allora la L'iterazione foreach viene valutata nell'ambiente di chiamata, che è l'ambiente globale, che è l'ambiente utilizzato da source(). Tuttavia, se si utilizza local(foreach(i = 1:2) %dopar% { ... }) anche questo fallisce in modo analogo alla precedente chiamata local(for(i in 1:2) { ... }).

In conclusione: non accade nulla di magico, ma capirlo è un po 'noioso.

4

Ho finalmente risolto il problema convertendo la sorgente ("addition.R") in una funzione e passando semplicemente le variabili in essa. Non so perché, ma le soluzioni suggerite basate su source(file, local = TRUE) non funzionano.

+0

Che 'source (" addition.R ", local = TRUE)' non funzioni per voi non ha senso per me. Puoi replicare l'errore con l'esempio riproducibile che ho adottato dal tuo OP? O ti stai riferendo a uno script R più complesso? Se quest'ultimo, ci possono essere milioni di ragioni. Inoltre, quale setup/'sessionInfo()'? – HenrikB

+0

Sto parlando dello script esatto e dell'errore esatto. – CoderInNetwork

+0

Questo è davvero strano. Hai l'errore anche in quell'esempio 'local ({for (i in 1:12) ...})'? Se è così, questo escluderebbe foreach ecc. Importantemente, qual è il tuo 'sessionInfo()' dopo aver ricevuto l'errore? Sospetto che ci sia qualcosa nella tua configurazione che causa questa differenza. Esecuzione di R nel terminale o in una GUI (ad esempio RStudio)? – HenrikB