From 665eccc54386a10d44a0621f57ef3f2dc4e7bc30 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:08:31 -0500 Subject: [PATCH] Reject negative values for noise --- python/scripts/nvbench_compare.py | 14 +++++++------- python/test/test_nvbench_compare.py | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/python/scripts/nvbench_compare.py b/python/scripts/nvbench_compare.py index 1217bdc..ccaec52 100644 --- a/python/scripts/nvbench_compare.py +++ b/python/scripts/nvbench_compare.py @@ -1676,11 +1676,11 @@ def compare_timings_for_bulk_same(ref_timing, cmp_timing, thresholds): def compare_timings_for_same(ref_timing, cmp_timing, ref_noise, cmp_noise, thresholds): - if not has_finite_noise(ref_noise) or not has_finite_noise(cmp_noise): + if not is_usable_noise(ref_noise) or not is_usable_noise(cmp_noise): return make_decision( ComparisonStatus.UNDECIDED, "noise_unavailable", - "relative dispersion is unavailable or non-finite", + "relative dispersion is unavailable, negative, or non-finite", ) if max(ref_noise, cmp_noise) > thresholds.same_relative_dispersion_ceiling: return make_decision( @@ -1850,7 +1850,7 @@ def compare_gpu_timings(ref_timing, cmp_timing, comparison_thresholds=None): diff_interval = compute_diff_interval(ref_interval, cmp_interval) frac_diff_interval = compute_frac_diff_interval(ref_interval, cmp_interval) - if not has_finite_noise(ref_noise) or not has_finite_noise(cmp_noise): + if not is_usable_noise(ref_noise) or not is_usable_noise(cmp_noise): max_noise = None else: max_noise = max(ref_noise, cmp_noise) @@ -2488,8 +2488,8 @@ def align_timing_interval_columns(rows, comparisons, axis_count): ) -def has_finite_noise(noise): - return noise is not None and math.isfinite(noise) +def is_usable_noise(noise): + return noise is not None and math.isfinite(noise) and noise >= 0.0 def colorize_comparison_status(status, no_color): @@ -2918,9 +2918,9 @@ def compare_benches( start = None for i, noise_value in enumerate(noise): - if has_finite_noise(noise_value) and start is None: + if is_usable_noise(noise_value) and start is None: start = i - if not has_finite_noise(noise_value) and start is not None: + if not is_usable_noise(noise_value) and start is not None: plot_confidence_band(start, i) start = None diff --git a/python/test/test_nvbench_compare.py b/python/test/test_nvbench_compare.py index 96e4a67..a3861e1 100644 --- a/python/test/test_nvbench_compare.py +++ b/python/test/test_nvbench_compare.py @@ -732,6 +732,24 @@ def test_compare_gpu_timings_classifies_common_cases(tmp_path, nvbench_compare): assert same.diff_interval == pytest.approx((-0.28, 0.28)) assert same.frac_diff_interval == pytest.approx((-0.2153846154, 0.28)) + negative_noise = nvbench_compare.compare_gpu_timings( + ref_interval_timing, + make_gpu_timing_data( + nvbench_compare, + minimum=1.02, + first_quartile=1.1, + median=1.204, + third_quartile=1.28, + mean=1.204, + interquartile_range_relative=-0.01, + sm_clock_rate_mean=100.0, + ), + ) + assert negative_noise is not None + assert negative_noise.status == nvbench_compare.ComparisonStatus.UNDECIDED + assert negative_noise.max_noise is None + assert negative_noise.reason.code == "noise_unavailable" + weak_overlap = nvbench_compare.compare_gpu_timings( make_gpu_timing_data( nvbench_compare,