这真让我大吃一惊。我的电脑基本循环需要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的低效率在哪里?
这怎么可能?
事实上,与此相比,我得到了完全相反的结果: 为什么foreach()%do%有时慢于?
foreach
当顺序使用时最终使用 compiler
使用非导出函数生成编译的字节代码 make.codeBuf
和 cmp
。您可以使用 cmpfun
将innerloop编译成字节码来模拟这个并实现类似的加速。
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