R:获取给定函数内所有变量和函数的列表和环境(用于并行处理)

时间:2017-11-09 08:55:30

标签: r parallel-processing parallel.foreach

我使用foreach进行并行处理,这需要通过列表手动将函数传递到已寻址内核的环境。我希望自动执行此过程并涵盖所有用例。易于使用仅包含变量的简单函数。然而,一旦要并行处理的函数使用在另一个环境中定义的参数和变量,就会出现并发症。考虑以下情况:

global.variable <- 3

global.function <-function(j){
  res <- j^2
  return(res)
}

compute.in.parallel <-function(i){
  res <- global.function(i+global.variable)
  return(res)
}

pop <- seq(10)

do <- function(pop,fun){
  require(doParallel)
  require(foreach)
  cl <- makeCluster(16)
  registerDoParallel(cl)
  clusterExport(cl,list("global.variable","global.function"),envir=globalenv())
  results <- foreach(i=pop) %dopar% fun(i)
  stopCluster(cl)
  return(results)
}

do(pop,compute.in.parallel)

这是有效的,因为我手动将global.variable和global.function传递给核心(请注意,compute.in.parallel本身在范围内自动考虑): clusterExport(cl,list("global.variable","global.function"),envir=globalenv())

但我想自动完成 - 要求在compute.in.parallel内构建一个所有变量和函数的字符串(但未定义/传递/包含)。我该怎么做?

我目前的解决方法是将所有可用变量转储到核心:

clusterExport(cl,as.list(unique(c(ls(.GlobalEnv),ls(environment())))),envir=environment())

然而,这并不令人满意 - 我没有考虑包命名空间和其他隐藏环境中的变量,也没有考虑将太多变量传递给核心,从而在每次并行运行时都会产生很大的开销。

有任何建议的改进吗?

2 个答案:

答案 0 :(得分:2)

只需传递do()中所需的所有参数,而不是使用全局变量。

compute.in.parallel <- function(i, global.variable, global.function) {
  global.function(i + global.variable)
}

do <- function(pop, fun, ncores = parallel::detectCores() - 1, ...) {
  require(foreach)
  cl <- parallel::makeCluster(ncores)
  on.exit(parallel::stopCluster(cl), add = TRUE)
  doParallel::registerDoParallel(cl)
  foreach(i = pop) %dopar% fun(i, ...)
}

do(seq(10), compute.in.parallel, 
   global.variable = 3, 
   global.function = function(j) j^2)

答案 1 :(得分:1)

future框架默认自动识别并导出全局变量。 doFuture包为foreach提供了一个通用的未来后端适配器。如果您使用它,以下工作:

do <- function(pop, fun) {
  library("doFuture")
  registerDoFuture()
  cl <- parallel::makeCluster(2)
  old_plan <- plan(cluster, workers = cl)
  on.exit({
    plan(old_plan)
    parallel::stopCluster(cl)
  })

  foreach(i = pop) %dopar% fun(i)
}