Rcpp vektörlerinin boyutunu değiştirme
Rcpp vektör sınıfları, R vektörlerinin üzerine çok ince bir katman olarak tasarlanmıştır. Bu, performans açısından, bunları büyütmenin veya küçültmenin doğru boyutta yeni bir vektör oluşturup ilgili verileri kopyalamak anlamına geldiği sonucunu doğurur. Bu işlem çok yavaştır, bu yüzden kaçınmak gerekir.
Mümkünse, önce vektörün nihai boyutunu hesaplayıp ardından o boyutta ayıracak şekilde kodunu yapılandırmalısın.
R'de x[x > 0] ifadesine eşdeğer olarak, bir vektörden pozitif değerleri seçen bir örnek görelim. Kaç tane pozitif sayı olacağını önceden bilmediğin için, sıfır uzunlukta bir vektörle başlayıp her bulduğunda bir değer eklemek cazip gelebilir. Burada, push_back() bir değeri sona ekleyen bir işlevdir.
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;
}
Ne yazık ki bu işlev yavaş olacaktır çünkü tekrar tekrar yeni vektörler oluşturup verileri kopyalaması gerekir. Daha iyisini yapabilir misin?
Bu egzersiz, kursun bir parçasıdır
Rcpp ile R Kodunu Optimize Etme
Egzersiz talimatları
- Daha verimli bir işlev olan
good_select_positive_values_cpp()tanımını, pozitif sayıları seçecek şekilde tamamla.- İlk
fordöngüsünde,x'in i'inci öğesi sıfırdan büyüksen_positive_elementsdeğişkenine bir ekle. - O döngüden sonra, boyutu
n_positive_elementsolanpositive_xadlı bir sayısal vektör ayır. - İkinci
fordöngüsünde, yinex'in i'inci öğesinin sıfırdan büyük olup olmadığını kontrol et. - Büyükse,
positive_x'in j'inci öğesinix'in i'inci öğesine eşitle, ardındanj'yi bir artır.
- İlk
- Karşılaştırma için
bad_select_positive_values_cpp()çalışma alanında mevcut. Zaman ölçümü farkını görmek için konsol çıktısını incele.
Uygulamalı etkileşimli egzersiz
Bu egzersizi bu örnek kodu tamamlayarak deneyin.
#include
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector good_select_positive_values_cpp(NumericVector x) {
int n_elements = x.size();
int n_positive_elements = 0;
// Calculate the size of the output
for(int i = 0; i < n_elements; i++) {
// If the ith element of x is positive
if(___) {
// Add 1 to n_positive_elements
___;
}
}
// Allocate a vector of size n_positive_elements
___;
// Fill the vector
int j = 0;
for(int i = 0; i < n_elements; i++) {
// If the ith element of x is positive
if(___) {
// Set the jth element of positive_x to the ith element of x
___;
// Add 1 to j
___;
}
}
return positive_x;
}
/*** R
set.seed(42)
x <- rnorm(1e4)
# Does it give the same answer as R?
all.equal(good_select_positive_values_cpp(x), x[x > 0])
# Which is faster?
microbenchmark(
bad_cpp = bad_select_positive_values_cpp(x),
good_cpp = good_select_positive_values_cpp(x)
)
*/