Skip to content

fix(hipblaslt): correct the Stream-K split predicate for uniform summation order - #10896

Merged
jaopaulolc merged 4 commits into
users/jolabega/uniform-summation-order-custom-kernelsfrom
users/jolabega/streamk-uniform-summation-predicate
Aug 20, 2026
Merged

jaopaulolc merged 4 commits into
users/jolabega/uniform-summation-order-custom-kernelsfrom
users/jolabega/streamk-uniform-summation-predicate

Conversation

@jaopaulolc

@jaopaulolc jaopaulolc commented Aug 17, 2026 •

Copy link
Copy Markdown
Contributor

Folded into #10765. Not part of the live USO stack (#10765 → #10941).

Original work: correct the Stream-K split predicate under uniform summation order (AIHPBLAS-4254). Landed on the #10765 branch; do not restack later PRs on this one.

@therock-pr-bot

therock-pr-bot Bot commented Aug 17, 2026 •

Copy link
Copy Markdown

✅ All Policy Checks Passed

Check Status Details
📝 PR Description ✅ Pass —
⛔ Forbidden Files ✅ Pass —
🧪 Unit Test ✅ Pass —
🚫 Draft PR 🔜 To Be Enabled —
🚩 Feature Flag 🔜 To Be Enabled —
📊 Code Coverage 🔜 To Be Enabled —

🎉 All policy checks passed!

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

🙋 Wish to Override Policy?

@codecov

codecov Bot commented Aug 17, 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 (35.19%) 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/jolabega/uniform-summation-order-custom-kernels   #10896   +/-   ##
======================================================================================
  Coverage                                                  69.82%   69.82%           
======================================================================================
  Files                                                       2783     2783           
  Lines                                                     458625   458625           
  Branches                                                   67643    67643           
======================================================================================
  Hits                                                      320221   320221           
  Misses                                                    115160   115160           
  Partials                                                   23244    23244           
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 38.19% <ø> (ø) Carriedforward from 4560ee1
TensileLite-Unit 76.58% <ø> (ø) Carriedforward from 4560ee1
hipBLAS 90.62% <ø> (ø) Carriedforward from 4560ee1
hipBLASLt 35.19% <ø> (ø)
hipCUB 82.68% <ø> (ø) Carriedforward from 4560ee1
hipDNN 86.81% <ø> (ø) Carriedforward from 4560ee1
hipFFT 43.60% <ø> (ø) Carriedforward from 4560ee1
hipRAND 76.12% <ø> (ø) Carriedforward from 4560ee1
hipSOLVER 69.03% <ø> (ø) Carriedforward from 4560ee1
hipSPARSE 86.99% <ø> (ø) Carriedforward from 4560ee1
rocBLAS 48.26% <ø> (ø) Carriedforward from 4560ee1
rocFFT 53.72% <ø> (ø) Carriedforward from 4560ee1
rocRAND 57.05% <ø> (ø) Carriedforward from 4560ee1
rocSOLVER 77.25% <ø> (ø) Carriedforward from 4560ee1
rocSPARSE 74.59% <ø> (ø) Carriedforward from 4560ee1
rocThrust 91.60% <ø> (ø) Carriedforward from 4560ee1

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

Files with missing lines Coverage Δ
.../hipblaslt/tensilelite/src/ContractionSolution.cpp 7.88% <ø> (ø)
🚀 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 added the rocm:gemm algos Label to identify PRs of the GEMM Algorithms team. label Aug 18, 2026
@jaopaulolc
jaopaulolc marked this pull request as ready for review August 18, 2026 19:46
@jaopaulolc
jaopaulolc requested a review from a team as a code owner August 18, 2026 19:46
@jaopaulolc
jaopaulolc force-pushed the users/jolabega/streamk-uniform-summation-predicate branch from 7f39d17 to 81dcb23 Compare August 18, 2026 19:51
@therock-pr-bot

Copy link
Copy Markdown

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

