我的代码很慢?

高效 R 代码写作

Colin Gillespie

Jumping Rivers & Newcastle University

我的代码真的慢吗?

  • 1 秒?
  • 1 分钟?
  • 1 小时?
高效 R 代码写作

我的代码真的慢吗?

高效 R 代码写作

基准测试

  1. 针对要基准测试的功能封装一个函数
  2. 在不同情境下计时,如数据集
高效 R 代码写作

示例:数列

$$ 1, 2, 3, \ldots, n $$

选项 1
1:n
选项 2
seq(1, n)
选项 3
seq(1, n, by = 1)
高效 R 代码写作

函数封装

colon <- function(n) 1:n
colon(5)
1 2 3 4 5
seq_default <- function(n) seq(1, n)
seq_by <- function(n) seq(1, n, by = 1)
高效 R 代码写作

用 system.time() 计时

system.time(colon(1e8))
#   user  system elapsed
#  0.032   0.028   0.060
system.time(seq_default(1e8))
#   user  system elapsed
#  0.060   0.028   0.086
system.time(seq_by(1e8))
#   user  system elapsed
#  1.088   0.520   1.600
  • user 时间:执行用户指令占用的 CPU 时间。
    • system 时间:系统代表调用进程执行所占的 CPU 时间。
    • elapsed 时间:约为二者之和,是我们通常关注的数值。
高效 R 代码写作

存储结果

问题在于

system.time(colon(1e8))

没有存储结果。需要重跑并保存结果:

res <- colon(1e8)

<- 运算符可同时执行:

  • 参数传递
  • 对象赋值
system.time(res <- colon(1e8))

= 运算符只执行下列之一:

  • 参数传递
  • 对象赋值
# Raises an error
system.time(res = colon(1e8))
高效 R 代码写作

相对时间

Method 绝对时间(秒) 相对时间
colon(n) 0.060 $0.060/0.060 = 1.00$
seq_default(n) 0.086 $0.086/0.060 = 1.40$
seq_by(n) 1.607 $1.60/0.060 = 26.7$
高效 R 代码写作

microbenchmark 包

  • 比较函数性能
    • 每个函数多次运行
library("microbenchmark")

n <- 1e8 microbenchmark(colon(n), seq_default(n), seq_by(n), times = 10) # 每个函数运行 10 次
# Unit: milliseconds
#           expr  min   lq  mean  median   uq  max neval cld
#       colon(n)   59  130   220     202  341  391    10  a
# seq_default(n)   94  204   290     337  348  383    10  a
#      seq_by(n) 1945 2044  2260    2275 2359 2787    10   b
高效 R 代码写作

Vamos praticar!

高效 R 代码写作

Preparing Video For Download...