加载不适用于foreach和%dopar%

时间:2011-07-24 00:37:55

标签: r foreach

在将对象从磁盘加载到内存时,我遇到了使用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)

执行此代码的结果是(没有“&gt;”):

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在我的架构上是顺序的。我只想理解为什么这不起作用......

感谢您的回答。

此致 萨莫。

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:2)

很难在不知情的情况下确切知道发生了什么:

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

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

    如果执行此代码而没有注册后端,则执行“正确”,因为%dopar%最终执行为%do%。

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

答案 2 :(得分:2)

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

external_object&lt; - 1

库(的foreach)
库(doParallel)
registerDoParallel(核= 32)
getDoParWorkers()

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