r-statistics-fanの日記

統計好き人間の覚書のようなもの

R3.4.0にアップデート。Rが高速に。

R3.4.0が出たと聞いた。
JITバイトコンパイラになり、loopが高速になるらしい。
適当にフィボナッチ数を計算する関数を作って試してみる。

fibonacci <- function(n){
      if(n == 1) 1
      else if(n == 2) 2
      else (fibonacci(n-2) + fibonacci(n-1))
}

fibonacci2 <- function(n){
f1 <- 1
f2 <- 2
f3 <- 1
if(n >= 3){
      for(i in 3:n){
      f3 <- f1 + f2
      f1 <- f2
      f2 <- f3
      }
      return(f3)
      }
return(n)
}

library(rbenchmark)
benchmark(fibonacci(20),fibonacci2(20), replications = 100)
benchmark(fibonacci2(200000), replications = 100)
#R3.3.0
> benchmark(fibonacci2(200000), replications = 100)
               test replications elapsed relative user.self sys.self user.child sys.child
1 fibonacci2(2e+05)          100   17.03        1     16.94        0         NA        NA

> benchmark(fibonacci(20),fibonacci2(20), replications = 100)
            test replications elapsed relative user.self sys.self user.child sys.child
1  fibonacci(20)          100    1.81       NA       1.8        0         NA        NA
2 fibonacci2(20)          100    0.00       NA       0.0        0         NA        NA
#R3.4.0
> benchmark(fibonacci2(200000), replications = 100)
               test replications elapsed relative user.self sys.self user.child sys.child
1 fibonacci2(2e+05)          100    2.25        1      2.18        0         NA        NA

> benchmark(fibonacci(20),fibonacci2(20), replications = 100)
            test replications elapsed relative user.self sys.self user.child sys.child
1  fibonacci(20)          100    0.81       NA       0.8        0         NA        NA
2 fibonacci2(20)          100    0.00       NA       0.0        0         NA        NA

fibonacciを見ると再帰関数も、2倍以上高速になっている。
fibonacci2をみると、for文での関数は7倍以上高速になっている。

単純に足し算でも比較

f.loop <- function(n){
      x <- 0
      for(i in seq_len(n)){
      x <- x + 1
      }
      return(x)
}

f.loop2 <- function(n){
      x <- rep(1, n)
      y <- 0
      for(i in seq_len(n)){
      y <- y + x[i]
      }
      return(y)
}


f.vec <- function(n){
      x <- rep(1, n)
      sum(x)
}

library(rbenchmark)
benchmark(f.vec(100000),f.loop(100000), f.loop2(100000), replications = 1000)
#R3.3.0
> benchmark(f.vec(100000),f.loop(100000), f.loop2(100000), replications = 1000)
            test replications elapsed relative user.self sys.self user.child sys.child
2  f.loop(1e+05)         1000   45.19   72.887     43.75     0.14         NA        NA
3 f.loop2(1e+05)         1000   67.94  109.581     65.74     0.25         NA        NA
1   f.vec(1e+05)         1000    0.62    1.000      0.42     0.19         NA        NA
#R.3.4.0
> benchmark(f.vec(100000),f.loop(100000), f.loop2(100000), replications = 1000)
            test replications elapsed relative user.self sys.self user.child sys.child
2  f.loop(1e+05)         1000    4.24    6.424      4.07     0.00         NA        NA
3 f.loop2(1e+05)         1000    6.69   10.136      6.26     0.17         NA        NA
1   f.vec(1e+05)         1000    0.66    1.000      0.42     0.22         NA        NA

loopは10倍程度高速ですね。

ここまで高速になると良いですねぇ。他言語との絶望的な差が縮まった感じ。。
アップデート後、実際今までのコードが動かなくなったりしているので面倒だけど
(パッケージのバージョンの問題もある)、今後のことを考えてR3.4系に移行するとしよう。