【问题标题】:foreach (foreach package) for parallel processing in Rforeach(foreach 包)用于 R 中的并行处理
【发布时间】:2015-09-28 22:59:09
【问题描述】:

我正在使用 for 循环计算置换检验统计量。我希望使用并行处理(特别是 foreach 包中的 foreach)来加快速度。我正在按照以下说明进行操作: https://beckmw.wordpress.com/2014/01/21/a-brief-foray-into-parallel-processing-with-r/

我的原始代码:

library(foreach)
library(doParallel)
set.seed(10)
x = rnorm(1000)
y = rnorm(1000)
n = length(x)
nexp = 10000
perm.stat1 = numeric(n)
ptm = proc.time()
for (i in 1:nexp){
  y = sample(y)
  perm.stat1[i] = cor(x,y,method = "pearson")
  }
proc.time()-ptm
# 1.321 seconds

但是,当我使用 foreach 循环时,我得到的结果要慢得多:

cl<-makeCluster(8)
registerDoParallel(cl)
perm.stat2 = numeric(n)
ptm = proc.time()
perm.stat2 = foreach(icount(nexp), .combine=c) %dopar% {
  y = sample(y)
  cor(x,y,method = "pearson")
}
proc.time()-ptm
stopCluster(cl)
#3.884 seconds

为什么会这样?我做错了什么? 谢谢

【问题讨论】:

    标签: r permutation parallel-processing


    【解决方案1】:

    您的性能很差,因为您将一个小问题分解为 10,000 个任务,每个任务大约需要 八分之一毫秒 来执行。当循环体需要很长一段时间(我以前说至少需要 10 秒,但现在我已经将其降至至少 1 秒)时,可以简单地将 for 循环转换为 foreach 循环),但是当任务非常小(在这种情况下,非常小)时,这种简单的策略不起作用。当任务较小时,您会花费大部分时间发送任务并从工作人员那里接收结果。换句话说,通信开销大于计算时间。坦率地说,我很惊讶你没有得到更差的表现。

    对我来说,并行化一个执行时间少于两秒的问题似乎并不值得,但您实际上可以通过 chunking 使用foreach 来加快速度。也就是说,您将问题分成更小的块,通常给每个工人一个块。这是一个例子:

    nw <- getDoParWorkers()
    perm.stat1 <-
      foreach(xnexp=idiv(nexp, chunks=nw), .combine=c) %dopar% {
        p = numeric(xnexp)
        for (i in 1:xnexp) {
          y = sample(y)
          p[i] = cor(x,y,method="pearson")
        }
        p
      }
    

    如您所见,foreach 循环将问题拆分为多个块,并且该循环的主体包含原始顺序代码的修改版本,现在处理整个问题的一小部分。

    在我的四核 Mac 笔记本电脑上,执行时间为 0.447 秒,而顺序版本为 1.245 秒。对我来说,这似乎是一个非常可观的速度。

    【讨论】:

      【解决方案2】:

      foreach 循环中有更多的计算开销。这将返回一个列表,其中包含循环主体的每次执行,然后通过 .combine=c 参数将其组合成一个向量。 for 循环不返回任何内容,而是将值分配给 perm.stat1 作为副作用,因此不需要任何额外开销。

      查看Why is foreach() %do% sometimes slower than for? 以更深入地解释为什么在许多情况下foreachfor 慢。 foreach 发挥作用的地方是循环内的操作是计算密集型的,相比之下,与返回列表中的每个值相关的时间损失微不足道。例如,上面 Wordpress 文章中使用的rnormsummary 的组合。

      【讨论】:

        猜你喜欢
        • 2016-10-08
        • 2016-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-21
        • 1970-01-01
        相关资源
        最近更新 更多