Skip to content

fix(tensilelite): fail the LibraryClient step when the library selects no solution - #15254

Open
Alex-Vasile wants to merge 1 commit into
users/alvasile/tl-speedup-03-codegen-worker-metadatafrom
users/alvasile/tl-speedup-04-library-client-require-selection
Open

Alex-Vasile wants to merge 1 commit into
users/alvasile/tl-speedup-03-codegen-worker-metadatafrom
users/alvasile/tl-speedup-04-library-client-require-selection

Conversation

@Alex-Vasile

@Alex-Vasile Alex-Vasile commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

JIRA ID : AIHPBLAS-5255

Motivation

A Tensile test config can end with a LibraryClient step. It writes library logic, builds a solution library from it, and runs tensilelite-client, the C++ program that runs and validates generated GPU kernels, in --best-solution mode, so the library itself picks the kernel for each problem. That step is how the tests check solution selection. When selection returned nothing, the client ran library solution 0 instead and exited 0. Tensile also ignored the LibraryClient run's return code, so a broken selection (for example, a Prediction library with no hardware model) passed its test.

Technical Details

Production code:

  • Client (main.cpp, SolutionIterator.hpp, SolutionIterator.cpp): a new option --require-selected-solution (default false). With it, TopSolutionIterator, the iterator --best-solution uses, does not fall back to solution 0 when selection is empty. It logs [TopSolutionIterator] No solution selected for problem <op> sizes <...> at Error level, skips the problem and counts it in a new error() override. The client then exits non-zero, through the same channel as a validation failure. Without the option, behavior is unchanged.
  • ClientWriter.writeRunScript passes the option only on the LibraryClient run. Benchmark runs do not get it.
  • Tensile.executeStepsInConfig now keeps ClientWriter.main's return code for the LibraryClient run. A non-zero code ends Tensile with LibraryClient exited with code N when ExitOnFails is set (default 1), as the benchmark step already does. The ExitOnFails comment in GlobalParameters.py says so.

Test code: tests/SolutionIteratorSelection_test.cpp (registered in tests/CMakeLists.txt) has 3 host-only gtests through SolutionIterator::Default(). They cover a selection running with or without the option, the solution-0 fallback without it, and skip, log and count with it. Tests/unit/test_library_client_require_selection.py has 5 tests: the option is written on LibraryClient lines and not on benchmark lines, a return code of 1 ends Tensile, and 0 or ExitOnFails: 0 do not.

Behavior change: every test config with a LibraryClient section now fails when selection is empty, or when the LibraryClient run exits non-zero for any other reason. A client binary older than this change aborts on the unknown option.

Test Plan

From projects/hipblaslt/tensilelite. C++ tests use one configured build: cmake --preset tensilelite -S .. -B <build> -DTENSILELITE_BUILD_TESTING=ON and cmake --build <build> --parallel.

  • tox -e unit -- tensilelite/Tests/unit/test_library_client_require_selection.py tensilelite/Tests/unit/characterization checks the run script and the return-code rule, plus the existing ClientWriter characterization tests.
  • ctest --test-dir <build>/tensilelite/tests --output-on-failure -R 'SolutionIteratorSelection' runs the 3 gtests.
  • tox -e py3 -- tensilelite/Tests -m common -k 'xfp32' on a gfx942 GPU runs the GridBased LibraryClient config, which only runs on gfx942.
  • pre-commit run --files client/include/SolutionIterator.hpp client/main.cpp client/src/SolutionIterator.cpp tensilelite/ClientWriter.py tensilelite/Common/GlobalParameters.py tensilelite/Tensile.py tensilelite/Tests/unit/test_library_client_require_selection.py tests/CMakeLists.txt tests/SolutionIteratorSelection_test.cpp runs the repository hooks.

Regression tests: SolutionIteratorSelectionTest.NothingSelectedIsAnErrorWithTheOption and test_failed_library_client_run_fails_tensile. Both must be shown to fail without the fix and pass with it, in a shared CI lane (TheRock GitHub Actions or Math CI). The LibraryClient step itself must also pass on gfx942 and gfx950.

Test Result

