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,因为 .export
被 mclapply
后端忽略。
正如 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 时使用特定于后端的方法来初始化工作程序,例如 clusterExport
或 clusterEvalQ
。以上是关于R:foreach 循环如何找到应该调用的函数?的主要内容,如果未能解决你的问题,请参考以下文章