Asignación Global, Paralelismo y Foreach
environment (1)
Acabo de ejecutar un análisis de larga duración (más de 24 horas) en múltiples conjuntos de datos. Como soy flojo y no quería lidiar con múltiples sesiones de R
y reunir los resultados luego, los ejecuté en paralelo usando foreach
.
El análisis devuelve un entorno lleno de resultados (y objetos intermedios), por lo que intenté asignar los resultados a entornos globales, solo para descubrir que esto no funcionaba. Aquí hay un código para ilustrar:
library(doMC)
library(foreach)
registerDoMC(3)
bigAnalysis <- function(matr) {
results <- new.env()
results$num1 <- 1
results$m <- matrix(1:9, 3, 3)
results$l <- list(1, list(3,4))
return(results)
}
a <- new.env()
b <- new.env()
c <- new.env()
foreach(i = 1:3) %dopar% {
if (i == 1) {
a <<- bigAnalysis(data1)
plot(a$m[,1], a$m[,2]) # assignment has worked here
} else if (i == 2) {
b <<- bigAnalysis(data2)
} else {
c <<- bigAnalysis(data3)
}
}
# Nothing stored :(
ls(envir=a)
# character(0)
He usado la asignación global dentro de foreach
antes (dentro de una función) para poblar matrices que había configurado previamente con datos (donde no podía hacerlo bien con .combine
), así que pensé que esto funcionaría.
EDITAR: parece que esto solo funciona dentro del cuerpo de una función:
f <- function() {
foreach(i = 1:3) %dopar% {
if (i == 1) {
a <<- bigAnalysis(data1)
} else if (i == 2) {
b <<- bigAnalysis(data2)
} else {
c <<- bigAnalysis(data3)
}
}
d <- new.env()
d$a <- a
d$b <- b
d$c <- c
return(d)
}
¿Por qué funciona esto en una función, pero no en el entorno de nivel superior?
Sus intentos de asignar a variables globales en el bucle foreach
están fallando porque están sucediendo en los procesos de trabajo bifurcados por mclapply
. Esas variables no se envían al proceso maestro, por lo que se pierden.
Podrías probar algo como esto:
r <- foreach(i = 1:3) %dopar% {
if (i == 1) {
bigAnalysis(data1)
} else if (i == 2) {
bigAnalysis(data2)
} else {
bigAnalysis(data3)
}
}
a <- r[[1]]
b <- r[[2]]
c <- r[[3]]
ls(a)
Utiliza la función de combinación predeterminada que devuelve los tres objetos de entorno en una lista.
Ejecutar el bucle foreach
en una función no va a hacer que funcione. Sin embargo, las asignaciones funcionarían si no llamaras registerDoMC
para que realmente estuvieras ejecutando secuencialmente. En ese caso, realmente está asignando tareas al entorno global del proceso maestro.