在foreach循环中找不到函数

sta*_*ing 19 parallel-processing foreach multicore r scoping

我正在尝试使用foreach在R中进行多核计算.

A <-function(....) {
    foreach(i=1:10) %dopar% {
    B()
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我A在控制台中调用函数.问题是我调用一个函数PosdefB只在其它脚本文件我源中定义.我不得不把Posdef输出参数列表放在foreach:.export=c("Posdef").但是我收到以下错误:

Error in { : task 3 failed - "could not find function "Posdef""
Run Code Online (Sandbox Code Playgroud)

为什么不能找到这个定义的函数?

Pau*_*und 14

所以我可以重现这一点,因为好奇:

require(doSNOW)
registerDoSNOW(makeCluster(5, type="SOCK"))
getDoParWorkers()
getDoParName()
getDoParVersion()

fib <- function(n) {
  if (n <= 1) { return(1) }
  return(fib(n-1) + fib(n-2))
}

my.matrix <- matrix(runif(2500, 10, 50), nrow=50)

calcLotsaFibs <- function() {
  result <- foreach(row.num=1:nrow(my.matrix), .export=c("fib", "my.matrix")) %dopar% {
    return(Vectorize(fib)(my.matrix[row.num,]))
  }
  return(result)
}

lotsa.fibs <- calcLotsaFibs()
Run Code Online (Sandbox Code Playgroud)

我已经能够通过将该函数放在另一个文件中并将该文件加载到foreach的主体中来解决这个问题.您显然也可以将函数定义移动到foreach本身的主体中.

[编辑 - 我之前曾建议.export可能无法正常使用函数名称,但在下面进行了更正.]

  • “.export”可以采用函数名称。然而,这是一个有趣的例子,因为我相信问题是当 `fib` 对自身进行递归调用时会发生错误,因为 `fib` 不在它自己的范围内,正如我在我的回答中所解释的那样。 (2认同)

Ste*_*ton 10

简短的回答是,这是并行后端中的一个错误,例如doSNOW,doParalleldoMPI,但它已被修复.

稍微长一点的答案是,foreach出口功能使用特殊的"出口"环境,而不是全球环境.这通常会导致在全局环境中创建的函数出现问题,因为"导出"环境不在其范围内,即使它们现在已在同一"导出"环境中定义.因此,他们无法看到"导出"环境中定义的任何其他函数或变量,例如您的案例中的"Posdef".

doSNOW,doParalleldoMPI后端现在从全球相关的环境切换到"出口"环境,通过".EXPORT"导出的函数,并且似乎已经解决了这些问题.

  • 我以为这个问题已经解决了,但是我仍然遇到以下问题:包foreach v 1.4.4,doMPI v 0.2.2,doParallel v 1.0.14,doSNOW v 1.0.16,在带有RStudio v 1.1.453的R v 3.5.0上运行 (2认同)