在并行 foreach 循环中使用 source()
Using source() within parallel foreach loops
这是一个玩具示例来说明我的问题。
library(foreach)
library(doMC)
registerDoMC(cores=2)
foreach(i = 1:2) %dopar%{
i + 2
}
[[1]]
[1] 3
[[2]]
[1] 4
目前一切顺利...
但是如果代码 i + 2
保存在文件 addition.R
中并且我使用 source()
调用该文件,那么
> foreach(i = 1:2) %dopar%{
+ source("addition.R")
+ }
Error in { : task 1 failed - "object 'i' not found"
我无法完全复制你的玩具,但我有一个类似的问题,我可以通过以下方式解决:
source(file, local = TRUE)
应该在本地环境下解析源,即识别i.
NiceE 的评论和 Sosel 的回答已经解决了这个问题;当调用 source(file)
时,它默认为 source(file, local = FALSE)
,这意味着源文件中的代码正在全局环境("user's workspace")中进行评估,并且有,cf。 ?source
。注意全局环境中没有变量i
。解决方案是确保文件来源于调用它的环境,即使用 source(file, local = TRUE)
.
解决方案:
library("foreach")
y <- foreach(i = 1:2) %dopar% {
i + 2
}
str(y)
doMC::registerDoMC(cores = 2L)
y <- foreach(i = 1:2) %dopar% {
source("addition.R", local = TRUE)
}
str(y)
使用 for()
循环的相同问题示例:
source()
是在不同于 i
所在的调用环境的全局环境中求值的事实也可以通过 运行 for 使用常规的 for 循环来说明在不同于全局的另一个环境中循环,例如在函数内部或通过:
local({
for(i in 1:2) {
source("addition.R")
}
})
给出:
Error in eval(ei, envir) : object 'i' not found
现在,上面的 foreach(i = 1:2) %dopar% { source("addition.R") }
与 registerDoSEQ()
当且仅当 从全局环境中调用的原因是 foreach 迭代在调用环境中求值,也就是全局环境,也就是source()
使用的环境。但是,如果使用 local(foreach(i = 1:2) %dopar% { ... })
也会失败,类似于上面的 local(for(i in 1:2) { ... })
调用。
结论:没有什么神奇的事情发生,但是理解它有点乏味。
我最终通过将源代码("addition.R") 转换为一个函数并将变量传递给它来解决了这个问题。我不知道为什么,但基于 source(file, local = TRUE)
的建议解决方案不起作用。
这是一个玩具示例来说明我的问题。
library(foreach)
library(doMC)
registerDoMC(cores=2)
foreach(i = 1:2) %dopar%{
i + 2
}
[[1]]
[1] 3
[[2]]
[1] 4
目前一切顺利...
但是如果代码 i + 2
保存在文件 addition.R
中并且我使用 source()
调用该文件,那么
> foreach(i = 1:2) %dopar%{
+ source("addition.R")
+ }
Error in { : task 1 failed - "object 'i' not found"
我无法完全复制你的玩具,但我有一个类似的问题,我可以通过以下方式解决:
source(file, local = TRUE)
应该在本地环境下解析源,即识别i.
NiceE 的评论和 Sosel 的回答已经解决了这个问题;当调用 source(file)
时,它默认为 source(file, local = FALSE)
,这意味着源文件中的代码正在全局环境("user's workspace")中进行评估,并且有,cf。 ?source
。注意全局环境中没有变量i
。解决方案是确保文件来源于调用它的环境,即使用 source(file, local = TRUE)
.
解决方案:
library("foreach")
y <- foreach(i = 1:2) %dopar% {
i + 2
}
str(y)
doMC::registerDoMC(cores = 2L)
y <- foreach(i = 1:2) %dopar% {
source("addition.R", local = TRUE)
}
str(y)
使用 for()
循环的相同问题示例:
source()
是在不同于 i
所在的调用环境的全局环境中求值的事实也可以通过 运行 for 使用常规的 for 循环来说明在不同于全局的另一个环境中循环,例如在函数内部或通过:
local({
for(i in 1:2) {
source("addition.R")
}
})
给出:
Error in eval(ei, envir) : object 'i' not found
现在,上面的 foreach(i = 1:2) %dopar% { source("addition.R") }
与 registerDoSEQ()
当且仅当 从全局环境中调用的原因是 foreach 迭代在调用环境中求值,也就是全局环境,也就是source()
使用的环境。但是,如果使用 local(foreach(i = 1:2) %dopar% { ... })
也会失败,类似于上面的 local(for(i in 1:2) { ... })
调用。
结论:没有什么神奇的事情发生,但是理解它有点乏味。
我最终通过将源代码("addition.R") 转换为一个函数并将变量传递给它来解决了这个问题。我不知道为什么,但基于 source(file, local = TRUE)
的建议解决方案不起作用。