Commit Graph

202 Commits

Author SHA1 Message Date
Oleksandr Pavlyk
25005fc9c4 Address review feedback for Python tooling scripts
Tighten missing-dependency install hints so compare-only dependencies point
to cuda-bench[compare] and plotting/dataframe dependencies point to
cuda-bench[plot], instead of defaulting every script to the broader tools
extra.

Also harden nvbench_compare_legacy by reporting missing or skipped state
summaries as UNKNOWN rows instead of silently dropping them, and by converting
missing axis metadata into the existing JSON-structure error path rather than
leaking StopIteration.

Finally, consolidate duplicate finite-number predicates in both compare
scripts so duration formatting and numeric validation share the same helper.
2026-07-09 16:50:36 -05:00
Oleksandr Pavlyk
cc17e96c3b Add nvbench-compare-legacy 2026-07-09 15:22:08 -05:00
Oleksandr Pavlyk
cb3ed117c0 Resolve benchmark-relative jsonbin sidecar paths in nvbench-compare
Thread the originating JSON path through bulk timing extraction so sidecar
filenames can be resolved with knowledge of the JSON basename. This lets
nvbench-compare handle --jsonbin output where the filename field may
store the benchmark-process-relative path, such as data/result.json-bin/0.bin,
instead of a path relative to the JSON file directory.

Keep resolution anchored to the JSON location and avoid falling back to the
caller working directory. Add regression coverage for this sidecar layout.

This change helps nvbench_compare properly resolve location of sidecar
binary files in the following CCCL-based workflow:

```
./bin/cub.bench.bitonic_sort.warp_keys.base -d 1 --cold-warmup-runs 16 --min-samples 100 --stopping-criterion entropy --min-r2 0.88 --jsonbin ../../../perf_data/warp-bitonic-sort-run1.json
./bin/cub.bench.bitonic_sort.warp_keys.base -d 1 --cold-warmup-runs 16 --min-samples 100 --stopping-criterion entropy --min-r2 0.88 --jsonbin ../../../perf_data/warp-bitonic-sort-run2.json

PYTHONPATH=./_deps/nvbench-src/python/scripts python ./_deps/nvbench-src/python/scripts/nvbench_compare.py ../../../perf_data/warp-bitonic-sort-run1.json ../../../perf_data/warp-bitonic-sort-run2.json
```

Before this change, script generated numerous RuntimeWarnigns alerting
that absolute path can not be resolved and bulk data will be treated as unavailable
2026-07-02 09:25:42 -05:00
Oleksandr Pavlyk
63fcd0afc4 Add nvbench_plot_bwutil to mock layout in test 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
73e6e8f0f9 Fix unexpected AttributeError when --no-color is used
Implemented robo-review feedback suggesting to expand coverage
of lazy loading helper.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
8d99eb10ed Clarify nvbench-compare validation helpers and CLI help
Factor finite-value checks through a common helper so positive and
non-negative finite predicates share the same None/finite guard. Add a
comment explaining the positive lower-bound clamp used for mean/stdev
intervals, since later ratio and log-distance checks require positive
bounds.

Also quote the --axis pow2 example in CLI help so shell users can copy
the example safely.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
4225c369fa percentile_rank use integer arithmetic and avoid use of floats 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
aff7bfae9e Implement typing for NumPy arrays friendly to lazy loading 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
f47063e41a make Python percentile_rank align C++ implementation
round in Python returns nearest even, while in C++ it
behaves as x -> floor(x + 0.5)
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
dd59fda561 colorama is not imported if --no-color is used 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
fd840b427b Harden tooling dependency import tests 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
ee66a4d6c1 Only translate ModuleNotFoundError exceptions
require_tooling_dependency() now only translates
ModuleNotFoundError when the missing module is the
requested top-level package. Other import
failures are re-raised unchanged.

This helps in situation where third-party dependency
is installed but broken for whatever reason. Previously
we would intercept it and suggest to run
pip install cuda-bench[tools], but that was already done.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
87937411e5 Load NVBench script tooling dependencies lazily
Add a shared nvbench_tooling_deps helper that imports packages required
by console tools and reports missing packages with an actionable install
recipe.

