全球任务,并行和前期

时间:2013-09-12 11:44:39

标签: r foreach environment

我刚刚对多组数据进行了长时间运行的分析(24小时以上)。由于我很懒,并且不想处理多个R会话并在之后将结果拉到一起,因此我使用foreach并行运行它们。

分析返回一个充满结果(和中间对象)的环境,因此我尝试将结果分配给全局环境,但却发现这不起作用。以下是一些代码来说明:

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)

我在foreach之前(在函数内)使用了全局赋值来填充我之前用数据设置的矩阵(我不能很好地使用.combine),所以我认为这会奏效。

编辑:看来这只能在函数体内运行:

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

为什么这在函数中有效,而在顶层环境中却无效?

1 个答案:

答案 0 :(得分:3)

您在foreach循环中分配给全局变量的尝试失败了,因为它们发生在由mclapply分叉的工作进程上。这些变量不会被发送回主进程,因此它们会丢失。

您可以尝试这样的事情:

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)

这使用默认的合并函数,它返回列表中的三个环境对象。

在函数中执行foreach循环不会使它工作。但是,如果您未调用registerDoMC以便实际按顺序运行,则分配将起作用。在这种情况下,您确实正在为主进程的全局环境进行分配。