Trung bình trượt (bằng C++)
Hàm trung bình trượt dạng vector hóa, rollmean3() chạy khá nhanh nhưng lại rất khó đọc. Rất khó nhận ra đây là mã tính trung bình trượt, khiến hàm khó gỡ lỗi và bảo trì.
Phiên bản thứ hai, rollmean2(), chậm hơn nhưng dễ đọc hơn. Nếu ta chuyển nó sang C++, hy vọng sẽ vừa dễ đọc vừa chạy nhanh.
rollmean2() đã được định nghĩa sẵn trong không gian làm việc; bạn có thể in định nghĩa của nó để nhớ lại cách hoạt động. Giờ bạn sẽ dịch rollmean2() sang C++, gán thành rollmean4().
Bài tập này là một phần của khóa học
Tối ưu hóa mã R với Rcpp
Hướng dẫn bài tập
- Gán
reslà mộtNumericVectorcó độ dàinvà các giá trị được cung cấp bởi phương thứcget_na()củaNumericVector. - Tính
totallà tổng củawindowgiá trị đầu tiên củax. - Tính giá trị trung bình tại vị trí
window - 1bằng tổng chia cho độ rộng cửa sổ. - Trong vòng lặp thứ hai, cập nhật tổng bằng cách trừ phần tử thứ
i - windowcủaxvà cộng phần tử thứicủax.
Bài tập tương tác thực hành trực tiếp
Hãy thử làm bài tập này bằng cách hoàn thành đoạn mã mẫu này.
#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
)
*/