STL のベクター
standard template library(stl)は、柔軟なアルゴリズムとデータ構造を含む C++ のライブラリです。たとえば、stl の double ベクターは、Rcpp の NumericVector に相当する「ネイティブ C++」の型です。次のコードは、10 要素の標準的な double ベクター x を作成します。
std::vector<double> x(10);
通常は、mean()、round()、abs() など R と同様に使える便利なメソッドにアクセスできるため、Rcpp のベクター型を使うほうが理にかなっています。しかし、stl のベクターには、毎回データをコピーすることなく動的にサイズを変更できるという利点があります。これにより、前の演習で扱った「bad」関数のような、よりシンプルなコードを書きつつ、「good」コードに匹敵する性能を維持できます。
この演習はコースの一部です
Rcpp で R コードを最適化する
演習の手順
- 正の数を選び出す、stl ベクター版の関数
select_positive_values_std()の定義を完成させてください。- 関数の戻り値の型を、
std::vector<double>を用いた標準の double ベクターに設定します。 - サイズが
0の標準 double ベクターpositive_xを定義します。 forループ内のifブロックで、positive_xのpush_back()を使って、xの i 番目の要素を追加します。
- 関数の戻り値の型を、
- 比較用に、前の演習の
good_select_positive_values_cpp()がワークスペースに用意されています。コンソール出力を確認して、2 つの関数の相対的な速度を見てみましょう。
実践的なインタラクティブ演習
このサンプルコードを完成させて、この演習に挑戦してみましょう。
#include
using namespace Rcpp;
// Set the return type to a standard double vector
// [[Rcpp::export]]
___ select_positive_values_std(NumericVector x) {
int n = x.size();
// Create positive_x, a standard double vector
___;
for(int i = 0; i < n; i++) {
if(x[i] > 0) {
// Append the ith element of x to positive_x
___;
}
}
return positive_x;
}
/*** R
set.seed(42)
x <- rnorm(1e6)
# Does it give the same answer as R?
all.equal(select_positive_values_std(x), x[x > 0])
# Which is faster?
microbenchmark(
good_cpp = good_select_positive_values_cpp(x),
std = select_positive_values_std(x)
)
*/