「オリジナルのR」、「RcppArmadillo」、「RcppEigen」で処理速度の比較をしてみたいと思います。
今回はソートで比較してみます。
「オリジナルのR」はorder()
、「Armadillo」はsort_index()
、「Eigen」はstd::sort()
を使います。
※ バージョンによっては正常に動作しない場合があります。私が試した環境は、
# パッケージの読込み
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::uvec IndexSortArma(arma::vec src)
{
// ソート
arma::uvec index = sort_index(src);
return index + 1; //Rのインデックスは1スタートなので、1追加
}
'
# コンパイルとリンクを行います(少し時間がかかります)
cppIndexSortArma <- cppFunction(code, depends="RcppArmadillo")
Eigenにはソート関数が無いようなので、std::sort()を使います。
std::vectorをインデックスをそのままにラムダ式でsortするを参考にしました。
# パッケージの読込み
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::VectorXi IndexSortEigen(Eigen::VectorXd src)
{
// 出力するインデックス
int num = src.size();
Eigen::VectorXi index(num);
std::iota(index.data(), index.data() + num, 0);
// ソート
std::sort(
index.data(),
index.data() + num,
[&src](double x, double y) -> bool { return src[x] < src[y]; }
);
return index.array() + 1; //Rのインデックスは1スタートなので、1追加
}
'
# コンパイルとリンクを行います(少し時間がかかります)
cppIndexSortEigen <- cppFunction(code, depends="RcppEigen", includes=c('#include <RcppEigen.h>'))
元データを作成します。
src <- rnorm(10000000)
「オリジナルのR」のorder()
t <- proc.time()
dst_r <- order(src)
print(proc.time() - t)
user system elapsed 0.57 0.05 0.62
「Armadillo」のsort_index()
t <- proc.time()
dst_arma <- cppIndexSortArma(src)
print(proc.time() - t)
user system elapsed 1.03 0.05 1.08
「Eigen」については、std::sort()
t <- proc.time()
dst_eigen <- cppIndexSortEigen(src)
print(proc.time() - t)
user system elapsed 2.15 0.03 2.18
結果のチェック
print("index_sort()の結果チェック")
all(dst_r == dst_arma)
print("std::sort()の結果チェック")
all(dst_r == dst_eigen)
[1] "index_sort()の結果チェック"
[1] "std::sort()の結果チェック"
今回の結果としては、以下の順位になりました。
order()
sort_index()
std::sort()
「Armadillo」や「Eigen」については、この結果でライブラリの性能についての良し悪しは言えないと思います。「Eigen」にいたっては、std::sort()
を使っていますし。
ただし、以下のことは言えると思っています。