意外に速いRタソ compared to C++
ちょいとRcppをがっつり使ってみようと、その試行錯誤記録が続く予定。
速度検証のテストコードとして、ランダムウォークする系列データを生成するコードを書いた。
library(Rcpp) sourceCpp(code=' #include<vector> #include <functional> #include <numeric> #include <Rcpp.h> using namespace Rcpp; // [[Rcpp::export]] NumericVector randomWalk(int size) { RNGScope scope; NumericVector rand(Rcpp::rnorm(size)); NumericVector cum(Rcpp::rnorm(size)); std::partial_sum(rand.begin(), rand.end(), cum.begin(), std::plus<double>()); return cum; } ')
これをピュアにRで書くと
cumsum(rnorm(10^5))
とだけ書けばよい。ちなみに、この2つは同じ結果をちゃんと返す。
> set.seed(100) > randomWalk(10) [1] -0.5021924 -0.3706612 -0.4495783 0.4372065 0.5541778 0.8728079 0.2910172 1.0055499 0.1802905 [10] -0.1795716 > set.seed(100) > cumsum(rnorm(10)) [1] -0.5021924 -0.3706612 -0.4495783 0.4372065 0.5541778 0.8728079 0.2910172 1.0055499 0.1802905 [10] -0.1795716
計算速度の比較をすると・・・
#結果比較 > library(rbenchmark) > res <- benchmark(randomWalk(10^5), cumsum(rnorm(10^5)), order="relative") > res[,1:4] test replications elapsed relative 2 cumsum(rnorm(10^5)) 100 1.49 1.000 1 randomWalk(10^5) 100 2.63 1.765
あらら、Rの方が速いよと、1.77倍速いよと。これはRの例の方が、直にCで書かれた部分だけ呼んでるからだろうと推測。
もうちょいいらんメモリ消費を削って、Rcpp版を書きなおして速くすると・・・以下のような感じ。
library(Rcpp) sourceCpp(code=' #include<vector> #include <functional> #include <numeric> #include <Rcpp.h> using namespace Rcpp; // [[Rcpp::export]] NumericVector randomWalk(int size) { RNGScope scope; NumericVector rand(Rcpp::rnorm(size)); std::partial_sum(rand.begin(), rand.end(), rand.begin(), std::plus<double>()); return rand; } ')
で、結果を比べると10%程度Rcpp版の方が速いというレベルか。
> res <- benchmark(randomWalk(10^5), cumsum(rnorm(10^5)), order="relative") > res[,1:4] test replications elapsed relative 1 randomWalk(10^5) 100 1.32 1.000 2 cumsum(rnorm(10^5)) 100 1.49 1.129