@jaopaulolc
jaopaulolc force-pushed the users/jolabega/streamk-uniform-summation-predicate branch from 81dcb23 to 85452f0 Compare August 19, 2026 16:48
@jaopaulolc
jaopaulolc requested review from a team as code owners August 19, 2026 20:35
@jaopaulolc
jaopaulolc force-pushed the users/jolabega/streamk-uniform-summation-predicate branch from 85452f0 to 5d73a5f Compare August 19, 2026 20:37
@jaopaulolc
jaopaulolc force-pushed the users/jolabega/streamk-uniform-summation-predicate branch from 5d73a5f to d1b83c1 Compare August 19, 2026 20:47
@jaopaulolc
jaopaulolc force-pushed the users/jolabega/streamk-uniform-summation-predicate branch from d1b83c1 to 456fa1a Compare August 20, 2026 15:15
@jaopaulolc
jaopaulolc force-pushed the users/jolabega/streamk-uniform-summation-predicate branch from 456fa1a to 86ac929 Compare August 20, 2026 16:06
@jaopaulolc
jaopaulolc force-pushed the users/jolabega/streamk-uniform-summation-predicate branch from 86ac929 to 4805ed6 Compare August 20, 2026 17:37
The StreamK=3 and StreamK=5-static kernel-arg packers each wrote out the
same skTiles/SKItersPerWG derivation, and CuCount_test.cpp carried a
third transcription of it. checkUniformSummationOrder() needs the same
numbers to reason about the split the kernel actually performs, which
would have made a fourth copy.

Introduce streamKStaticSplit() as the single source of truth, plus
streamKStaticSplitRowUniform() for the row-uniformity condition over its
result, and call the former from all three existing sites. No behaviour
change: the helper reproduces the existing arithmetic including the
skFullTiles term and the clamp to the tile count.
…he tiles

The uniform-summation-order gate refused any Stream-K launch unless the
resolved grid divided the tile count. That is sufficient but not
necessary. Row uniformity requires only that every output tile be folded
from the same ordered list of chunk lengths, which also holds when the
grid is a multiple of the tile count and every tile is cut into equal
chunks: there is no data-parallel region, so no tile is left whole, and
the cut offsets are identical for all of them.

Test the property directly, over the split streamKStaticSplit() packs:

  skTiles == 0                                    force-DP-only
  extraIters == 0 && skItersPerWG != 0
    && (skItersPerWG == itersPerTile              every chunk a whole tile
        || (skTiles == tiles
            && itersPerTile % skItersPerWG == 0)) equal cuts, no DP region

The first clause preserves today's acceptance of force-DP-only. The
skItersPerWG != 0 term is load-bearing: the grouped-GEMM callers pass a
default-constructed StreamKSettings, where the modulo would otherwise be
undefined.

Scope it to the packing it describes. StreamK=4 and StreamK=5-dynamic
pack a different ABI and keep the divisibility test, which is redundant
for them because they are separately held to skTiles == 0. The reduction
strategy is now checked before the split arithmetic, since the
arithmetic models the tree packing and the parallel path reinterprets
the same arguments.

This strictly widens acceptance; nothing previously honoured is now
refused. It recovers roughly 10% of the tuned gfx950 Stream-K entries
with no device-side change.

JIRA ID : AIHPBLAS-4252
Four configurations are expressible but were never audited against the
uniform-summation-order guarantee. None of them occurs in the shipped
tuned logic, so no dispatch changes outcome today; each closes a hole a
future kernel or logic file could walk into.

- UseInitialStridesCD, and packed C0/C1 index sets. Both turn off the
  coordinate-agnostic store addressing (optSingleColVgpr /
  optSharedColVgpr) that keeps an out-of-range lane from influencing an
  in-range one on the partials path.
- WaveSplitK, as WorkGroup[2] > 1 with LocalSplitU <= 1. Its
  redundant-lane mask covers the D/TD stores, not the workspace partials
  store. Gated inside the Stream-K scope on purpose: every shipped
  WaveSplitK solution has StreamK=0, and refusing those would buy
  nothing. LocalSplitU > 1 and UseSubtileImpl are deliberately untouched.
- MX with DepthU not a multiple of 256. The gfx950 HostPreSwizzle scale
  layout packs 32 rows x 8 MX blocks into a 256-byte granule addressed
  lane-linearly, and Stream-K shifts the scale SRD by a scalar
  StreamKLocalStart*DepthU; a shift inside a granule permutes rows
  against K-blocks. Solution validation already forces this for MX fp4
  but admits DepthU=128 for MX fp8. Detected from
  problemType.mxBlock{A,B}, never from a kernel-name substring: the _MX_
  token in several kernel names is F32XdlMathOp=XFloat32, and those f32
  kernels ship StreamK=3 with DepthU=16.

Both the throwing gate and the selection-time filter now consult one
shared implementation, so they cannot drift; the filter drops such
solutions quietly instead of failing the launch.

JIRA ID : AIHPBLAS-4255
…tions

Three new suites, 27 cases, alongside the 5 pre-existing ones:

