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

Posted

技术标签:

【中文标题】R:foreach 循环如何找到应该调用的函数?【英文标题】:R: how does a foreach loop find a function that should be invoked? 【发布时间】:2013-06-25 01:54:50 【问题描述】:

我在使用调用自定义函数的 foreach 循环(使用 %dopar%)时遇到问题。使用Linux时确实没有问题,但是使用Windows时却找不到自定义函数。这个问题很难用语言来解释,所以我写了一个小例子来展示它。假设我有一个包含三个简单函数的集合,其中FUN2(使用%do%)和FUN3(使用%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)

函数存储在名为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 

然后我在 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""

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

我的问题:尽管代码相同(除了 registerDoParallel 语法不同),为什么 Windows 的行为与 Linux 不同?当通过函数 FUN3 调用时,如何确保 Windows 确实 找到函数 FUN

【问题讨论】:

【参考方案1】:

在您的clusterExport 调用中,删除env=environment() 部分。你正在做的是告诉clusterExport 在一个全新的环境中寻找你的对象,所以它自然不会找到它们。

【讨论】:

【参考方案2】:

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

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

FUN3 <- function(a, b) 
  foreach(i=1:3, .export='FUN') %dopar% FUN(i, a, b)

此解决方案适用于 Linux 和 Windows,因为 .exportmclapply 后端忽略。

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

【讨论】:

+1 不错的答案。如果FUN 以前没有被采购怎么办? (即工作环境中不存在)?是否可以通过导出相应的 R 文件使其在 foreach 中可用? (例如,.export="path/to/FUN.R")。换句话说,.export 是否适用于除 R 对象之外的文件? @Steve Weston 的原因是,在我的情况下,每个工作人员都需要写入 .txt 文件,调用将文件作为输入的可执行文件,然后读回 .exe 的输出(这是另一个.txt 文件)。我想知道.export 是否可以将.exe 文件提供(复制)到每个工人的临时工作目录 @Antoine 不,您只能使用 foreach .export 参数指定一个或多个变量的名称。除此之外,我通常在使用 doParallel 时使用特定于后端的方法来初始化工作程序,例如 clusterExportclusterEvalQ

以上是关于R:foreach 循环如何找到应该调用的函数?的主要内容,如果未能解决你的问题,请参考以下文章

如何将自定义函数加载到 R 中的 foreach 循环中?

在 foreach 循环中找不到函数

在 R 中使用 foreach 循环读取 MATLAB .mat 文件时出现问题

在 R 中使用“foreach()”函数时如何创建进度条?

如何等待来自 forEach 循环的多个异步调用?

jsp页面中如何实现<c:forEach>循环一次就调用一次js函数?