1. 学ぶ
  2. /
  3. コース
  4. /
  5. Rcpp で R コードを最適化する

Connected

演習

Rcpp ベクトルのサイズは変更しないでください

Rcpp のベクトルクラスは、R のベクトルをほぼそのまま薄く包んだラッパーとして設計されています。つまり、サイズを増減させると、その都度、適切なサイズの新しいベクトルを作成し、関連データをコピーする必要があります。これは非常に遅い処理なので、避けるべきです。

可能であれば、まず最終的なベクトルのサイズを計算してから、そのサイズでメモリを確保するようにコードを組み立ててください。

ここでは、R の x[x > 0] と同等の、ベクトルから正の値だけを選ぶ例を見てみましょう。事前に正の数がいくつあるか分からないため、要素数 0 のベクトルから始めて、見つけるたびに値を末尾に追加したくなるかもしれません。ここでの push_back() は値を追加する関数です。

NumericVector bad_select_positive_values_cpp(NumericVector x) {
  NumericVector positive_x(0);
  for(int i = 0; i < x.size(); i++) {
    if(x[i] > 0) {
      positive_x.push_back(x[i]);
    }
  }
  return positive_x;
}

しかし、この関数はそのたびに新しいベクトルを作ってデータをコピーするため、遅くなってしまいます。もっと良い方法を考えてみましょう!

指示

100 XP
  • より効率的な関数 good_select_positive_values_cpp() の定義を完成させ、正の数だけを選択してください。
    • 最初の for ループでは、x の i 番目の要素が 0 より大きければ、n_positive_elements に 1 を加えます。
    • そのループの後、サイズが n_positive_elements の数値ベクトル positive_x を確保します。
    • 2 つ目の for ループでも、x の i 番目の要素が 0 より大きいかを再度確認します。
    • 条件を満たしたら、positive_x の j 番目の要素を x の i 番目の要素に設定し、その後で j に 1 を加えます。
  • 比較のために bad_select_positive_values_cpp() がワークスペースに用意されています。コンソール出力を確認して、実行時間のベンチマーク差を見てみましょう。