繁体   English   中英

foreach(foreach包),用于R中的并行处理

[英]foreach (foreach package) for parallel processing in R

我正在使用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

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

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

在我看来,并行执行不到两秒钟的问题似乎并不值得,但实际上您可以通过块化使用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秒。 在我看来,这是一个非常可观的速度。

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

看看为什么foreach()%do%有时会比for慢? 对于为什么一个更深入的解释foreach是慢for在许多情况下。 当循环内的操作需要大量计算时, foreach才能发挥作用,相比之下,与返回列表中的每个值相关的时间损失微不足道。 例如,上面的Wordpress文章中使用的rnormsummary的组合。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM