【问题标题】:load does not work with foreach and %dopar%负载不适用于 foreach 和 %dopar%
【发布时间】:2011-10-11 20:46:16
【问题描述】:

在将对象从磁盘加载到内存时,我遇到了一些使用 foreach %dopar% 的问题...当我尝试在使用 foreach %dopar% 时加载对象时未加载对象(当我仅使用 %do% 时它有效)下面是一个显示我的问题的简单示例。

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)

执行此代码的结果是(不带“>”):

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

我知道我无法使用 foreach 改进 IO,因为 IO 在我的架构上是连续的。我只是想了解为什么这不起作用...

感谢您的回答。

问候, 萨摩。

【问题讨论】:

  • 所以,我想就是这样。也许有人可以建议我应该发布这个问题以获得答案的 R-help 列表吗?谢谢。

标签: r foreach


【解决方案1】:

我认为问题在于%do% 能够写入全局环境,而%dopar% 则不能。如果您想要 foreach() 语法和其他好东西,但不需要并行后端,使用 %do% 非常有用。

另外,由于%do% 是按顺序完成的,因此保持全局环境清洁可以留给用户,因为不会出现竞争条件。在并行情况下,您可能会遇到竞争条件(即,一些并行任务可能会先于其他任务完成,并且可能会产生随机的、难以重现的结果)。

由于竞争条件,如果可以避免的话,将这种操作直接写入全局环境并不是一个好主意。以后的用户可能会采用这样的顺序代码并将%do% 替换为%dopar%,希望得到更快的结果,但不能得到相同的结果。值得称赞的是,您已经找到了一个清晰的例子来说明可能发生的情况。

【讨论】:

  • 谢谢。我开始使用 %dopar% 时不了解 R 中的并行后端实际上是如何工作的,因此我产生了误解。
【解决方案2】:

在不知道的情况下很难准确地判断发生了什么:

  1. 您的操作系统是什么。
  2. 您向 %dopar% 注册了哪些并行后端

如果您使用的是 doMC,那么 foreach 块中的代码将在 fork() 的进程中执行。这意味着它有自己的内存空间,虽然它会在本地修改 .GlobalEnv,但不会在“主”进程中修改它。也就是说,您最终会修改 .GlobalEnv 的副本。

如果您在没有注册后端的情况下执行此代码,它会“正确”执行,因为 %dopar% 最终会像 %do% 一样执行。

处理这种情况的一种方法可能是将对象加载到新环境中,然后使用 foreach() 的 .combine 参数将每个对象的内容复制到 .GlobalEnv 中。

【讨论】:

  • 感谢您的解释。我现在明白幕后发生了什么。
【解决方案3】:

当我尝试使用“foreach”+“doSnow”在 32 核计算机上运行并行程序时,我遇到了同样的问题。 “foreach”停止工作并说:未找到对象!我确实在“foreach”中使用了“.export”来包含那个外部对象,但它仍然说没有找到对象! 当我尝试“doParallel”而不是“doSnow”时,它起作用了!

external_object

库(foreach)
图书馆(doParallel)
registerDoParallel(cores=32)
getDoParWorkers()

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

【讨论】:

  • 这与本问题的主题不同,后者是关于 foreach 循环中的全局环境副作用。此外,除了发出警告说external_object 已导出,表明您不需要使用.export 之外,您的示例适用于我。我不确定你的 doSNOW 示例出了什么问题,但是当 doSNOW 在 Linux 和 Mac OS X 上失败时,doParallel 通常可以正常工作,因为 doParallel 使用的是 mclapply 而不是 clusterApplyLB。
猜你喜欢
  • 2016-05-20
  • 2020-06-14
  • 2011-04-23
  • 1970-01-01
  • 1970-01-01
  • 2016-08-02
  • 2018-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多