Commit Graph

210 Commits

Author SHA1 Message Date
Oleksandr Pavlyk
d74c06f4b7 Harden nvbench-compare CLI failure handling
Apply the same small stability fixes to the modern and legacy compare scripts:
report malformed nested JSON through the structured parse-error path, reject
directory comparisons that produce no matching JSON files, use the supported
pipe table format for old tabulate versions, and retitle the summary plot as a
GPU timing change.

Add regression coverage for the modern comparator error paths and output
formatting.
2026-07-14 16:49:28 -05:00
Oleksandr Pavlyk
0f6e712b8f Fix bulk debug paths and duplicate plot series
Emit absolute sidecar paths in bulk-debug rows so generated debug scripts can
be replayed from a different working directory.

Also include duplicate state occurrence information in --plot-along series keys
for both modern and legacy comparators, preventing later duplicate states from
overwriting earlier plotted series.

Add regression coverage for absolute bulk-debug paths and duplicate plot-along
series.
2026-07-14 16:40:31 -05:00
Oleksandr Pavlyk
7d0940275c Remove unused parameters and unreachable code 2026-07-14 16:17:55 -05:00
Oleksandr Pavlyk
45cea23c89 Fix formatting of negative durations 2026-07-14 16:14:19 -05:00
Oleksandr Pavlyk
550154c9c4 Tighten nvbench_compare test coverage 2026-07-14 15:38:05 -05:00
Oleksandr Pavlyk
a822ce0311 Add missed legacy compare script to the test 2026-07-14 15:23:48 -05:00
Oleksandr Pavlyk
b6bc7cca91 Decouple plot-along rendering from row filtering 2026-07-14 15:20:29 -05:00
Oleksandr Pavlyk
149a2d257a Allow timing-only bulk data to confirm SAME
Permit nvbench-compare to use bulk timing samples to confirm SAME even when
sample frequency sidecars are unavailable. This lets legacy --jsonbin outputs,
which recorded sample times but not frequencies, avoid AMBG results when
summary noise is high but timing coverage clearly supports equality.

Cycle coverage is still required when frequency samples are present, and
FAST/SLOW clear-gap confirmation remains cycle-based.

Add regression coverage for noisy bulk samples that exceed the SAME noise
ceiling but are classified SAME from bulk timing/cycle coverage, including the
timing-only legacy-data path.
2026-07-14 15:06:55 -05:00
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