在 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】:

简短的回答是,这是doSNOWdoParalleldoMPI 等并行后端中的一个错误,但它已被修复。

略长一点的答案是foreach 使用特殊的“导出”环境而不是全局环境向工作人员导出函数。这曾经会导致在全局环境中创建的函数出现问题,因为“导出”环境不在它们的范围内,即使它们现在是在同一个“导出”环境中定义的。因此,他们看不到“导出”环境中定义的任何其他函数或变量,例如您的案例中的“Posdef”。

doSNOWdoParalleldoMPI 后端现在将关联环境从全局更改为通过“.export”导出的函数的“导出”环境,似乎已经解决了这些问题。

【讨论】:

我认为这个问题已经解决了,但我仍然遇到与 foreach v 1.4.4doMPI v 0.2.2doParallel v 1.0.14doSNOW 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

在我的 for 循环中找不到逻辑错误

为什么在for循环的第二次迭代中找不到XPATH

C++ 在命名空间中找不到函数

在 Robot Framework 中找不到 IN 关键字。如何在不使用 IN 关键字的情况下使用 for 循环?

在运行时配置中找不到env:13