Skip to content

Commit

Permalink
Fix float64 comparison test failure on archs using FMA
Browse files Browse the repository at this point in the history
Architectures using FMA optimization yield slightly different results so
we cannot assume floating point values will be precisely the same across
different architectures.

The solution in this change is to check "abs(a-b) < tolerance" instead
of comparing the exact values. This will give us confidence that the
histogram buckets are near identical.

Signed-off-by: Seth Bunce <[email protected]>
  • Loading branch information
sbunce committed Sep 13, 2022
1 parent 9801a4e commit e8353d9
Showing 1 changed file with 25 additions and 7 deletions.
32 changes: 25 additions & 7 deletions prometheus/histogram_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,14 +354,12 @@ func TestBuckets(t *testing.T) {
}

got = ExponentialBucketsRange(1, 100, 10)
want = []float64{
1.0, 1.6681005372000588, 2.782559402207125,
4.641588833612779, 7.742636826811273, 12.915496650148842,
21.544346900318846, 35.93813663804629, 59.94842503189414,
100.00000000000007,
want = []float64{1.0, 1.6681, 2.7825, 4.6415, 7.7426, 12.9154, 21.5443,
35.9381, 59.9484, 100.0000,
}
if !reflect.DeepEqual(got, want) {
t.Errorf("exponential buckets range: got %v, want %v", got, want)
const tolerance = 0.0001
if !equalFloat64s(got, want, 0.0001) {
t.Errorf("exponential buckets range: got %v, want %v (tolerance %f)", got, want, tolerance)
}
}

Expand Down Expand Up @@ -467,3 +465,23 @@ func TestHistogramExemplar(t *testing.T) {
}
}
}

// equalFloat64 returns true if a and b are within the tolerance. We have this
// because float comparison varies on different architectures. For example,
// architectures which do FMA yield slightly different results.
// https://github.com/prometheus/client_golang/pull/899#issuecomment-1244506390
func equalFloat64(a, b, tolerance float64) bool {
return math.Abs(a-b) < tolerance
}

func equalFloat64s(a, b []float64, tolerance float64) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if !equalFloat64(a[i], b[i], tolerance) {
return false
}
}
return true
}

0 comments on commit e8353d9

Please sign in to comment.