From b6bc7cca91013da40553ed579dda8e6e5cde1167 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Tue, 14 Jul 2026 15:20:29 -0500 Subject: [PATCH] Decouple plot-along rendering from row filtering --- python/scripts/nvbench_compare.py | 52 ++++++++++++++----------- python/test/test_nvbench_compare.py | 60 +++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 23 deletions(-) diff --git a/python/scripts/nvbench_compare.py b/python/scripts/nvbench_compare.py index b64ffde..f0ad1e2 100644 --- a/python/scripts/nvbench_compare.py +++ b/python/scripts/nvbench_compare.py @@ -3264,12 +3264,12 @@ def compare_benches( ) ) - if len(rows) == 0: + has_rows = len(rows) > 0 + has_plot_along_data = bool(plot_along) and any( + axis_times for axis_times in plot_data["cmp"].values() + ) + if not has_rows and not has_plot_along_data: continue - if display == "explain": - align_explain_interval_columns(rows, row_comparisons, len(axes)) - elif display == "intervals": - align_timing_interval_columns(rows, row_comparisons, len(axes)) cmp_device = find_device_by_id(cmp_device_id, run_data.cmp_devices) ref_device = find_device_by_id(ref_device_id, run_data.ref_devices) @@ -3279,27 +3279,33 @@ def compare_benches( f"ref={ref_device_id} cmp={cmp_device_id}, but device metadata is missing" ) - if cmp_device == ref_device: - print(f"## [{cmp_device['id']}] {cmp_device['name']}\n") - else: - print( - f"## [{ref_device['id']}] {ref_device['name']} vs. " - f"[{cmp_device['id']}] {cmp_device['name']}\n" - ) - tabulate, tabulate_version = load_tabulate_for_table_output() - # colalign and github format require tabulate 0.8.3 - if tabulate_version >= (0, 8, 3): - print( - tabulate.tabulate( - rows, headers=headers, colalign=colalign, tablefmt="github" + if has_rows: + if display == "explain": + align_explain_interval_columns(rows, row_comparisons, len(axes)) + elif display == "intervals": + align_timing_interval_columns(rows, row_comparisons, len(axes)) + + if cmp_device == ref_device: + print(f"## [{cmp_device['id']}] {cmp_device['name']}\n") + else: + print( + f"## [{ref_device['id']}] {ref_device['name']} vs. " + f"[{cmp_device['id']}] {cmp_device['name']}\n" ) - ) - else: - print(tabulate.tabulate(rows, headers=headers, tablefmt="markdown")) + tabulate, tabulate_version = load_tabulate_for_table_output() + # colalign and github format require tabulate 0.8.3 + if tabulate_version >= (0, 8, 3): + print( + tabulate.tabulate( + rows, headers=headers, colalign=colalign, tablefmt="github" + ) + ) + else: + print(tabulate.tabulate(rows, headers=headers, tablefmt="markdown")) - print("") + print("") - if plot_along: + if has_plot_along_data: fig = plt.figure() try: plt.xscale("log") diff --git a/python/test/test_nvbench_compare.py b/python/test/test_nvbench_compare.py index e2d5b56..4cd87fd 100644 --- a/python/test/test_nvbench_compare.py +++ b/python/test/test_nvbench_compare.py @@ -2193,6 +2193,66 @@ def test_plot_along_skips_states_without_selected_axis(monkeypatch, nvbench_comp assert [call["x"] for call in fill_between_calls] == [[1.0, 2.0], [1.0, 2.0]] +def test_plot_along_ignores_threshold_diff_table_filter(monkeypatch, nvbench_compare): + run_data = make_comparison_run_data(nvbench_compare) + plot_calls = [] + table_calls = [] + + def fake_plot(x, y, shape, *args, **kwargs): + plot_calls.append({"x": x, "y": y, "shape": shape}) + return [types.SimpleNamespace(get_color=lambda: "black")] + + monkeypatch.setattr(sys.modules["matplotlib.pyplot"], "plot", fake_plot) + monkeypatch.setattr( + sys.modules["matplotlib.pyplot"], "fill_between", lambda *args, **kwargs: None + ) + monkeypatch.setattr( + nvbench_compare, + "load_tabulate_for_table_output", + lambda: ( + types.SimpleNamespace( + tabulate=lambda *args, **kwargs: table_calls.append(args) + ), + (0, 8, 10), + ), + ) + + ref_benches = [ + make_benchmark( + [ + make_state(nvbench_compare, "state", axis_value=1), + make_state(nvbench_compare, "state", axis_value=2), + ] + ) + ] + cmp_benches = [ + make_benchmark( + [ + make_state(nvbench_compare, "state", axis_value=1), + make_state(nvbench_compare, "state", axis_value=2), + ] + ) + ] + + nvbench_compare.compare_benches( + run_data, + ref_benches, + cmp_benches, + threshold=1.0, + plot_along="A", + plot=False, + dark=False, + filter_plan=make_filter_plan(nvbench_compare), + no_color=True, + ) + + assert run_data.stats.config_count == 2 + assert run_data.stats.pass_count == 2 + assert table_calls == [] + assert [call["x"] for call in plot_calls] == [[1.0, 2.0], [1.0, 2.0]] + assert [call["shape"] for call in plot_calls] == ["-", "--"] + + def test_plot_along_rejects_non_numeric_axis_values(monkeypatch, nvbench_compare): run_data = make_comparison_run_data(nvbench_compare)