在并行的foreach循环中使用source()

Mar*_*rco 15 foreach r

这是一个说明我的问题的玩具示例.

library(foreach)
library(doMC)
registerDoMC(cores=2)

foreach(i = 1:2) %dopar%{
  i + 2
}
[[1]]
[1] 3

[[2]]
[1] 4
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好...

但是如果代码i + 2保存在文件中addition.R并且我使用source()那时调用该文件

> foreach(i = 1:2) %dopar%{
+   source("addition.R")
+ }
Error in { : task 1 failed - "object 'i' not found"
Run Code Online (Sandbox Code Playgroud)

Sos*_*sel 11

我不能完全重现你的玩具,但我有一个熟悉的问题,我可以通过以下方式解决:

source(file, local = TRUE)
Run Code Online (Sandbox Code Playgroud)

它应解析本地环境中的源,即识别i.


Hen*_*ikB 6

尼斯的评论和索塞尔的回答已经解决了这个问题; 当调用source(file)它默认为source(file, local = FALSE),这意味着源文件中的代码正在全局环境("用户的工作区")中进行评估,并且参见 ?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)
Run Code Online (Sandbox Code Playgroud)

for()循环相同问题的示例:

source()在全局环境中评估的事实与调用环境不同,其中i生命也可以通过在除了全局之外的另一个环境中运行for循环来使用常规for循环来说明,例如在函数内部或通过:

local({
  for(i in 1:2) {
    source("addition.R")
  }
})
Run Code Online (Sandbox Code Playgroud)

这使:

Error in eval(ei, envir) : object 'i' not found
Run Code Online (Sandbox Code Playgroud)

现在,上面的原因是foreach(i = 1:2) %dopar% { source("addition.R") },registerDoSEQ() 当且仅当从全局环境调用时,是因为foreach迭代在调用环境中进行评估,调用环境是全局环境,即source()使用的环境.但是,如果使用它local(foreach(i = 1:2) %dopar% { ... })也会类似于上述local(for(i in 1:2) { ... })调用失败.

总之:没有什么魔法发生,但要理解它有点单调乏味.