在将对象从磁盘加载到内存时,我遇到了使用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在我的架构上是顺序的。我只想理解为什么这不起作用......
感谢您的回答。
此致 萨莫。
答案 0 :(得分:2)
我认为问题在于%do%
能够写入全局环境,而%dopar%
则不能。如果您需要%do%
语法和其他好东西,但不需要并行后端,则使用foreach()
非常有用。
此外,由于%do%
按顺序完成,保持全局环境清洁可留给用户,因为不存在竞争条件。在并行的情况下,你可以有竞争条件(即一些并行任务可能先于其他任务完成,并且可以创建随机的,难以重现的结果)。
由于竞争条件,如果您可以避免这种情况,那么将这种操作直接写入全局环境并不是一个好主意。稍后的用户可以使用此类顺序代码并将%do%
替换为%dopar%
,希望获得更快的结果,但不能获得相同的结果。值得赞扬的是,您已经找到了一个清晰的例子,说明可能发生的地方。
答案 1 :(得分:2)
很难在不知情的情况下确切知道发生了什么:
如果您正在使用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 }