2011-07-24 10 views
7

Tuve algunos problemas con el uso de foreach% dopar% al cargar objetos del disco en la memoria ... Los objetos no se cargan cuando intento cargarlos cuando uso foreach% dopar% (funciona cuando uso solo% do%) A continuación se muestra un ejemplo simple que muestra mi problema.la carga no funciona con foreach y% dopar%

envir = .GlobalEnv 

x <- "X test" 
y <- "Y test" 
z <- "Z test" 

save(x, file="x.RData") 
save(y, file="y.RData") 
save(z, file="z.RData") 

rm(x) 
rm(y) 
rm(z) 

objectsNamesVector <- c("x", "y", "z") 

foreach(i=1:length(objectsNamesVector), .combine=function (...) NULL, .multicombine=TRUE) %do% { 
    print(paste("Loading object ", objectsNamesVector[i]," - ", i, " of ", length(objectsNamesVector), sep="")) 
    load(file=paste(objectsNamesVector[i], ".RData", sep=""), envir=envir) 
} 

print(x) 
print(y) 
print(z) 

rm(x) 
rm(y) 
rm(z) 

foreach(i=1:length(objectsNamesVector), .combine=function (...) NULL, .multicombine=TRUE) %dopar% { 
    print(paste("Loading object ", objectsNamesVector[i]," - ", i, " of ", length(objectsNamesVector), sep="")) 
    load(file=paste(objectsNamesVector[i], ".RData", sep=""), envir=envir) 
} 

print(x) 
print(y) 
print(z) 

Resultado de la ejecución de este código es (sin el ">"):

envir = .GlobalEnv 

x <- "X test" 
y <- "Y test" 
z <- "Z test" 

save(x, file="x.RData") 
save(y, file="y.RData") 
save(z, file="z.RData") 

rm(x) 
rm(y) 
rm(z) 

objectsNamesVector <- c("x", "y", "z") 

foreach(i=1:length(objectsNamesVector), .combine=function (...) NULL, .multicombine=TRUE) %do% { 
+ print(paste("Loading object ", objectsNamesVector[i]," - ", i, " of ", length(objectsNamesVector), sep="")) 
+ load(file=paste(objectsNamesVector[i], ".RData", sep=""), envir=envir) 
+ } 
[1] "Loading object x - 1 of 3" 
[1] "Loading object y - 2 of 3" 
[1] "Loading object z - 3 of 3" 
NULL 

print(x) 
[1] "X test" 
print(y) 
[1] "Y test" 
print(z) 
[1] "Z test" 
rm(x) 
rm(y) 
rm(z) 

foreach(i=1:length(objectsNamesVector), .combine=function (...) NULL, .multicombine=TRUE) %dopar% { 
+ print(paste("Loading object ", objectsNamesVector[i]," - ", i, " of ", length(objectsNamesVector), sep="")) 
+ load(file=paste(objectsNamesVector[i], ".RData", sep=""), envir=envir) 
+ } 
NULL 

print(x) 
Error in print(x) : object 'x' not found 
print(y) 
Error in print(y) : object 'y' not found 
print(z) 
Error in print(z) : object 'z' not found 

entiendo que no puedo mejorar IO con foreach ya IO es secuencial en mi arquitectura. Simplemente me gustaría entender por qué esto no funciona ...

Gracias por su respuesta.

Saludos, Samo.

+0

Así que, supongo que es esto. ¿Puede alguien asesorar sobre qué lista de ayuda de R debería publicar esta pregunta para obtener una respuesta? Thnx. – user859821

Respuesta

2

Creo que el problema es que el %do% es capaz de escribir en el entorno global, mientras que el %dopar% no lo está. Usar %do% es muy útil si desea la sintaxis foreach() y otras características, pero no necesita un servidor paralelo.

Además, como el %do% se realiza en secuencia, se puede dejar al usuario el entorno global limpio, ya que no habrá condiciones de carrera. En el caso paralelo, puede tener condiciones de carrera (es decir, algunas tareas paralelas pueden terminar antes que otras y puede crear resultados aleatorios difíciles de reproducir).

Debido a las condiciones de carrera, no es una buena idea tener este tipo de operación escribiendo directamente en el entorno global, si puede evitarlo. Un usuario posterior puede tomar dicho código secuencial y reemplazar %do% con %dopar%, con la esperanza de obtener resultados más rápidos, pero no obtener los mismos resultados. Para su crédito, ha encontrado un claro ejemplo de dónde puede ocurrir eso.

+0

Gracias. Empecé a usar% dopar% sin entender cómo funciona el back-end paralelo en R, de ahí mis ideas equivocadas. – user859821

2

Es difícil decir exactamente lo que está pasando sin saber:

  1. Cuál es su sistema operativo.
  2. Lo backend paralelo que se haya registrado para dopar%%

Si está utilizando DOMC, a continuación, el código dentro del bloque foreach ejecuta dentro de un "proceso ed tenedor(). Esto significa que tiene su propio espacio de memoria, y aunque modificará .GlobalEnv localmente, no lo modificará dentro del proceso "maestro". Es decir, terminas modificando una copia de .GlobalEnv.

Si ejecuta este código sin back-end registrado, se ejecuta "correctamente", porque% dopar% termina ejecutando como% do% does.

Una forma de manejar esta situación podría ser cargar objetos en nuevos entornos, y luego usar el parámetro .combine de foreach() para copiar el contenido de cada uno de ellos en .GlobalEnv.

+0

Gracias por tu explicación. Ahora entiendo lo que está sucediendo detrás de escena. – user859821

1

Tuve el mismo problema cuando traté de usar "foreach" + "doSnow" para ejecutar un programa paralelo en una computadora de 32 núcleos. "foreach" dejó de funcionar y dijo: ¡NO SE ENCUENTRA UN OBJETO! Utilicé el ".export" en "foreach" para incluir ese objeto externo, ¡pero aún decía que el OBJETO NO SE ENCONTRÓ! Cuando probé "doParallel" NO "doSnow", ¡funcionó!

external_object <-1

biblioteca (foreach)
biblioteca (doParallel)
registerDoParallel (núcleos = 32)
getDoParWorkers()

foreach (i = 1: 32, .combine = c .multicombine = TRUE, .export = c ("objeto_externo"))% dopar% { external_object }

+0

Este es un problema diferente al tema de esta pregunta, que trata sobre los efectos secundarios del entorno global en los bucles foreach. Además, su ejemplo funciona para mí con doSNOW, excepto que se emite una advertencia que dice que 'external_object' ya se exportó, lo que indica que no necesita usar' .export'. No estoy seguro de lo que estaba mal con su ejemplo doSNOW, pero doParallel a menudo funciona cuando doSNOW falla en Linux y Mac OS X debido al uso de doParallel de mclapply en lugar de clusterApplyLB. –

Cuestiones relacionadas