在 foreach 循环中找不到函数
Posted
技术标签:
【中文标题】在 foreach 循环中找不到函数【英文标题】:could not find function inside foreach loop 【发布时间】:2011-06-13 12:13:33 【问题描述】:我正在尝试使用 foreach 在 R 中进行多核计算。
A <-function(....)
foreach(i=1:10) %dopar%
B()
然后我在控制台中调用函数A
。问题是我在B
内调用了一个函数Posdef
,该函数在我提供的另一个脚本文件中定义。我不得不将Posdef
放在foreach
的导出参数列表中:.export=c("Posdef")
。但是我收到以下错误:
Error in : task 3 failed - "could not find function "Posdef""
为什么 R 找不到这个定义的函数?
【问题讨论】:
我建议搜索有关使用 R 进行动态作用域的信息。这根本不直观,您会发现很多关于 SO 的问题详细说明了人们在函数中定义函数时遇到的问题。 我们希望有一个可重现的例子。另外,您是否尝试过降雪进行多核处理?我发现它更直观,更容易适应(修改应用功能)。 同样的问题,暂时没有找到简单的答案。我设法通过调用 4 个核心 foreach(j=1:N、.combine=rbind、.packages=c(调用所有功能所需的包向量))%dopar% fun(j) 使其工作。它提高了速度,但不会除以 4(仅除以 2)我不确定我做了什么,所以不要复制这个.. 我通过导出每个有问题的函数来解决我的问题,这里建议使用clusterExport(cl, 'myMean')
***.com/questions/17879766/…
【参考方案1】:
为了好奇,我可以重现这个:
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()
我已经能够通过将函数放在另一个文件中并将该文件加载到 foreach 的主体中来解决这个问题。显然,您也可以将函数定义移动到 foreach 本身的主体中。
[编辑——我之前曾建议 .export 可能无法与函数名称一起正常工作,但在下面得到了更正。]
【讨论】:
".export" 可以采用函数名称。然而,这是一个有趣的例子,因为我认为问题是当fib
对其自身进行递归调用时会发生错误,因为fib
不在它自己的范围内,正如我在回答中解释的那样。
你的意思是如果我们将自定义函数包装在 R 包中它可以工作?【参考方案2】:
简短的回答是,这是doSNOW
、doParallel
和doMPI
等并行后端中的一个错误,但它已被修复。
略长一点的答案是foreach
使用特殊的“导出”环境而不是全局环境向工作人员导出函数。这曾经会导致在全局环境中创建的函数出现问题,因为“导出”环境不在它们的范围内,即使它们现在是在同一个“导出”环境中定义的。因此,他们看不到“导出”环境中定义的任何其他函数或变量,例如您的案例中的“Posdef”。
doSNOW
、doParallel
和 doMPI
后端现在将关联环境从全局更改为通过“.export”导出的函数的“导出”环境,似乎已经解决了这些问题。
【讨论】:
我认为这个问题已经解决了,但我仍然遇到与foreach v 1.4.4
、doMPI v 0.2.2
、doParallel v 1.0.14
、doSNOW v 1.0.16
包相同的问题,在 R v 3.5.0
和 @987654333 上运行@【参考方案3】:
foreach %dopar% 问题的快速解决方法是重新安装这些软件包:
install.packages("doSNOW")
install.packages("doParallel")
install.packages("doMPI")
它在我的情况下有效。
【讨论】:
以上是关于在 foreach 循环中找不到函数的主要内容,如果未能解决你的问题,请参考以下文章
在我的循环中找不到ArrayIndexOutOfBoundsException:5