在R doParallel 'foreach'中找不到函数 - 任务1失败 -“无法找到函数'raster'”

59

我第一次尝试在我的机构使用高性能集群,遇到了一个无法解决的问题。

以下代码返回了一个错误:

ptime<-system.time({
  r <- foreach(z = 1:length(files),.combine=cbind) %dopar% {
    raster <- raster(paste(folder,files[1],sep=""))
    data<-getValues(raster)
    clp <- na.omit(data)
    for(i in 1:length(classes)){
      results[i,z]<-length(clp[clp==classes[i]])/length(clp)
      print(z)
    }
  }
})

Error in { : task 1 failed - "could not find function "raster""

A也尝试了不同的foreach代码来完成我另一个任务:

r <- foreach (i=1:length(poly)) %dopar% {
  clip<-gIntersection(paths,poly[i,])
  lgth<-gLength(clip)
  vid<-poly@data[i,3]
  path.lgth[i,] <- c(vid,lgth)
  print(i)
}

这一次找不到 gIntersection 函数。显然,所有的包都已经安装和加载了。读了一些论坛帖子后,似乎与函数执行/操作的环境有关。

有人可以帮忙吗?我不是程序员!

谢谢!

更新:

我已经根据提供的解决方案调整了我的代码:

results<-matrix(nrow=length(classes),ncol=length(files))
dimnames(results)[[1]]<-classes
dimnames(results)[[2]]<-files

ptime<-system.time({
    foreach(z = 1:length(files),.packages="raster") %dopar% {
    raster <- raster(paste(folder,files[z],sep=""))
    data<-getValues(raster)
    clp <- na.omit(data)
    for(i in 1:length(classes)){
      results[i,z]<-length(clp[clp==classes[i]])/length(clp)
      print(z)
    }
  }
})

但是我得到的输出结果(我的结果矩阵)全部都是na。正如您所看到的,我创建了一个名为results的矩阵对象来存储结果(使用for循环工作),但是在阅读foreach的文档后,似乎您需要使用该函数以不同的方式保存结果。

有什么建议可以为.combine参数选择什么?


13
尝试使用foreach函数的.packages参数,这些包不会在工作进程中被加载。 - Roland
1
请查看http://cran.r-project.org/web/packages/foreach/vignettes/foreach.pdf的第8页和第9页,或者使用`?foreach`命令。这里可以找到Roland评论中提供的信息。 - Joris Meys
非常感谢您的帮助!这个问题已经解决了,但现在我有一个新问题。我将编辑我的原始问题。 - Karen
4
请勿更改您的问题以提出新问题,这会让未来的访问者感到困惑。如果您有新的问题,请提出一个新问题。显然,这是一个新的问题。请参阅 http://stackoverflow.com/tour 和 http://stackoverflow.com/help/asking 了解该网站的运作方式。 - Joris Meys
我只是尝试在之前的回答者已经了解的关于我的代码的知识基础上继续构建。 - Karen
cran.r-project.org/web/packages/foreach/vignettes/foreach.pdf 是一个失效的链接。新链接为 cran.r-project.org/web/packages/foreach/vignettes/foreach.html。 - Timothy M Pollington
3个回答

84
foreach 的使用说明文档 和 foreach 的帮助页面中,强调了在使用默认未加载函数的并行计算时,需要提供 .packages 参数。因此,第一个示例中的代码应该是:
ptime<-system.time({
  r <- foreach(z = 1:length(files),
               .combine=cbind, 
               .packages='raster') %dopar% {
      # some code
      # and more code
  }
})

更多解释

foreach包在后台进行了大量设置。原理是这样的(技术细节稍微有点复杂):

  • foreach建立了一种“工人”系统,你可以将其视为分布式计算集群中每个核心上运行的独立R会话。

  • 需要执行的函数以及执行该函数所需的对象被加载到每个“工人”会话中。

  • 每个工人会话计算数据子集的结果。

  • 不同工人计算的结果被汇总并在“主”R会话中报告。

由于工人可以看作是独立的R会话,因此无法自动加载来自“主”会话的软件包。您必须指定应在这些工人会话中加载哪些软件包,并且这就是foreach.package参数的用途。


请注意,当您使用其他软件包时(例如parallelsnowfall),您必须显式地设置这些工人,并确保在工人会话中传递对象和加载软件包。


3
所有依赖项都必须加载。 - Giorgio Spedicato

4
我有同样的问题。我的解决方案是:
  1. 将您的函数准备在一个单独的R文件中。

Function.R

f <- function(parameters...){Body...}
  1. 在foreach循环中调用您的函数

MainFile.R

library(foreach)
library(doParallel)
cores=detectCores()
cl <- makeCluster(cores[1]-2) #not to overload your computer
registerDoParallel(cl)

clusterEvalQ(cl, .libPaths("C:/R/win-library/4.0")) #Give your R library path
output <- foreach(i=1:5, .combine = rbind) %dopar% {
source("~/Function.R") # That is the main point. Source your Function File here.
temp <- f(parameters...) # use your custom function after sourcing 
temp
}

stopCluster(cl)

3
我遇到了使用foreach时出现"找不到函数"的错误。通常,这个问题与包中的函数对foreach工作者不可用有关。但我的使用情况是,在与foreach相同的脚本中定义了非包/自定义/孤立(?)/未导出(?)函数。为了解决这个问题,而不是创建一个新的包并导出函数,可以使用一种简单的方法。以下是具体情况:
一个脚本包含:
funA(){
    ...
}

funB(){
    ...
}

funC(){     
    foreach(){
        funA(); funB()
    }
}

funC()

在调用funC函数之前,定义了两个函数funAfunB。看起来这前两个函数并不被认为是在全局环境下funC,即使它们在同一个脚本中,因此会出现错误。简单的解决方法是将funAfunB剪切并粘贴到funC的定义顶部,如下所示:

funC(){
    funA(){
        ...
    }
    funB(){
        ...
    }       
    foreach(){}
}

funC()

在这个线程中,您可以找到关于这种情况发生的解释和一个干净的解决方案:https://dev59.com/Qmw15IYBdhLWcg3wVKF1#15638393 - Wassermann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接