Update NVBench scripts to support both direct source-tree execution and
installed package execution through the __package__ import pattern. Defer
third-party tooling imports until they are needed, including lazy loading
for compare tables, device diffs, and plotting paths.

Make loaders resilient to partial initialization failures so a later
retry can complete any dependency that failed previously.

Update tests to cover direct internal use, packaged cuda.bench.scripts
imports, dependency-loader error messages, and cheap CLI validation before
tooling dependencies are loaded.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
2bb4ca63a9 Test packaged import path.
test_nvbench_tooling_deps.py now has a smoke test that builds a
temporary package layout matching the wheel mapping:

cuda/bench/scripts/nvbench_tooling_deps.py

and imports:

cuda.bench.scripts.nvbench_tooling_deps

That covers the cuda.bench.scripts.* path without requiring a wheel
build/install inside this unit test.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
68d638ca85 Move lazy load after cheap CLI arg validation
Move `load_nvbench_compare_tooling()` after:
  - config resolution / --dump-config
  - filter parsing
  - device-filter parsing
  - input arity validation
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
d682a8b0e0 Install scripts into cuda/bench.scripts in prefix
Introduce optional dependency categories in the wheel metadata,
with cuda-bench[tools] encompasing all dependencies of nvbench
scripts.

Closes #393
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
02373ec7b2 Load script tooling dependencies lazily
Add a shared nvbench_tooling_deps helper for importing packages required
by NVBench console tools. Missing tooling packages now raise a dedicated
error with an install recipe instead of failing with a raw ImportError.

Update script imports to work both as installed package modules and as
direct source-tree scripts by using the __package__ import pattern for
nvbench_json and the new tooling helper.

Defer nvbench-compare dependencies to the points where they are needed:
NumPy/colorama during normal comparison setup, tabulate during table
rendering, jsondiff only for device mismatch reporting, and plotting
packages only for plot modes.

Update tests to initialize compare tooling when calling internals
directly and add coverage for the tooling dependency loader.

Closes #384
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
45f28e2855 Handle legacy nvbench-compare timing summaries
Derive absolute standard deviation from relative stdev and mean when
nv/cold/time/gpu/stdev/absolute is absent. This lets older JSON files
that only contain mean and relative stdev still construct timing
intervals.

Also allow mean/stdev intervals to be built without min/max summaries,
using min/max only as optional clipping bounds when present. This
restores SAME classification for legacy fixture data instead of treating
those rows as missing-interval AMBG cases.

Update nvbench_compare tests to cover derived stdev handling and the
legacy mean/stdev comparison path.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
46e61aa12b Respect custom bulk readers in materiality checks
Move Float32BinarySource material-payload detection into the source object.
Default file-backed sources still use resolved file size so missing or empty
sidecars remain unavailable, but positive-count sources with custom readers are
treated as material and proceed through the lazy read path.

Add regression coverage for virtual bulk sources whose custom reader provides
data without a local sidecar file.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
a822e2d4c8 --threshold-diff is treated as % value, as documented 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
021a639407 Harden nvbench-compare parsing and plot tests
Reject boolean summary float payloads instead of coercing them to 1.0/0.0,
while keeping numeric strings accepted for NVBench JSON compatibility.

Add regression coverage for generated bulk-debug Python filenames that require
escaping, and strengthen the plot-along test to assert log-log axes and
confidence-band rendering.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
adb7e2a0ca Test to use --bulk-debug-python stdout, not STDOUT
Also add a test to check that STDOUT also works.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
2e0f635b6c Match benchmark-axis scoping to NVBench CLI
When any --benchmark filter is present, keep comparison limited to the
explicitly selected benchmarks. Leading --axis filters are still replayed onto
each selected benchmark, matching native NVBench option parsing, but they no
longer cause unrelated benchmarks to be compared.

E.g., `-a A=2 -b bench1` now compares only bench1,
`-a A=2 -b bench1 -b bench2` applies A=2 to both selected benchmarks