These results were taken on the original unsplit branch, on a gfx950 host with a development build:

  • On an ini file for which nothing is selected, the old client and the new client without the option exited 0 running solution 0. With the option, the new client exited 1 and printed the message.
  • prediction_bf16 passed with the library's own pick, MT64x64. With a client wrapper that made its problem unmatched, Tensile exited 255 and the pytest run phase failed.
  • CTest: 1,507 of 1,507 passed, 3 of them new. A mutant that ignores the option failed the new gtest. The 5 new Python tests and 35 ClientWriter run-path characterization tests passed; the new tests failed against the unfixed Python files.
  • The full TensileLite unit suite did not run to completion: a host process killed pytest runs. 2 of 12 chunks completed, with 1,572 passed and 0 failures.
  • xfp32.yaml was not run with the option, because it is gfx942-only. A gfx950 F32 copy of it passed.

Not yet run on this branch. Automated GitHub checks are pending.

Related

  • Work tracking: AIHPBLAS-5255

Device / Architecture Coverage

Client host code (solution iteration) and the Python test harness; no kernel generation changes. The LibraryClient step runs on the GPU, and xfp32.yaml runs only on gfx942. Before merge, the common tests' LibraryClient configs need a passing run on gfx942 and gfx950 in CI.

Submission Checklist

Risk level

Moderate (3/5): any non-zero LibraryClient exit now fails Tensile, including validation failures that used to pass with a warning and clients built from an older tree. The gfx942-only xfp32 LibraryClient step has not been run with the option, and the full unit suite has not completed.

@Alex-Vasile Alex-Vasile added NoCI Don't run CI ci:skip Skip all CI builds/tests for this PR labels Nov 6, 2026
@Alex-Vasile
Alex-Vasile added this pull request to stack #15292 November 6, 2026 17:39
@Alex-Vasile
Alex-Vasile force-pushed the users/alvasile/tl-speedup-04-library-client-require-selection branch from 262e21a to 3c6d28e Compare November 6, 2026 18:24
@therock-pr-bot

therock-pr-bot Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

✅ All Checks Passed — Ready for Review

Check Status Details
📝 PR Description ✅ Pass —
⛔ Forbidden Files ✅ Pass —
🧪 Unit Test ✅ Pass —
🔎 pre-commit ✅ Pass —
🚫 Draft PR 🔜 To Be Enabled —
🚩 Feature Flag 🔜 To Be Enabled —
📊 Code Coverage 🔜 To Be Enabled —
🤖 therock-pr-bot ✅ Pass —

🎉 All checks passed! This PR is ready for review.

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

🙋 Wish to Override Policy?

@therock-pr-bot

therock-pr-bot Bot commented Nov 6, 2026

Copy link
Copy Markdown

🎉 All checks passed! This PR is ready for review.

@Alex-Vasile Alex-Vasile removed NoCI Don't run CI ci:skip Skip all CI builds/tests for this PR labels Nov 6, 2026
…s no solution

With --best-solution the client ran library solution 0 when selection returned nothing, and Tensile ignored the LibraryClient return code, so a library that selects nothing (for example a broken Prediction setup) passed. A new client option --require-selected-solution (passed only on the LibraryClient run) reports and counts such problems, and Tensile now fails on a non-zero LibraryClient exit under ExitOnFails. One line is hand-written (user-approved): SolutionIterator::Default() passes the new argument in base's two-line make_shared<TopSolutionIterator> call; branch 10 (predicate dump opt-in) reflows that call into its final form.
@Alex-Vasile
Alex-Vasile force-pushed the users/alvasile/tl-speedup-04-library-client-require-selection branch from 3c6d28e to 6f5d536 Compare November 6, 2026 18:45
@Alex-Vasile
Alex-Vasile marked this pull request as ready for review November 6, 2026 18:45
@Alex-Vasile
Alex-Vasile requested review from a team as code owners November 6, 2026 18:45

@tony-davis tony-davis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Alex! I think this is an important fix. A LibraryClient step that quietly runs solution 0 when selection comes back empty is exactly the kind of thing that makes a green test mean less than people think. I traced the new path and it looks right to me. With --require-selected-solution, TopSolutionIterator skips the problem, counts it once, and that count reaches main's exit code through MetaRunListener::error(), the same way a validation failure does. Without the option, nothing changes. I also checked that the hw-common job takes the client and the tests from the same installed artifact, so I don't see a lane where an older client would trip over the new option.

The tests are good. NothingSelectedIsAnErrorWithTheOption uses a real MasterSolutionLibrary and would fail if the option check, the count, or the log line went away. test_failed_library_client_run_fails_tensile would fail if the return-code check were dropped.

