r - 使用并行函数时的环境和范围

标签 r function parallel-processing scope

我有以下功能:

f1<-function(x){
  iih_data<-...stuff...
  ...more stuff...

  cl <- makeCluster(mc <- getOption("cl.cores", 6))
  clusterExport(cl, c("iih_data"))
  clusterEvalQ(cl, require(lme4))

  Tstar<-parCapply(cl, ystar, function(x){
     ostar=glmer(x ~ GENO + RACE + (1|GROUP), family="binomial",data=iih_data,nAGQ=1)
     fixef(ostar)[2]/sqrt(vcov(ostar)[2,2])
  })

  stopCluster(cl)

  ...more stuff...
}

但是我得到这个错误:
Error in get(name, envir = envir) : object 'iih_data' not found

我猜想这与我试图在函数内部并行运行apply有关。你们能帮我解决这个问题吗?谢谢

最佳答案

如您所知,clusterExport会在.GlobalEnv中查找指定的变量,除非另行指定envir参数。但是在您的特定示例中,iih_data与正在使用parCapply执行的未命名函数一起进行了序列化,因此实际上不会使用通过clusterExport导出给工作人员的副本。实际上,在执行f1之前在parCapply中定义的所有局部变量都将与未命名的worker函数一起序列化并发送给每个worker。

该技术对于将数据发送给工作人员非常有用(它实际上由clusterExport本身使用),但是您必须知道自己在做什么,否则会严重影响性能,尤其是在使用clusterApplyclusterApplyLB时,因为它们没有不会执行parLapplyparCapply进行的相同的预定。

这是一个简单的示例,说明了这一点:

library(parallel)
cl <- makePSOCKcluster(3)
f1 <- function() {
  iih_data <- 'foo'
  parLapply(cl, 1:3, function(i) iih_data)
}
f1()

您可能会因为未显式导出对象而出现错误,提示“找不到对象'iih_data'”,但您没有这样做。奇怪的是,从全局环境定义函数时不会发生这种情况,因为全局环境永远不会与函数一起序列化。

如果您认为这很奇怪,那么在处理参数时事情就会变得很陌生。考虑以下示例:
library(parallel)
cl <- makePSOCKcluster(3)
f1 <- function(iih_data) {
  parLapply(cl, 1:3, function(i) iih_data)
}
x <- 'foo'
f1(x)

在我之前的示例中,您可能会认为这可行,但是却收到以下错误:
Error in checkForRemoteErrors(val) : 
  3 nodes produced errors; first error: object 'x' not found

但是为什么它说“找不到对象'x'”而不是“找不到对象'iih_data'”?这是由于R对函数参数的懒惰求值。该函数及其关联的环境被序列化并发送给工作程序,而无需评估参数“iih_data”。在对 worker 执行未命名的 worker 函数之前,不会进行评估,这是因为它发现在 worker 的全局环境中未定义“x”。

您可以通过将f1更改为以下内容来解决此问题:
f1 <- function(iih_data) {
  force(iih_data)
  parLapply(cl, 1:3, function(i) iih_data)
}

如果您执行force而不是调用clusterExport(cl, 'iih_data', envir=environment()),它将起作用,但不是因为您已将其导出到工作程序。之所以可行,是因为该论点已被强制执行,但效率低得多,并且复制到 worker 全局环境中的值(value)观仍将不被使用。辅助函数实际上仍将使用本地环境中“iih_data”的副本,该副本是通过调用与未命名的辅助函数一起序列化的f1创建的。

这似乎是一个学术问题,但是一旦您开始从内部函数调用并行函数(例如parLapplyclusterApply)以执行未命名的工作程序函数,它就会以各种形式出现。我被这种问题困扰了很多次。

关于r - 使用并行函数时的环境和范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18035711/

相关文章:

database - oracle多用户功能

javascript - 如何重命名javascript预定义函数

.net - 默认情况下,F# 是否在内部使代码并行运行?

c# - 在 parallel.foreach 范围之外递增计数值

r - 是否可以创建一个在 R 中的列名称中包含空格的数据框?

r - R中的多项式特征扩展

c++ - 使函数参数成为具有多个参数的函数的错误

c# - 增加 Parallel.For 中运行的线程数

将数组提升到不同的幂

r - mutate_if 的正确语法