【问题标题】:Why is R for loop 10 times slower than when using foreach?为什么 R for 循环比使用 foreach 慢 10 倍?
【发布时间】:2014-07-09 10:49:12
【问题描述】:

这真的让我大吃一惊。在我的计算机上,基本循环大约需要 8 秒:

system.time({
x <- 0
for (p in 1:2) {
    for (i in 1:500) {
        for (j in 1:5000) {
            x <- x + i * j
        }
    }
}
})
x

而如果我在非并行模式下使用foreach,它确实只需要 0.7 秒!!!

system.time({
x <- 0
foreach(p = 1:2, .combine = rbind) %do% 
    for (i in 1:500) {
        for (j in 1:5000) {
            x <- x + i * j
        }
    }
})
x

结果是一样的,但是foreach 以某种方式能够比基本 R 更快地达到它!基础R的低效率在哪里?

这怎么可能?

事实上,我得到了与这个完全相反的结果:Why is foreach() %do% sometimes slower than for?

【问题讨论】:

  • 这是一个完美的例子,说明如何编写包可以改进/增强基本方法。
  • @Richard 太好了,如果你明白为什么会发生什么,请发表答案。
  • 代码被编译,最终由make.codeBuf
  • @James,是的,听起来像!
  • 所以如果你把你的三重循环,把它变成一个函数,并使用compile::cmpfun,结果函数会和foreach一样快吗?

标签: r foreach parallel-foreach


【解决方案1】:

foreach 在顺序使用时最终使用compiler 使用非导出函数make.codeBufcmp 生成编译字节码。您可以使用cmpfun 将内部循环编译为字节码来模拟这一点并实现类似的加速。

f.original <- function() {
x <- 0
for (p in 1:2) {
    for (i in 1:500) {
        for (j in 1:5000) {
            x <- x + i * j
        }
    }
}
x
}

f.foreach <- function() {
x <- 0
foreach(p = 1:2, .combine = rbind) %do% 
    for (i in 1:500) {
        for (j in 1:5000) {
            x <- x + i * j
        }
    }
x
}

f.cmpfun <- function(x) {
f <- cmpfun(function(x) {
    for (i in 1:500) {
        for (j in 1:5000) {
            x <- x + i * j
            }
        }
        x
    })
    f(f(0))
}

结果

library(microbenchmark)
microbenchmark(f.original(),f.foreach(),f.cmpfun(), times=5)
Unit: milliseconds
         expr       min        lq    median        uq       max neval
 f.original() 4033.6114 4051.5422 4061.7211 4072.6700 4079.0338     5
  f.foreach()  426.0977  429.6853  434.0246  437.0178  447.9809     5
   f.cmpfun()  418.2016  427.9036  441.7873  444.1142  444.4260     5
all.equal(f.original(),f.foreach(),f.cmpfun())
[1] TRUE

【讨论】:

    猜你喜欢
    • 2013-06-19
    • 2014-01-21
    • 1970-01-01
    • 2019-12-08
    • 1970-01-01
    • 2017-11-09
    • 1970-01-01
    • 2011-07-28
    • 2019-06-26
    相关资源
    最近更新 更多