【问题标题】:Global Assignment, Parallelism, and foreach全局分配、并行性和 foreach
【发布时间】:2013-09-12 11:44:38
【问题描述】:

我刚刚完成了对多组数据的长时间运行分析(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)
}

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

【问题讨论】:

    标签: r foreach environment


    【解决方案1】:

    您在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 以便您实际上是按顺序运行,那么分配将起作用。在这种情况下,您实际上是在对主进程的全局环境进行分配。

    【讨论】:

    • 谢谢!你是对的,将它包装在一个函数中是行不通的。不知道为什么我认为它确实如此。可悲的是,虽然你的方法是正确的(我不可避免地退回到.combinemcapply 给了我一个关于不支持长向量的神秘错误消息(我猜是由于我的对象大小)所以我会将它们从foreach 循环。
    猜你喜欢
    • 2012-08-12
    • 1970-01-01
    • 1970-01-01
    • 2015-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    • 1970-01-01
    相关资源
    最近更新 更多