1 min read

itertools的效能

看到許多版友在問itertools的效能,讓我想跟大家分享一些關於程式效能的經驗。

一般來說,我們不會去優化所有的程式碼,因為優化有很大的代價:一般性可讀性。 通常跑得快與寫的快,是要做取捨的。 這裡的例子很好想像,大家只要比較R的程式碼與Rcpp的程式碼就好了。

又由於程式的效能通常也符合80-20法則: 80%的時間是花在20%的程式碼 所以實務上,我不會從頭到尾都把程式用Rcpp來寫, 而是只抽出最花時間的那段程式碼,改成Rcpp。

以一個for loop來說:

library(microbenchmark)
library(itertools)
## Loading required package: iterators
f1 <- function() {
  lapply(1:100, function(i) {
    lapply(1:100, function(j) {
    })
  })
  NULL
}
f2 <- function() {
  lapply(product(i = 1:100, j = 1:100), function(x) { })
  NULL
}
microbenchmark(f1(), f2(), times = 10)
## Unit: milliseconds
##  expr        min         lq       mean     median         uq        max
##  f1()   4.657429   5.329925   6.092346   5.896559   6.685231   8.482395
##  f2() 466.092096 485.819743 504.164424 500.838942 522.266778 538.185611
##  neval
##     10
##     10

在我的電腦上,差不多是5 vs 500 milliseconds 的差異,也就是100倍。 看起來很多,可是在實務上呢?

如果每跑一次迴圈內的程式碼花1 milli seconds做計算,那整體的時間差異也是: 10000 + 5 v.s. 10000 + 500, 而在10000面前,你不太會注意到那100倍的差距。

就我自己用itertools的經驗時,通常是在寫一些不是效能很重要的程式碼。ps. 效能重要的程式碼我會用C++寫。 有時候,當寫一個只會跑若干次的程式時,為了省那不到一秒的時間,而去寫更難寫更複雜的程式碼,反而花更多時間,並且得不償失阿。 所以我在看到一些R友問效能的時候,心裡其實是感到滿訝異的: 大家是不是走火入魔了? 並不是只有跑得快才有價值,有的時候能把程式碼弄的更簡單,也是很有價值的。而這個套件的價值,偏向後者。