关于foreach:如何在R中并行化包的函数

How to parallelize a function for a package in R

我想并行化我正在处理的程序包的一部分。 我应该使用哪些软件包和什么语法来使该软件包在不同的体系结构上灵活且可用? 我的问题出在单个sapply()调用中,如以下模拟代码所示:

1
2
3
4
5
6
7
8
9
10
11
.heavyStuff <- function(x) {
   # do a lot of work
   Sys.sleep(1)
}

listOfX <- 1:20

userFunc1 <- function(listOfX) {    
  res <- sapply(listOfX, .heavyStuff)
  return(res)
}

根据不同的指南,我炮制了以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
userFunc2 <- function(listOfX, dopar.arg=2) {
  if(requireNamespace("doParallel")) {
    doParallel::registerDoParallel(dopar.arg)
    res <- foreach(i=1:length(listOfX)) %dopar% {
       .heavyStuff(listOfX[[i]])
    }
    names(res) <- names(listOfX)
  } else {
    res <- sapply(listOfX, .heavyStuff)
  }
  return(res)
}

问题:

  • 我可以安全地在包装中使用这样的代码吗? 它在各种平台上都能很好地工作吗?
  • 有没有办法避免foreach()构造? 我更喜欢使用类似sapply或lapply的函数。 但是,并行库中的构造似乎更特定于平台。
  • 如果dopar.arg==NULL,则上面的代码不起作用,即使doParallel的介绍说没有任何参数,"您将得到3个工作并且在类Unix系统上
    您将获得的工作人员数量大约等于系统核心数量的一半。"

  • 作为Future Framework的作者,我建议您看看future.apply包,例如

    1
    2
    3
    4
    5
    library(future.apply)
    userFunc2 <- function(listOfX) {    
      res <- future_sapply(listOfX, .heavyStuff)
      return(res)
    }

    默认情况是事情按顺序运行,但是如果用户愿意,他们可以使用他们想要的任何并行将来的后端,例如

    1
    2
    3
    4
    5
    6
    7
    8
    library(future)
    plan(multiprocess)    # parallel on local machine - all cores by default

    library(future.batchtools)
    plan(batchtools_sge)  # parallel on an SGE compute cluster

    library(future)
    plan(sequential)      # sequentially

    设计模式是您决定要并行化什么,而用户如何并行化。