R:foreach循环如何找到应该调用的函数?

use*_*417 18 parallel-processing foreach r mpi

当我使用%dopar%调用自定义函数的foreach循环(使用)时,我遇到了问题.使用Linux时没有真正的问题,但是当我使用Windows时,无法找到自定义的功能.很难用文字解释这个问题,所以我写了一个小例子来展示它.假设我有三个简单函数的集合,其中FUN2(using %do%)和FUN3(using %dopar%)调用第一个函数(FUN):

FUN <- function(x,y,z) { x + y + z }
FUN2 <- function(a, b) {
  foreach(i=1:3) %do% FUN(i, a, b)
}
FUN3 <- function(a, b) {
  foreach(i=1:3) %dopar% FUN(i, a, b)
}
Run Code Online (Sandbox Code Playgroud)

这些函数存储在一个名为的脚本中foreach_testfunctions.R.在另一个脚本(foreach.test)中我发布了这些函数,使用library(doParallel)并尝试使用这些函数.首先我用Linux做,一切正常:

source("foreach_testfunctions.R")
a <- 2
b <- 3
library(doParallel)
registerDoParallel()

foreach(i=1:3) %do% FUN(i, a, b)    ## works fine
FUN2(a, b)                          ## works fine
foreach(i=1:3) %dopar% FUN(i, a, b) ## works fine
FUN3(a, b)                          ## works fine 
Run Code Online (Sandbox Code Playgroud)

然后我在Windows中执行此操作:

source("foreach_testfunctions.R")
a <- 2
b <- 3
library(doParallel)
cl <- makeCluster(3)
registerDoParallel(cl)

foreach(i=1:3) %do% FUN(i, a, b)    ## works fine
FUN2(a, b)                          ## works fine
foreach(i=1:3) %dopar% FUN(i, a, b) ## works fine
FUN3(a, b)                          ## does not work
Error in FUN(i, a, b) : task 1 failed - "Could not find function "FUN""
Run Code Online (Sandbox Code Playgroud)

结论:(1)没有问题%do%.(2)%dopar%使用Windows时出现问题.我尝试clusterExport(cl, varlist=c("FUN", "a", "b"), env=environment())在调用的行之前插入行,FUN3以确保FUN在适当的环境中找到函数和变量a和b,但错误仍然存​​在.

我的问题:为什么Windows的行为与Linux不同,尽管代码相同(除了不同的registerDoParallel语法)?我怎样才能确保Windows 确实发现功能FUN时,通过功能调用FUN3

Ste*_*ton 24

它们的行为不同,因为在Linux上registerDoParallel注册mclapply后端,而它clusterApplyLB在Windows上注册后端.使用mclapply后端时,基本上没有数据导出问题,因此它适用于Linux.但是clusterApplyLB,如果foreach不自动导出所需的功能和数据,则可能会遇到问题.

您可以通过选项修改FUN3为导出来解决此问题:FUN.export

FUN3 <- function(a, b) {
  foreach(i=1:3, .export='FUN') %dopar% FUN(i, a, b)
}
Run Code Online (Sandbox Code Playgroud)

此解决方案适用于Linux和Windows,因为后端.export会忽略此解决方案mclapply.

正如Hong Ooi所指出的,你在使用中有错误clusterExport,但我不会用它clusterExport来解决问题,因为它是特定于后端的.