From 42d786f1acb1fe315a194478bea69acdcd4aca56 Mon Sep 17 00:00:00 2001 From: darshanime Date: Sat, 30 Oct 2021 19:41:36 +0530 Subject: [PATCH] use kahan summation for aggregation functions Signed-off-by: darshanime --- promql/functions.go | 24 ++++++++++++++---------- promql/functions_test.go | 4 ++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/promql/functions.go b/promql/functions.go index e737992e46..49ff09678f 100644 --- a/promql/functions.go +++ b/promql/functions.go @@ -471,28 +471,32 @@ func funcQuantileOverTime(vals []parser.Value, args parser.Expressions, enh *Eva // === stddev_over_time(Matrix parser.ValueTypeMatrix) Vector === func funcStddevOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) Vector { return aggrOverTime(vals, enh, func(values []Point) float64 { - var aux, count, mean float64 + var count float64 + var mean, cMean float64 + var aux, cAux float64 for _, v := range values { count++ - delta := v.V - mean - mean += delta / count - aux += delta * (v.V - mean) + delta := v.V - (mean + cMean) + mean, cMean = kahanSumInc(delta/count, mean, cMean) + aux, cAux = kahanSumInc(delta*(v.V-(mean+cMean)), aux, cAux) } - return math.Sqrt(aux / count) + return math.Sqrt((aux + cAux) / count) }) } // === stdvar_over_time(Matrix parser.ValueTypeMatrix) Vector === func funcStdvarOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) Vector { return aggrOverTime(vals, enh, func(values []Point) float64 { - var aux, count, mean float64 + var count float64 + var mean, cMean float64 + var aux, cAux float64 for _, v := range values { count++ - delta := v.V - mean - mean += delta / count - aux += delta * (v.V - mean) + delta := v.V - (mean + cMean) + mean, cMean = kahanSumInc(delta/count, mean, cMean) + aux, cAux = kahanSumInc(delta*(v.V-(mean+cMean)), aux, cAux) } - return aux / count + return (aux + cAux) / count }) } diff --git a/promql/functions_test.go b/promql/functions_test.go index b0a8b5db6a..19ee105da7 100644 --- a/promql/functions_test.go +++ b/promql/functions_test.go @@ -73,8 +73,8 @@ func TestFunctionList(t *testing.T) { } } -func TestKahanSummation(t *testing.T) { +func TestKahanSum(t *testing.T) { vals := []float64{1.0, math.Pow(10, 100), 1.0, -1 * math.Pow(10, 100)} expected := 2.0 - require.Equal(t, expected, kahanSummation(vals)) + require.Equal(t, expected, kahanSum(vals)) }