「オリジナルのR」、「RcppArmadillo」、「RcppEigen」で処理速度の比較をしてみたいと思います。
「RcppArmadillo」、「RcppEigen」を使うのは、恐らく以下のような時だと思います。
Rcpp入門の関数を、1固定ではなく、行番号+列番号とした関数を作成して比較します。
※ バージョンによっては正常に動作しない場合があります。私が試した環境は、
PlusIJ_R <- function(src)
{
num_row <- nrow(src)
num_col <- ncol(src)
for(r in 1:num_row)
{
for(c in 1:num_col)
{
src[r, c] = src[r, c] + r + c
}
}
return(src)
}
# パッケージの読込み
library(Rcpp)
library(RcppArmadillo)
# パッケージのバージョンの確認
packageVersion("Rcpp")
packageVersion("RcppArmadillo")
# C+11にてコンパイルします
Sys.setenv("PKG_CXXFLAGS"="-std=c++11")
[1] '0.12.12'
[1] '0.7.960.1.2'
# C++のコード
code <- '
arma::mat PlusIJ_Arma(arma::mat src)
{
int num_row = src.n_rows;
int num_col = src.n_cols;
for(int r = 0; r < num_row; r++)
{
for(int c = 0; c < num_col; c++)
{
src(r, c) = src(r, c) + r + 1 + c + 1;
}
}
return src;
}
'
# コンパイルとリンクを行います(少し時間がかかります)
cppPlusIJ_Arma <- cppFunction(code, depends="RcppArmadillo")
# パッケージの読込み
library(Rcpp)
library(RcppEigen)
# パッケージのバージョンの確認
packageVersion("Rcpp")
packageVersion("RcppEigen")
# C+11にてコンパイルします
Sys.setenv("PKG_CXXFLAGS"="-std=c++11")
Attaching package: 'RcppEigen' The following objects are masked from 'package:RcppArmadillo': fastLm, fastLmPure
[1] '0.12.12'
[1] '0.3.3.3.0'
# C++のコード
code <- '
Eigen::MatrixXd PlusIJ_Eigen(Eigen::MatrixXd src)
{
int num_row = src.rows();
int num_col = src.cols();
for(int r = 0; r < num_row; r++)
{
for(int c = 0; c < num_col; c++)
{
src(r, c) = src(r, c) + r + 1 + c + 1;
}
}
return src;
}
'
# コンパイルとリンクを行います(少し時間がかかります)
cppPlusIJ_Eigen <- cppFunction(code, depends="RcppEigen", includes=c("#include <RcppEigen.h>"))
元データを作成します。
src <- matrix(1:100000000, nrow=10000)
Rで作成した関数
t <- proc.time()
dst_r <- PlusIJ_R(src)
print(proc.time() - t)
user system elapsed 11.17 0.05 11.23
RcppArmadilloで作成した関数
t <- proc.time()
dst_arma <- cppPlusIJ_Arma(src)
print(proc.time() - t)
user system elapsed 1.92 0.48 2.40
RcppEigenで作成した関数
t <- proc.time()
dst_eigen <- cppPlusIJ_Eigen(src)
print(proc.time() - t)
user system elapsed 1.82 0.51 2.34
結果のチェック
print("RcppArmadilloで作成した関数チェック")
all(dst_r == dst_arma)
print("RcppEigenで作成した関数チェック")
all(dst_r == dst_eigen)
[1] "RcppArmadilloで作成した関数チェック"
[1] "RcppEigenで作成した関数チェック"
今回の結果としては、以下の順位になりました。
forループを多用するコードになる場合は積極的に、「RcppArmadillo」や「RcppEigen」を使うべきだと思いました。
「RcppArmadillo」と「RcppEigen」のどちらを利用するかは、悩みどころです。