r - 循环内部与外部功能的速度差异

标签 r microbenchmark

this SO post在对各种解决方案进行基准测试时引发了讨论。考虑以下代码

# global environment is empty - new session just started
# set up
set.seed(20181231)
n <- sample(10^3:10^4,10^3)
for_loop <- function(n) {
  out <- integer(length(n))
  for(k in 1:length(out)) {
    if((k %% 2) == 0){
      out[k] <- 0L
      next
    }
    out[k] <- 1L
    next
  }
  out
}
# benchmarking
res <- microbenchmark::microbenchmark(
  for_loop = {
    out <- integer(length(n))
    for(k in 1:length(out)) {
      if((k %% 2) == 0){
        out[k] <- 0L
        next
      }
      out[k] <- 1L
      next
    }
    out
  },
  for_loop(n),
  times = 10^4
)

这是完全相同循环的基准测试结果,一个包含在函数中,另一个不包含

# Unit: microseconds
#        expr      min       lq      mean   median       uq      max neval cld
#    for_loop 3216.773 3615.360 4120.3772 3759.771 4261.377 34388.95 10000   b
# for_loop(n)  162.280  180.149  225.8061  190.724  211.875 26991.58 10000  a 
ggplot2::autoplot(res)

benchmarking2

可以看出,效率存在巨大差异。这背后的根本原因是什么?

需要明确的是,问题不在于上述代码解决的任务(可以更优雅地完成),而只是关于常规循环和包含在函数内的循环之间的效率差异。

最佳答案

解释是函数是“即时”编译的,而解释代码不是。有关说明,请参阅 ?compiler::enableJIT

如果你想演示差异,运行

compiler::enableJIT(0)

在您的任何代码之前(包括 for_loop 函数的创建)。这会为该 session 的其余部分禁用 JIT 编译。那么两组代码的时间将更加相似。

您必须在创建 for_loop 函数之前执行此操作,因为一旦它被 JIT 编译器编译,它将保持编译状态,无论是否启用 JIT。

关于r - 循环内部与外部功能的速度差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53974449/

相关文章:

java - 在应用程序服务器中运行微基准测试 [JMH]

java - 如何用 Java 编写正确的微基准测试?

r - 通过组变量计算多个数值变量的百分比

r - 查找异常值并计算出现次数

r - 在循环中将 data.frame 行绑定(bind)到另一个 data.frame 的有效方法?

c++ - 以前的代码似乎影响了以后函数调用的时间

r - 过滤 R data.frames 时更新因子水平

regex - 在长字符串中插入换行符

benchmarking - Netlogo 中的时间差异

memory - 是否可以根据 memtest 结果计算缓存延迟?