Średnie kroczące (w C++)
Wektoryzowana funkcja średniej kroczącej rollmean3() działała wydajnie, ale była bardzo trudna w odczycie. Ciężko się domyślić, że ten kod oblicza średnią kroczącą, co utrudnia debugowanie i utrzymanie funkcji.
Druga wersja, rollmean2(), była wolniejsza, ale znacznie czytelniejsza. Jeśli przeniesiemy ją do C++, powinniśmy uzyskać zarówno czytelność kodu, jak i wysoką wydajność.
rollmean2() jest zdefiniowana w twoim środowisku pracy – możesz wyświetlić jej definicję, aby przypomnieć sobie, jak działa. Teraz przetłumacz rollmean2() na C++, przypisując wynik do rollmean4().
To ćwiczenie jest częścią kursu
Optymalizacja kodu R za pomocą Rcpp
Instrukcje do ćwiczenia
- Ustaw
resjakoNumericVectoro długościni wartościach zwracanych przez metodęget_na()obiektuNumericVector. - Oblicz
totaljako sumę pierwszychwindowwartościx. - Oblicz średnią przy indeksie
window - 1jakototalpodzielone przez szerokość okna. - W drugiej pętli zaktualizuj sumę, odejmując
i - window-ty elementxi dodająci-ty elementx.
Interaktywne ćwiczenie praktyczne
Spróbuj tego ćwiczenia, uzupełniając ten przykładowy kod.
#include
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector rollmean4(NumericVector x, int window) {
int n = x.size();
// Set res as a NumericVector of NAs with length n
NumericVector res(___, ___::___());
// Sum the first window worth of values of x
double total = 0.0;
for(int i = 0; i < window; i++) {
total += ___;
}
// Treat the first case seperately
res[window - 1] = ___ / window;
// Iteratively update the total and recalculate the mean
for(int i = window; i < n; i++) {
// Remove the (i - window)th case, and add the ith case
total += - ___ + ___;
// Calculate the mean at the ith position
res[i] = total / window;
}
return res;
}
/*** R
# Compare rollmean2, rollmean3 and rollmean4
set.seed(42)
x <- rnorm(1e4)
microbenchmark(
rollmean2(x, 4),
rollmean3(x, 4),
rollmean4(x, 4),
times = 5
)
*/