[英]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文章中使用的rnorm
和summary
的组合。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.