Update tests for global axis filters with benchmark scopes and document the
selection behavior.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
58feaaf6dd Include axis values in duplicate-state matching before falling back to occurrence order. 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
02e2d6f097 Compute quantiles the same way C++ does
Use rounded-rank method, rather than NumPy's quantile
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
ad4a76dbe1 Validate bulk binary sizes as integral metadata
Reject boolean and floating-point values for int64 bulk binary sizes instead of
silently converting them with int(). Keep integer strings accepted for existing
NVBench JSON compatibility, and add regression coverage for valid and malformed
size payloads.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
2878f7ccae Keep robust timing comparisons per side
Select robust timing inputs independently for reference and compare data:
prefer robust summaries when present, otherwise recompute robust statistics from
that side's bulk samples. Fall back to mean/stdev summaries only when both sides
cannot provide robust timing inputs.

This allows modern JSON data with robust summaries to compare against legacy JSON
data that lacks robust summaries but includes bulk sample data, without mixing
summary families or unnecessarily falling back to mean/stdev.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
9b79d9db4b Do not resolve missing bulk files against CWD
Introduce has_robust_interval predicate and used it.
It is used to check whether robust interval can be constructed
before attempting that and falling back to mean/stdev construction
otherwise
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
28c21dcbb3 Wrap JSON parsing in try/except
This reports a meaningful error if JSON file is not formed as
nvbench_compare expected without replicating JSON schema in code.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
f388764ace Validate type of values for expected keys in JSON file 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
9cf6c3e49c Run the plot test with plot=True keyword to make sure it is exercised 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
e29f4c65c9 Implement review feedback on test_nvbench_compare
1. Skip test when running with Py3.10 if tomli is unavailable
   before nvbench_compare fixture is constructed, that is at
   collection time rather than at execution time
2. Check that test of plotting options calls plot
3. Test actual output to verify that warning about device
   mismatch is absent when device selection is requested
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
ee2ca490a5 Fix nvbench-compare filter and plot validation
Keep leading --axis filters global even when later --benchmark scopes are
present, so commands like "-a A=2 -b bench" still compare other benchmarks
matching the global axis filter.

Tighten --plot-along validation for the log-log plot path by rejecting
non-numeric, non-positive, and non-finite axis values with targeted errors.

Add regression coverage for global axis scoping and invalid plot-axis values.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
901dcd5026 Introduce helper to read JSON files for tests 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
58030150bf Reject non-numeric --plot-along axes
Add explicit validation for plot-axis values so string/type axes fail with a
clear CLI error instead of a raw float conversion exception. Add regression
coverage for a type axis.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
08d2f49aa9 Replace Pass bucket in the summary output with Unchanged, clarified description 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
b000f6d7e6 Harden nvbench-compare input and noise handling
Route NVBench JSON read failures and missing required root keys through the
documented user-facing error path so malformed inputs return 1 instead of
producing a traceback.

Allow deterministic mean-based timing summaries with zero standard deviation to
form zero-width intervals, while still rejecting negative or non-finite
dispersion values. Reuse the same non-negative finite predicate for relative
noise validation.

Add regression coverage for unreadable inputs, missing root keys, and identical
stable timing summaries.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
9a978cd410 Reject negative values for noise 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
55ee4e4d45 Tighten nvbench-compare argument parsing
Let argparse derive the program name from the actual invocation instead of
hardcoding nvbench_compare, so help and error output match the installed
nvbench-compare entry point.

Declare comparison inputs as explicit positional arguments and use parse_args()
instead of parse_known_args(). This preserves --dump-config without input files
while rejecting unknown options through argparse rather than treating typoed
flags as JSON paths.

Add regression coverage for rejecting an unknown CLI option.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
4fabe3fde9 Harden nvbench-compare plotting and filter docs
Skip UNKNOWN rows when collecting summary plot entries so non-numeric
fractional differences cannot reach the plotting path. Add a regression test
that exercises compare_benches(..., plot=True) with an UNKNOWN row.

Document the supported pow2 axis-filter syntax and update the CLI help example
to use NAME[pow2]=EXP, matching the parser behavior for axes displayed as 2^N.

* Document when status ???? (UNKNOWN) is emitted
* Clarify --no-color behavior

* nvbench_compare.md: clarify --no-color behavior, fix example

* Document display options in nvbench_compare.md

