R言語のdo.callとReduceの速度を比較する
概要
行列のリストをbindして、巨大な一つの行列にすることを考える。
Rjpwiki的には、do.callでbindするらしいが、実際のところ、do.callとReduceとdoMCのどれが一番速いのか気になったので、比較してみた。
実験条件
適当な100*100の行列を100個用意して、リストに格納する。
それをbindする時間で競う。
mat.list <- list(NULL) for(i in 1:100){ mat.list[[i]] <- matrix(runif(100*100),nrow=100,ncol=100) }
結果
bindに使う場合、Reduceは異様なほど遅い。
do.callとdoMCはタスクと環境次第。
ちなみにbind系なら、rbind.fill(plyrパッケージ)が最強らしい。
The rbinding race: for vs. do.call vs. rbind.fill | (R news & tutorials)
> system.time( tmp <- do.call(args=mat.list,what=cbind)) user system elapsed 0.005 0.006 0.012
> system.time( tmp <- Reduce(x=mat.list,f=cbind)) user system elapsed 0.242 0.253 0.495
library('doMC') registerDoMC(1) > system.time( tmp <- foreach(i = 1:100,.combine=cbind) %dopar% { mat.list[[i]] } ) user system elapsed 0.055 0.005 0.059
ただ、Reduce本来の使い方(演算)をするならReduceの方が速いらしい。
過去の配列を保持し続けるようなことが不向きらしい?
> system.time( tmp <- do.call(args=mat.list,what=sum)) user system elapsed 0.010 0.001 0.010 > system.time( tmp <- Reduce(x=mat.list,f=sum)) user system elapsed 0.001 0.000 0.002
-
- 追記
R help - What is the difference between Reduce(…) and do.call(…) ?
こういうことらしい。
Reduceはforの延長上にあって、do.callは関数を引数全体に一括でかける感じ。
まあ要するに、大体do.callで良いという話。