简体   繁体   English

为什么R for循环比使用foreach慢10倍?

[英]Why is R for loop 10 times slower than when using foreach?

This is really blowing my mind. 这真让我大吃一惊。 The basic loop takes like 8 seconds on my computer: 基本循环在我的计算机上花了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

Whereas if I use foreach in non-parallel mode, it does take only 0.7 secs!!! 然而,如果我在非并行模式下使用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

The result is the same, but foreach was somehow able to reach it much faster than basic R! 结果是一样的,但是foreach能以某种方式比基本的R更快地达到它! Where is the inefficiency of basic R? 基本R的低效率在哪里?

How is this possible? 这怎么可能?

In fact, I got complete opposite result compared to this one: Why is foreach() %do% sometimes slower than for? 事实上,与此相比,我获得了完全相反的结果: 为什么foreach()%do%有时慢于?

foreach when used sequentially eventually uses compiler to produce compiled byte code using the non-exported functions make.codeBuf and cmp . foreach在顺序使用时最终使用compiler使用非导出函数make.codeBufcmp生成编译的字节代码。 You can use cmpfun to compile the innerloop into bytecode to simulate this and achieve a similar speedup. 您可以使用cmpfuncmpfun编译为字节码来模拟这个并实现类似的加速。

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))
}

Results 结果

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

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

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