* Small mention of plotting capabilities in nvbench_compare.md
* Call out that example requires shell with process substitution capabilities
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
118382daf1 ComparisonThresholds no longer provides constructor with defaults
Test file changed to use get_default_thresholds() function instead
of call to constructor.

This is to make sure that default preset values do not diverge from
values encoded in the constructor.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
e75815ff97 Use legacy np.unique(..., return_counts=True)
This is to support older versions of NumPy
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
f72c02dba2 Keep nvbench-compare bulk debug output executable
* Define nan and inf in generated --bulk-debug-python scripts so pprint output
for non-finite timing values remains valid Python code. Add a regression test
that executes the generated script and verifies nan/inf values round-trip.

* Sharpen bulk-cycle confirmation gating. Only suppress summary-clock
fallback when both reference and compare inputs provide paired, non-empty bulk
sample/frequency payloads. Missing or empty bulk files are treated as
unavailable evidence and still allow sm_clock_rate/mean fallback, while
malformed non-empty payloads continue to produce AMBG.

Add regression coverage for missing bulk files falling back to summary-cycle
confirmation.

These changes resolve automated review feedback
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
4f66b5d7f0 Harden nvbench-compare tests for diagnostics paths
* Register the dynamically loaded nvbench_compare module in sys.modules before
executing it so tests better match normal import behavior.

* Add shared tabulate-capture helpers and select rendered comparison tables by
header suffix instead of relying on the last tabulate call. This makes display
tests robust to future summary or legend table output.

* Add coverage for unusable bulk cycle data forcing an ambiguous result instead
of falling back to summary clock confirmation.

* Rename the TOML parser integration test to clarify that it exercises whichever
parser is available in the environment, and document the Python 3.10 tomli
skip behavior.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
4f67ddd083 Treat unusable bulk cycle data as ambiguous
When bulk sample or frequency sources are present, do not silently fall
back to summary SM clock confirmation if the bulk cycle data cannot be
used. Report the clear-gap decision as AMBG with a
bulk_cycle_data_unusable reason instead.

Still allow summary-clock fallback when no bulk sample/frequency sources
are present.

Also update the Unknown summary label to describe the broader set of
input-data failures now counted as UNKNOWN.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
dea0272f02 Explicitly handle unavailable timings in nvbench-compare
Treat matched states with unusable timing data as UNKNOWN instead of
dropping them from the comparison. This includes missing, non-finite, or
non-positive timing centers, skipped states, and states with missing GPU
timing summaries.

Add explicit reason codes for these cases so the summary points users at
the underlying data issue. Preserve available timing data from the other
side when only one side is missing, and render unavailable durations as
n/a in all display modes.

Also sort values returned by np.unique_counts before nearest-neighbor
coverage checks so the distance algorithm receives ordered inputs.

Add regression coverage for UNKNOWN counting, skipped states, missing
summaries, unavailable center formatting, and the updated coverage helper.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
104a06a93f Ensure that bulk-debug-python script is enclosed in markers
This permits extracting Python script using Unix CLI tools
when `--bulk-debug-python stdout` is used.

Added example of using this to nvbench_compare.md doc.
2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
2518b43ac3 Replaced UNDECIDED with AMBG, use Gray color/shrug emoji 2026-07-02 07:26:49 -05:00
Oleksandr Pavlyk
6ecf0fe2bb Improve nvbench-compare interval display readability
Add compact reason labels for explain-mode tables while keeping canonical
reason codes in the undecided summary. Emit a one-line legend only for
non-trivial abbreviations.

Refine interval displays so timing values align across table rows:
  - align Lo/Ce/Hi values in explain mode
  - align center values in intervals mode when some rows lack interval bounds
  - avoid repeating units when center and interval deltas use the same unit

Add a Change column for non-legacy displays so FAST/SLOW rows show the
signed interval-bound relative change, while SAME and UNDECIDED rows remain
blank.

Extend nvbench_compare tests to cover reason legend filtering, interval
alignment, missing-interval alignment, and Change column formatting.
2026-07-02 07:26:48 -05:00
Oleksandr Pavlyk
6cb930971a Implement --bulk-debug-python option
Use this option to generate Python script with information needed to load
bulk data from reference/compare datasets for further drill-down into
data.
2026-07-02 07:26:48 -05:00