Things I'd like to see before merge:

  • Most of the affected configs are gfx950. On develop, 12 common configs have a LibraryClient step. 11 are gfx950-only (fused_a2a, the 8 subtile_mxfp8_* configs, and the 2 mxfp8_*_repro configs), and only xfp32.yaml is gfx942. The Test Plan runs only -k xfp32. TheRock's tensilelite-common job runs gfx950 per PR, so I think it's enough to point at that job's result once it's green. I'd add those configs to the Test Plan so a reader knows they're the ones at stake.
  • prediction_bf16 isn't in the tree. The Test Result cites it, but I couldn't find it on develop. Could you say which in-tree config shows the same thing, or note that it was a scratch config?
  • Which lane runs the new gtests? The overlay wants defect-fix regression tests to run in a shared lane. tests/test_categories.yaml defines a standard tier labelled pr, but I couldn't confirm from here that a required check actually runs tensilelite-tests on a PR. (Math CI's coverage-cpp runs ctest, but it doesn't gate.) If you know the lane, a link to its run with SolutionIteratorSelectionTest in it would settle it.

Smaller things:

  • mxfp8_residual_fail_classes_repro.yaml says it fails "only with some probability." The LibraryClient run now gates too, so that config gets two chances to flake per run. Is it stable in CI today?
  • The option does nothing without --best-solution, because only TopSolutionIterator reads it. The help text says so, but I bet a one-line warning would save someone a confusing afternoon.
  • Same note as the earlier layers on the "must be shown to fail" sentence in the Test Plan. I'd say what was shown locally and what is pending.

Suggested replacement for the device paragraph:

Client host code (solution iteration) and the Python test harness; no kernel generation changes. Twelve common configs end with a LibraryClient step: xfp32.yaml on gfx942, and 11 gfx950 configs (comm/gfx950/fused_a2a, eight subtile_mxfp8_*, mxfp8_verify_fail_repro and mxfp8_residual_fail_classes_repro). Each one now fails if the library selects nothing or the client exits non-zero. Before merge, TheRock's tensilelite-common job must pass on gfx942 and gfx950. gfx950 so far has only a local run of an F32 copy of xfp32.yaml.

Thanks!

@codecov

codecov Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

❌ Your project check has failed because the head coverage (70.07%) is below the target coverage (80.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@                                  Coverage Diff                                  @@
##           users/alvasile/tl-speedup-03-codegen-worker-metadata   #15254   +/-   ##
=====================================================================================
  Coverage                                                 78.10%   78.10%           
=====================================================================================
  Files                                                      3007     3007           
  Lines                                                    522273   522270    -3     
  Branches                                                  81515    81515           
=====================================================================================
- Hits                                                     407877   407875    -2     
+ Misses                                                    85449    85448    -1     
  Partials                                                  28947    28947           
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 53.89% <ø> (+<0.01%) ⬆️ Carriedforward from e23155f
TensileLite-Unit 85.08% <ø> (-<0.01%) ⬇️ Carriedforward from e23155f
hipBLAS 90.62% <ø> (ø) Carriedforward from e23155f
hipBLASLt 70.07% <ø> (ø)
hipCUB 82.68% <ø> (ø) Carriedforward from e23155f
hipDNN 87.33% <ø> (ø) Carriedforward from e23155f
hipFFT 42.65% <ø> (ø) Carriedforward from e23155f
hipRAND 76.12% <ø> (ø) Carriedforward from e23155f
hipSOLVER 69.67% <ø> (ø) Carriedforward from e23155f
hipSPARSE 87.03% <ø> (ø) Carriedforward from e23155f
rocALUTION 82.89% <ø> (ø) Carriedforward from e23155f
rocBLAS 69.20% <ø> (ø) Carriedforward from e23155f
rocFFT 46.49% <ø> (ø) Carriedforward from e23155f
rocRAND 57.32% <ø> (ø) Carriedforward from e23155f
rocSOLVER 76.66% <ø> (ø) Carriedforward from e23155f
rocSPARSE 83.66% <ø> (ø) Carriedforward from e23155f
rocSPARSE-unit 79.57% <ø> (ø) Carriedforward from e23155f
rocThrust 93.15% <ø> (ø) Carriedforward from e23155f

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
...blaslt/tensilelite/client/src/SolutionIterator.cpp 5.90% <ø> (+0.01%) ⬆️
.../hipblaslt/tensilelite/tensilelite/ClientWriter.py 75.29% <ø> (-0.04%) ⬇️
...tensilelite/tensilelite/Common/GlobalParameters.py 95.99% <ø> (ø)
...jects/hipblaslt/tensilelite/tensilelite/Tensile.py 83.09% <ø> (-0.04%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants