247 | | So for each quantity we maintain the following object: |
248 | | {{{ |
249 | | #define MIN_SAMPLES 20 |
250 | | // after this many samples, use exponentially averaged version |
251 | | #define SAMPLE_WEIGHT 0.001 |
252 | | // new samples get this weight in exp avg |
253 | | #define SAMPLE_LIMIT 10 |
254 | | // cap samples at recent_mean*10 |
255 | | |
256 | | struct STATS { |
257 | | int nsamples; |
258 | | double mean; |
259 | | double sum_var; |
260 | | double recent_mean; |
261 | | double recent_var; |
262 | | |
263 | | void update(double sample) { |
264 | | if (sample < 0) return; |
265 | | if (nsamples > MIN_SAMPLES) { |
266 | | if (sample > recent_mean*SAMPLE_LIMIT) { |
267 | | sample = recent_main*SAMPLE_LIMIT; |
268 | | } |
269 | | } |
270 | | // see http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance |
271 | | nsamples++; |
272 | | double delta = sample - mean; |
273 | | mean += delta/nsamples; |
274 | | sum_var += delta*(sample-mean); |
275 | | |
276 | | if (nsamples < MIN_SAMPLES) { |
277 | | recent_mean = mean; |
278 | | recent_var = sum_var/nsamples; |
279 | | } else { |
280 | | // update recent averages |
281 | | delta = sample - recent_mean; |
282 | | recent_mean += SAMPLE_WEIGHT*delta; |
283 | | double d2 = delta*delta - recent_var; |
284 | | recent_var += SAMPLE_WEIGHT*d2; |
285 | | } |
286 | | } |
287 | | }; |
288 | | }}} |
| 248 | The code that does all this is |
| 249 | [http://boinc.berkeley.edu/trac/browser/trunk/boinc/lib/average.h here]. |