Skip to content

test(tensilelite): fix stale Stream-K parallel workspace-starved expectations - #11635

Merged
jaopaulolc merged 1 commit into
developfrom
users/jolabega/fix-uso-tests-develop
Sep 3, 2026
Merged

jaopaulolc merged 1 commit into
developfrom
users/jolabega/fix-uso-tests-develop

Conversation

@jaopaulolc

@jaopaulolc jaopaulolc commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

JIRA ID : AIHPBLAS-4633

Motivation

The host unit test StreamKLaunchSummaryTest.Sk3ParallelReductionWorkspaceStarvedFallsBackToTree, in projects/hipblaslt/tensilelite/tests/StreamKLaunchSummary_test.cpp, fails on develop. It is a CPU-only test: it builds a ContractionSolution, asks it which Stream-K launch it would choose for a given problem, and inspects the resulting decision record. No GPU is involved.

A bisect that rebuilt and reran the test at every step identifies 3a558b0d4d4, "feat(hipblaslt): Stream-K extra-iters, grid steering, and parallel admission under USO" (#10941). Its parent f4caa56e6ee passes; 3a558b0d4d4 and every descendant fail.

The test's expectations, not the product code, are what became wrong. #10941 changed which stage of the decision pipeline gets credit for the chosen grid, and the test asserted the older attribution.

The Jenkins job that runs these host unit tests, mci/rocm-libraries/tensilelite-unit-codecov(hipblaslt), is not a required check for merging, so a failure in it does not block a pull request. That is how the regression reached develop unnoticed.

Technical Details

Stream-K spreads a matrix multiply across a fixed grid of workgroups rather than one workgroup per output tile, so several workgroups can contribute partial sums to the same tile and those partials must be combined afterwards. Two combining strategies exist here. Parallel reduction writes partial tiles to a scratch workspace and reduces them in a second pass, so it requires that workspace. Tree reduction combines in place and requires none. The k-split factor F = grid / tiles is how many workgroups share one tile; parallel reduction is only meaningful when F is at least 2.

#10941 introduced streamKReconcileReduction(reduction, skGrid, tiles) in ContractionSolution.cpp. It demotes parallel to tree whenever F drops below 2, and the same commit called it from all three sites that must agree on the reduction:

  • requiredWorkspaceSize(), which callers use to size the workspace allocation;
  • resolveStreamKSettings(), which is what solve() launches;
  • computeStreamKDecisions(), the diagnostic snapshot this test inspects.

In the snapshot the call sits immediately before the guard that decides whether a partials workspace is needed.

The test drives a 256x4096x4096 problem with a 128x128 macro tile on a 256-CU gfx950 device, so tiles is 64, and sets the workspace size to 0. Origami's grid_k_split_aware selection (shared/origami/src/origami/streamk.cpp) already rejects any grid whose partial tiles would not fit the workspace, collapsing the grid from 256 down to tiles = 64. That clamp is long-standing and #10941 did not touch it.

The reconcile therefore sees F = 64 / 64 = 1 and demotes the reduction to tree before the guard runs. The guard reserves only when the reduction is parallel or tiles % grid is non-zero, and neither now holds, so its body never executes. idealWorkspaceBytes stays 0 and workspaceDPFallbackFired stays false, contradicting the old assertions.

Why the fix belongs in the test. The launch is unchanged by #10941: before and after, this configuration launches tree reduction with grid == tiles == 64 and no workspace. Only the attribution moved, and it moved toward the truth, because grid selection produced grid = 64, not the workspace-DP fallback. Reverting or reordering the reconcile would reintroduce a genuine divergence between the workspace query and the launch, since requiredWorkspaceSize() sizes through requiredWorkspaceSizeGsu(grid / tiles), which short-circuits to 0 at a split factor of 1, while computeStreamKDecisions() sizes through partialTileSize(grid), which does not. With the reconcile ahead of both, that triple reaches neither formula and the two cannot disagree about whether a workspace is needed. All production logic is therefore left untouched; the only non-test edit is a comment.

The change has three parts:

  1. Renamed and corrected the failing test to Sk3ParallelWorkspaceStarvedGridCollapsesToTilesAndReconcilesToTree, matching actual behaviour: no workspace-DP fallback, not dpOnly, idealWorkspaceBytes of 0, and changedBy = none / source = none in the printed summary. Assertions that were already correct are kept, including that getSKReduction() still starts from parallel, the tile and grid equalities, and that both workspace sizings return 0.

  2. Added Sk3ParallelFixedGridWorkspaceDpFallbackFires to restore the coverage the rename would otherwise delete. It sets skFixedGrid = 128 (that is, 2 * tiles) with a zero workspace, so F = 2 survives the reconcile and the parallel-side workspace-DP fallback genuinely fires: idealWorkspaceBytes is 8388608 bytes (partialTileSize(128)), the grid moves from a selected 128 to a final 64, and the summary reports changedBy = workspaceDP and source = workspaceDP(runtime). A fixed grid is the only remaining way to reach that branch: on the dynamic-grid path a parallel launch has skGrid = F * tiles > tiles, so tiles % skGrid is always non-zero, and origami applies the same workspace predicate during selection first, meaning parallel only survives selection when the workspace already fits. feat(hipblaslt): Stream-K extra-iters, grid steering, and parallel admission under USO #10941 silently cost that branch its coverage; this test restores it.

  3. Corrected a stale comment on StreamKDecisions::requiredWorkspaceBytes in ContractionSolution.hpp, which documented a query-versus-snapshot divergence (using this same 256x4096x4096 example) that the reconcile made unreachable, plus the same staleness in a neighbouring test comment.

No changelog entry: projects/hipblaslt/CHANGELOG.md is a release-notes file keyed to ROCm versions and records user-facing API and feature changes. Recent test-only commits under projects/hipblaslt/tensilelite/tests/ do not touch it, and this change alters no public behaviour.

Test Plan

Build the tensilelite C++ host-library gtest binary (CMake TENSILELITE_BUILD_TESTING=ON, target tensilelite-tests) and run:

  1. The affected suite on its own: ./tensilelite-tests --gtest_filter=StreamKLaunchSummaryTest.*.
  2. The full binary, ./tensilelite-tests, to confirm no collateral damage.

Both tests read TENSILE_STREAMK_DATA_PARALLEL, which forces data-parallel mode and would make the scenarios vacuous, so that variable (and TENSILE_DB) must be unset; each test asserts this up front. No GPU or device library is required.

Test Result

Both runs pass.

  • StreamKLaunchSummaryTest: 25 of 25 pass, including the renamed test and the new Sk3ParallelFixedGridWorkspaceDpFallbackFires.
  • Full tensilelite-tests binary: 447 tests across 81 suites, 445 passed, 0 failed, 2 skipped. Both skips are pre-existing and unrelated to this change (RangeLibraryTest/RangeLibraryTest.SpecificSizes/0 and FP4ZeroFrequency/MXDataGenFP4Test.ZeroFrequencyWithinBounds/3).

clang-format reports no changes needed on the modified line ranges of both files.

Submission Checklist

Risk level

None. The change touches no production logic. It edits one test file and one comment in ContractionSolution.hpp; no declaration, signature, or executable statement in the header is modified, so no runtime behaviour and no generated kernel can change. The worst case is a test that is itself wrong, which the full-suite run above bounds.

…ctations

StreamKLaunchSummaryTest.Sk3ParallelReductionWorkspaceStarvedFallsBackToTree
has been failing on develop since 3a558b0 ("feat(hipblaslt): Stream-K
extra-iters, grid steering, and parallel admission under USO", #10941). A
bisect that rebuilt and reran the test at every step confirms it: the parent
commit f4caa56 passes, and 3a558b0 and every descendant fail.

#10941 added the helper streamKReconcileReduction(reduction, skGrid, tiles) in
ContractionSolution.cpp. It demotes parallel reduction to tree whenever the
k-split factor skGrid / tiles falls below 2, and the same commit called it from
all three sites that have to agree on the reduction: requiredWorkspaceSize(),
resolveStreamKSettings() (which is what solve() launches), and
computeStreamKDecisions() (the diagnostic snapshot the test inspects). In the
snapshot the call sits immediately before the partials workspace guard.

The test drives a 256x4096x4096 problem with a 128x128 macro tile on a 256-CU
gfx950 device, so tiles is 64, and sets the workspace size to 0. Origami's
grid_k_split_aware selection already collapses the grid from 256 down to
tiles = 64 for a zero workspace; that clamp is long-standing and #10941 did not
touch it. The reconcile therefore sees a split factor of 1 and demotes the
reduction to tree before the guard runs, and the guard only reserves when the
reduction is parallel or tiles % grid is non-zero, so its body never executes.
That is why idealWorkspaceBytes stays 0 and workspaceDPFallbackFired stays
false.

The launch itself is unchanged. Before and after #10941 this configuration
launches tree reduction with grid == tiles == 64 and no workspace. Only the
attribution moved, and it moved toward the truth, because grid selection rather
than the workspace-DP fallback is what produced grid = 64. The test was
asserting the old attribution, so the expectation was stale and the product
logic is deliberately left untouched. Reverting or reordering the reconcile
would reintroduce a real divergence between the workspace query and the launch:
requiredWorkspaceSize() sizes through requiredWorkspaceSizeGsu(grid / tiles),
which short-circuits to 0 at a split factor of 1, while computeStreamKDecisions()
sizes through partialTileSize(grid), which does not.

Changes:

- Rename the test to
  Sk3ParallelWorkspaceStarvedGridCollapsesToTilesAndReconcilesToTree and
  correct its expectations to the behaviour the code has: no workspace-DP
  fallback, not dpOnly, idealWorkspaceBytes of 0, and "changedBy = none" /
  "source = none" in the printed summary. Assertions that were already correct
  are kept.

- Add Sk3ParallelFixedGridWorkspaceDpFallbackFires to restore the coverage the
  rename would otherwise drop. It sets skFixedGrid to 128, which is 2 * tiles,
  with a zero workspace, so the split factor of 2 survives the reconcile and the
  parallel-side workspace-DP fallback genuinely fires: idealWorkspaceBytes is
  8388608, the grid moves from a selected 128 to a final 64, and the summary
  reports "changedBy = workspaceDP". A fixed grid is the only way left to reach
  that branch, because on the dynamic-grid path a parallel launch has
  skGrid = F * tiles > tiles, so tiles % skGrid is always non-zero and origami
  applies the same workspace predicate during selection first.

- Correct a stale comment on StreamKDecisions::requiredWorkspaceBytes, which
  described a query-versus-snapshot divergence that the reconcile made
  unreachable, and the same staleness in a neighbouring test comment.

Verified with the tensilelite host unit tests: StreamKLaunchSummaryTest passes
25 of 25, and the full binary reports 445 passed and 2 pre-existing skips across
447 tests in 81 suites, with no failures.
@therock-pr-bot

therock-pr-bot Bot commented Sep 2, 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 Sep 2, 2026

Copy link
Copy Markdown

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

@jaopaulolc jaopaulolc added the rocm:gemm algos Label to identify PRs of the GEMM Algorithms team. label Sep 2, 2026
@codecov

codecov Bot commented Sep 2, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

❌ Your project status has failed because the head coverage (38.61%) 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             @@
##           develop   #11635      +/-   ##
===========================================
- Coverage    63.78%   63.75%   -0.03%     
===========================================
  Files         2825     2825              
  Lines       469111   469773     +662     
  Branches     69265    69386     +121     
===========================================
+ Hits        299192   299457     +265     
- Misses      148872   149256     +384     
- Partials     21047    21060      +13     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 38.61% <ø> (-0.43%) ⬇️
TensileLite-Unit 75.61% <ø> (+0.08%) ⬆️
hipBLAS 90.62% <ø> (ø) Carriedforward from c837e3e
hipBLASLt 35.22% <ø> (-<0.01%) ⬇️
hipCUB 82.68% <ø> (ø) Carriedforward from c837e3e
hipDNN 86.95% <ø> (ø) Carriedforward from c837e3e
hipFFT 43.25% <ø> (ø) Carriedforward from c837e3e
hipRAND 76.12% <ø> (ø) Carriedforward from c837e3e
hipSOLVER 68.92% <ø> (ø) Carriedforward from c837e3e
hipSPARSE 86.99% <ø> (ø) Carriedforward from c837e3e
rocBLAS 0.28% <ø> (ø) Carriedforward from c837e3e
rocFFT 45.91% <ø> (ø) Carriedforward from c837e3e
rocRAND 56.91% <ø> (ø) Carriedforward from c837e3e
rocSOLVER 76.83% <ø> (ø) Carriedforward from c837e3e
rocSPARSE 74.61% <ø> (ø) Carriedforward from c837e3e
rocThrust 91.60% <ø> (ø) Carriedforward from c837e3e

*This pull request uses carry forward flags. Click here to find out more.
see 8 files with indirect coverage changes

🚀 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.

@jaopaulolc
jaopaulolc enabled auto-merge (squash) September 3, 2026 01:51
@jaopaulolc
jaopaulolc merged commit f8d041b into develop Sep 3, 2026
275 of 296 checks passed
@jaopaulolc
jaopaulolc deleted the users/jolabega/fix-uso-tests-develop branch September 3, 2026 02:57
@assistant-librarian

Copy link
Copy Markdown
Contributor

TheRock Submodule Bump Activity

Newest first

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