stats: Use an algorithm popularised by Knuth to compute mean and variance

Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
This commit is contained in:
Damien Lespiau 2015-06-25 23:57:49 +01:00
parent 9986282c2b
commit 05c10f940f
2 changed files with 41 additions and 6 deletions

View File

@ -42,15 +42,47 @@ void igt_stats_push(igt_stats_t *stats, uint64_t value)
{ {
igt_assert(stats->n_values < stats->capacity); igt_assert(stats->n_values < stats->capacity);
stats->values[stats->n_values++] = value; stats->values[stats->n_values++] = value;
stats->mean_variance_valid = false;
}
/*
* Algorithm popularised by Knuth in:
*
* The Art of Computer Programming, volume 2: Seminumerical Algorithms,
* 3rd edn., p. 232. Boston: Addison-Wesley
*
* Source: https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
*/
static void igt_stats_knuth_mean_variance(igt_stats_t *stats)
{
double mean = 0., m2 = 0.;
unsigned int i;
if (stats->mean_variance_valid)
return;
for (i = 0; i < stats->n_values; i++) {
double delta = stats->values[i] - mean;
mean += delta / (i + 1);
m2 += delta * (stats->values[i] - mean);
}
stats->mean = mean;
stats->variance = m2 / stats->n_values;
stats->mean_variance_valid = true;
} }
double igt_stats_get_mean(igt_stats_t *stats) double igt_stats_get_mean(igt_stats_t *stats)
{ {
unsigned int i; igt_stats_knuth_mean_variance(stats);
double a = 0.0;
for (i = 0; i < stats->n_values; i++) return stats->mean;
a += (double)stats->values[i] / stats->n_values; }
return a; double igt_stats_get_variance(igt_stats_t *stats)
{
igt_stats_knuth_mean_variance(stats);
return stats->variance;
} }

View File

@ -28,9 +28,12 @@ typedef struct {
uint64_t *values; uint64_t *values;
unsigned int capacity; unsigned int capacity;
unsigned int n_values; unsigned int n_values;
unsigned int mean_variance_valid : 1;
double mean, variance;
} igt_stats_t; } igt_stats_t;
void igt_stats_init(igt_stats_t *stats, unsigned int capacity); void igt_stats_init(igt_stats_t *stats, unsigned int capacity);
void igt_stats_fini(igt_stats_t *stats); void igt_stats_fini(igt_stats_t *stats);
void igt_stats_push(igt_stats_t *stats, uint64_t value); void igt_stats_push(igt_stats_t *stats, uint64_t value);
double igt_stats_get_mean(igt_stats_t *stats); double igt_stats_get_mean(igt_stats_t *stats);
double igt_stats_get_variance(igt_stats_t *stats);