- RowUniformity/RowUniformityStreamKSplit_pre_checkin, 11 cases. A
  white-box table over streamKStaticSplit() and
  streamKStaticSplitRowUniform(), asserting the packed skTiles,
  SKItersPerWG and extraIters as well as the verdict, so it pins the
  packing mirror and not only the predicate. Covers both newly admitted
  cases, both previously admitted ones, four genuinely non-uniform
  splits, force-DP-only, skFullTiles=0 and a zero grid.
- RowUniformityStreamKRejection_pre_checkin, 9 cases. One per rejection
  against a synthesised solution, plus the over-rejection guards:
  LocalSplitU > 1 and WaveSplitK without Stream-K must still be
  admitted, and non-MX DepthU=128 must be admitted, which is the
  regression test for the f32 kernels whose names carry an _MX_ token.
- RowUniformityClauseTwo_pre_checkin, 2 cases. M=4096 N=32 K=10240 bf16
  with HIPBLASLT_MATMUL_DESC_SM_COUNT_TARGET=80 and with it unset. Each
  discovers the resolution per candidate rather than pinning solution
  indices, asserts the grid is a multiple of the tile count and not
  equal to it, runs the launch and checks D is bitwise row-uniform, and
  requires a parallel-reduction resolution to still be refused. Skips
  with a diagnostic naming the shape and the counts if the library
  reaches neither regime.

The harness gains a per-problem element type and CU budget so the bf16
shape above is reachable. It sets max_workspace_bytes explicitly: the
preference defaults to 0 and clamps the request, which would collapse the
grid back to the tile count and make the new coverage pass vacuously.
@jaopaulolc
jaopaulolc force-pushed the users/jolabega/streamk-uniform-summation-predicate branch from 4805ed6 to 6311476 Compare August 20, 2026 22:53
@jaopaulolc
jaopaulolc merged commit 6311476 into develop Aug 20, 2026
24 of 26 checks passed
@jaopaulolc
jaopaulolc deleted the users/jolabega/streamk-uniform-summation-predicate branch August 20, 2026 22:57
jaopaulolc added a commit that referenced this pull request Aug 21, 2026
… output (#10722)

JIRA ID : AIHPBLAS-4252, AIHPBLAS-4255

## Motivation

Identical rows of `A` can produce last-bit differences across rows of
`D` when tiles accumulate `K` in different orders. This PR adds an
opt-in hipBLASLt control for **row uniformity within one run** (not
run-to-run determinism). AIHPBLAS-4255 requires StaggerU to be forced
off when the mode is on.

## Changes

**API**
- Descriptor attribute
`HIPBLASLT_MATMUL_DESC_UNIFORM_SUMMATION_ORDER_EXT` (105, `int32_t`):
`0` off (default), `1` on; other values →
`HIPBLAS_STATUS_INVALID_VALUE`.
- C++: `GemmPreference::setUniformSummationOrder` /
`getUniformSummationOrder`.
- Bench: `--uniform_summation_order off|on`.

**Guarantee**
If the mode is on and `hipblasLtMatmul` succeeds, and every row of `A`
is the same vector, then every row of `D` is bitwise identical within
that run.

**Enforcement** (`ContractionSolution.cpp`)
1. `calculateAutoStaggerU` clamps StaggerU (and related stagger fields)
to 0 after env overrides and the prediction-cache write.
2. `checkUniformSummationOrder` fail-closes before dispatch
(`UniformSummationOrderError` → `HIPBLAS_STATUS_INVALID_VALUE`).
3. `uniformSummationOrderSupported` drops solutions that are statically
unsafe during selection; the launch check remains authoritative.

**This PR refuses custom kernels** (`customKernelName` non-empty). Docs,
sample, and custom-kernel admission are later stack PRs.

Also masks the stagger-mapping bitfield when packing kernel args.
Explicit solution-index overrides bypass selection filtering; with the
mode on, that path logs a warning instead of hard-rejecting.

Bottom of the coherence stack (#10722 → #10765 → #10896 → #10941 →
#10942).

## Test plan / result

- `row_uniformity_gtest.cpp`: identical `A` rows; bitwise row compares
of `D`; `ClampRepaired_*` selects by Tensile metadata.
- Aux / `GemmPreference` gtests for default, round-trip, and invalid
values.
- Suites pass on gfx950 (MI355X).

## Risk

Low–medium. Opt-in, off by default, fail-closed. Main shared-path risk
is descriptor plumbing (covered by attribute tests).
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.

1 participant