- こちらにフィボナッチ数列の発生を再帰関数で作る実験をしている
- 再帰関数がどのような「遅さ」をもたらすかの実験なので、関数自体はシンプル
- Rでべたに書くと
fibR <- function(seq) {
if (seq == 0) return(0);
if (seq == 1) return(1);
return (fibR(seq - 1) + fibR(seq - 2));
}
-
- 再帰しているから、べたに、値を「格納しながら進む」ことになる。ソースは簡単だけれど、処理はまだるっこしい
- Rcppを使うと
library(Rcpp)
library(inline)
incltxt <- '
int fibonacci(const int x) {
if (x == 0) return(0);
if (x == 1) return(1);
return (fibonacci(x - 1)) + fibonacci(x - 2);
}'
fibRcpp <- cxxfunction(signature(xs="int"),
plugin="Rcpp",
incl=incltxt,
body='
int x = Rcpp::as<int>(xs);
return Rcpp::wrap( fibonacci(x) );
')
- Rのコードをコンパイルするという仕組みもあって、それはcompilerパッケージがやるらしいのだが、それもやってみる
library(compiler)
fibRC <- cmpfun(fibR)
N <- 25
res <- benchmark(fibR(N),
fibRC(N),
fibRcpp(N),
columns=c("test", "replications", "elapsed",
"relative", "user.self", "sys.self"),
order="relative",
replications=1)
print(res)
- Rcppはほとんど時間がかからないのに、RとRのコンパイルだけの処理、では、時間がかかりますよ、と。(例にあるとおりに、N=35にしたりすると、すごい時間がかかってしまう)
> print(res)
test replications elapsed relative user.self sys.self
1 fibR(N) 1 9.88 NA 9.60 0.03
2 fibRC(N) 1 8.78 NA 8.61 0.00
3 fibRcpp(N) 1 0.00 NA 0.00 0.00
> print(res)
test replications elapsed relative user.self sys.self
1 fibR(N) 1 2.03 NA 2.03 0
2 fibRC(N) 1 2.04 NA 2.01 0
3 fibRcpp(N) 1 0.00 NA 0.00 0