移動平均(C++)
向量化的移動平均函式 rollmean3() 效能不錯,但可讀性很差。從這段程式碼看出它在計算移動平均非常不容易,讓除錯與維護都更困難。
第二個版本 rollmean2() 較慢,但更容易閱讀。若把它翻成 C++,理想情況下能同時兼顧易讀性與高效能。
rollmean2() 已定義在你的工作空間;你可以印出它的定義來回想其運作方式。接下來你要把 rollmean2() 轉寫成 C++,並指定為 rollmean4()。
本練習屬於課程
用 Rcpp 最佳化 R 程式碼
練習說明
- 將
res設為長度為n的NumericVector,其初始值由NumericVector的get_na()方法提供。 - 將
total設為x的前window個值的總和。 - 在索引
window - 1的位置計算平均數,做法是用總和除以視窗寬度。 - 在第二個迴圈中,透過減去
x的第i - window個元素並加上第i個元素來更新總和。
動手互動練習
試著完成這個範例程式碼,體驗一下這個練習。
#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
)
*/