我的程式跑得很慢!

撰寫高效 R 程式碼

Colin Gillespie

Jumping Rivers & Newcastle University

我的程式真的很慢嗎?

  • 1 秒?
  • 1 分鐘?
  • 1 小時?
撰寫高效 R 程式碼

我的程式真的很慢嗎?

撰寫高效 R 程式碼

效能評測(Benchmarking)

  1. 先把要評測的功能包成一個函式。
  2. 在不同情境下量測時間,例如資料集大小。
撰寫高效 R 程式碼

範例:數列產生

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

選項 1
1:n
選項 2
seq(1, n)
選項 3
seq(1, n, by = 1)
撰寫高效 R 程式碼

包成函式(Function wrapping)

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:大約是 user 加上 system,我們通常最在意這個數字。
撰寫高效 R 程式碼

把結果存起來

下列程式的問題在於:

system.time(colon(1e8))

我們沒有把結果存起來。需要重跑並儲存結果:

res <- colon(1e8)

<- 同時執行:

  • 參數傳遞
  • 物件指派
system.time(res <- colon(1e8))

= 只能執行其中「一種」:

  • 參數傳遞
  • 物件指派
# 會拋出錯誤
system.time(res = colon(1e8))
撰寫高效 R 程式碼

相對時間

Method Absolute time (secs) Relative time
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 程式碼

一起來練習吧!

撰寫高效 R 程式碼

Preparing Video For Download...