r-statistics-fanの日記

統計好きの現場の臨床医の覚書のようなもの

Rcppを使う:その2

C言語による乱数生成
ここメルセンヌツイスターソースコードがあるので利用してみる。

あらかじめMT.hをincludeフォルダにおいておく必要がある。

以下のファイルをpi4.cppとして保存

#include <Rcpp.h>
#include <stdio.h>
#include <MT.h>
using namespace Rcpp;
// [[Rcpp::export]]
double pi4Cpp(){
long circle_in = 0;
init_genrand(10);
for (long i = 0; i < 100000000; ++i) {
double  l = pow(genrand_real3(),2) + pow(genrand_real3(),2);
if (l < 1.0){
      circle_in++;   
}
}
//return(circle_in);
return(4.0 * circle_in / 100000000);
}

そして、以下のRコードを実行する。

library(Rcpp)
library(rbenchmark)

sourceCpp("pi4.cpp")

cppFunction('double pi3Cpp(){
      long circle_in = 0;
      Rcpp::NumericVector x = runif(200000000);
      for (long i = 0; i < 100000000; ++i) {
            double  l = x[i]*x[i] + x[i+100000000]*x[i+100000000];
            if (l < 1.0){
                  circle_in++;   
            }
      }
      return(4.0 * circle_in / 100000000);
}')

f0 <- function(){
      n = 100000000
      x <- runif(n = n)
      y <- runif(n = n)
      print(4*sum(x^2 + y^2 <= 1)/n)
}

benchmark(f0(),pi3Cpp(),pi4Cpp(),replications = 1)
> benchmark(f0(),pi3Cpp(),pi4Cpp(),replications = 1)
[1] 3.141453
[1] 3.141787
      test replications elapsed relative user.self sys.self user.child sys.child
1     f0()            1   11.09    8.338     10.17     0.83         NA        NA
2 pi3Cpp()            1    2.87    2.158      2.59     0.26         NA        NA
3 pi4Cpp()            1    1.33    1.000      1.32     0.00         NA        NA
> 

11秒だったのが、Rcppを使用して毎ループでメルセンヌツイスター乱数を
呼び出しても、1.33秒まで短くなった。