Repository navigation
fix(hip-kernel-provider): ASM SDPA backward declines layouts and dims its kernels address wrongly - #14684
Open
brockhargreaves-amd wants to merge 6 commits into
Open
fix(hip-kernel-provider): ASM SDPA backward declines layouts and dims its kernels address wrongly#14684brockhargreaves-amd wants to merge 6 commits into
brockhargreaves-amd wants to merge 6 commits into
Conversation
…youts SdpaBwdPlanBuilder::isApplicable accepted tensor layouts that the gfx942 backward kernels address wrongly. On gfx942 (MI300X) each one gave silent wrong gradients instead of a decline. The evidence comes from two sources. One is GPU runs of the plugin from a CI build of #14312, which accepts all of these layouts. The other is disassembly of the dispatched .co files. Q/K/V/O/dO/dQ/dK/dV strides. The ODO, DQDKDV and DQ_CONVERT argument blocks carry only batch, head and sequence byte strides. isApplicable now declines: - A head-dim (innermost) stride other than 1. The kernels read it as 1: a stride-2 Q gave Inf dK/dV, and a stride-2 dQ left elements unwritten. - A sequence stride below D, also on a length-1 sequence axis. Each buffer ends S * seq stride bytes into its (batch, head) slice, so the end of the last row reads as 0, and writes there are dropped. A seq stride of 1 on a length-1 axis gave wrong gradients for each of the eight tensors. Seq strides of D/2 and 2 did the same for Q, K, V and dO. - An odd stride on an axis whose offset DQDKDV puts in its 4-byte record index (byte offset >> 2). That is the sequence axis of Q, K, V, dO, dK and dV, and the head axis of dK and dV. Rows that start 2 bytes into a dword are read or written one element early. A seq stride of D+1 failed on each of the six. A dO row pitch of D+1 gave 47-97 % wrong dQ, dK and dV. Odd strides on the other axes are addressed correctly and stay accepted: - batch strides, which are added to the 64-bit buffer base; - head strides of Q, K, V, O, dO and dQ; - seq strides of O and dQ, which ODO and DQ_CONVERT address by byte offset. The causal kernels also add the dK/dV head offset to the base, but the check does not depend on the mask. Stats (LSE). All 28 dispatched batch-mode DQDKDV kernels compute the LSE and D offset as ((b * H_q + h) * S_q + s) * 4 and never load Hs_lsed. A stats head stride padded to S_q + 64 gave wrong gradients that changed between runs with identical inputs. A padded batch stride, a seq stride of 2 and [B, S_q, H] storage also gave wrong gradients. isApplicable now requires stats dims [B, H_q, S_q] or [B, H_q, S_q, 1] matching Q, with packed strides on every axis longer than 1. buildPlan sets the LSE/D strides from Q's dims, so the stride of a size-1 stats axis no longer reaches a kernel argument or the 32-bit stride check. These layouts stay accepted, all GPU-verified on gfx942: BSHD on all tensors, dO strides that differ from O, seq strides D+2 and D+8, B and H above 1, hd192, fp16, causal and sliding-window masks, BR causal with Sq above Skv, Sq in {1, 16, 17}, and tails. New tests in TestSdpaBwdPlanBuilder.cpp (gfx942 only, like the other isApplicable tests). Each decline arm has a case that only it declines, and each exemption has an accept case: - IsApplicableAcceptsAddressableLayouts - IsApplicableRejectsNonUnitHeadDimStride - IsApplicableRejectsMisalignedOrShortRows - IsApplicableRejectsNonPackedStats Checked on gfx942 (MI300X). This commit's plugin replaced the one in a CI build of #14312, and results were compared with the CPU reference: - Each declined layout above failed with the old plugin, which accepts it, and now declines. Each layout named above as addressed correctly passed with the old plugin and still passes. The probes cover hd128 and hd192, bf16 and fp16, and the no-mask, causal and sliding-window kernels. - The shipped bf16 tolerance hides some short-row errors, so those were also compared at atol=1e-9 with packed controls. Their error was 7-34x the controls'; for Q, the dQ error sits in the cut-off last row. - The develop quick/standard SdpaBackward bundles and the CI Sdpa bundles give the same results as before. - The unit tests pass. Each of 29 mutants that removes or widens one arm of these checks makes one of the new tests fail. Rebased onto develop 98b504d, after #14075, whose range gate now runs first in isApplicable. The GPU results above are from develop 61c2675. On the new base, the four ALMIOPEN-3035 ASM SDPA fix branches (backward layouts, attention scale, a16 accumulator, forward layouts) were built and run together: - hip_kernel_provider_tests: 912 pass and 7 skip on gfx942 (MI325X), 886 pass and 33 skip on gfx950 (MI355X); none fail. - hip_kernel_provider_integration_tests: none fail on either. - develop's SDPA bundles on ASM_SDPA_ENGINE, run like the CI lane (claims enforced): 62 pass and 56 skip on gfx942, 15 pass and 103 skip on gfx950, and no support claim fails. A host-side run of the real isApplicable over these bundles finds no outcome change from develop. - #14622's SdpaBackward bundles (138218c) with its temporary [[test_skips]] removed: 275 pass and 225 skip on gfx942, none fail, and no support claim fails. This branch's checks decline the 20 cases behind the DEF-01, DEF-02, DEF-04, DEF-05/H61, prbu01, prbu03 and prbu13 skips, and no other case (host-checked for this branch alone). - clang-tidy 20 and clang-format 18 are clean on the changed files. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…r dims Every backward kernel takes B, H, S_q, S_kv and D once, from Q, K and V, and addresses all eight tensors with them. isApplicable compared only K's head count with Q's. The frontend lets V have fewer heads than K, because it checks only that both divide H_q. DQDKDV then reads V and writes dV for every Q head, past the last head of both. On gfx942 (MI300X), with H_q = H_k = 4 and H_v = 2 or 1, 51 % of dQ and dK and 87-92 % of dV were wrong. The other dims were not compared with Q's and K's either: the frontend checks only dO against O. isApplicable now requires O, dO and dQ to have Q's dims, V, dK and dV to have K's dims, and K's batch to equal Q's. The check runs after the GQA, asymmetric head-dim and head-dim checks, so those keep their own decline reasons. New test IsApplicableRejectsMismatchedTensorDims covers both of these graphs, plus one case per check that only that check declines. Checked on gfx942 (MI300X), with this commit's plugin in a CI build of #14312. Both of these graphs failed with the old plugin and now decline, and no other probe or bundle case changes from the previous commit. Of the 182 cases of an earlier gfx942 sweep, only the 4 head-dim stride and stats layout failures change: they now decline. Each of 7 mutants that removes one of these checks makes the new test fail. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
SdpaBwdPlanBuilder::isApplicable accepted dQ, dK and dV with a zero batch or head stride on an axis longer than 1. Such a graph has no well-defined result in general, because the slices that share memory hold different gradients. No layer rejects it: the frontend and backend check only that dims are positive and that strides are set, and isApplicable's stride checks pass a zero stride on these axes, which fits in 32 bits and is even. Each kernel launches its own workgroups for each (batch, head) slice (grid y and z are head and batch). DQDKDV writes dK and dV, and DQ_CONVERT (A32 path) writes dQ, with plain stores at batch * batch stride + head * head stride. With a zero stride several slices share memory, so each element ends up holding whichever slice was stored last. On gfx942 (MI300X), B=2, H=2 (H=3 where noted), S=256, bf16, three runs in each of two GPU jobs: - dK and dV with batch stride 0: each memory location held one batch's gradient, so half of the dK and dV elements differed from the packed run, and 17k-54k of them changed between runs with identical inputs. - dQ with batch stride 0: the same, with 33k-65k changing between runs. - dK and dV with head stride 0, H=3: two thirds differed from the packed run, and 23k-147k changed between runs. - dQ with head stride 0, H=3: two thirds differed from the packed run, and 64k-148k changed between runs. There was no NaN or Inf and no write into the guard regions around each buffer, and dQ was unaffected when only dK and dV aliased. isApplicable now declines dQ, dK and dV with a zero batch or head stride on an axis longer than 1. The sequence and head-dim axes are already covered: their strides must be at least D and exactly 1. These stay accepted: - Zero strides on the inputs Q, K, V, O and dO (broadcasts), which the kernels just re-read. On gfx942 these gave gradients that matched the CPU reference and were bitwise equal to the packed runs, in each of three runs: K and V together, or dO alone, with a zero batch stride, head stride or both; Q, O or V alone with a zero batch or head stride; Q and O together with a zero head stride; and all five inputs with a zero batch stride. The K and V batch broadcast also passed with fp16, with a top-left causal mask, and at S=64. - A zero stride on a length-1 axis, on outputs too, since it only ever multiplies index 0. On gfx942, dQ, dK and dV with batch stride 0 at B=1, or head stride 0 at H=1, passed the same way. Nonzero strides that make an output overlap itself are not checked. On gfx942, dK and dV with equal batch and head strides (B=H=2) are still accepted. They differed from the packed run in a quarter of their elements, 6% of dK and 17% of dV were outside the CPU reference's bf16 tolerance, and the result was not always the same from run to run. The zero stride is checked on its own because it is how a broadcast is written, so an output gets one when it is given the strides of a broadcast input; other overlap has to be built by hand. PyTorch's check for tensors that an operation writes to also rejects only a zero stride on an axis longer than 1. A general rule (sort the axes by stride and require each stride to cover the span of the axes inside it) is left for a follow-up, in this plugin or in hipDNN graph validation, where every engine would get it. It would also need the range tests that #14075 added to switch to non-overlapping strides: they give dQ, dK and dV overlapping strides, such as equal batch and head strides with H=8, and expect them to be accepted. New test IsApplicableRejectsZeroStrideOutputs has one case per output tensor and axis, and covers the four layouts that failed on gfx942. IsApplicableAcceptsAddressableLayouts gains the broadcast inputs and the zero strides on length-1 output axes. Checked on gfx942 (MI300X) with a standalone hipDNN probe that drives ASM_SDPA_ENGINE on its own buffers, because the bundle harness's test tensors reject zero strides. It compares dQ, dK and dV with a float64 CPU reference and with the same data stored packed, three runs per case. - The develop plugin accepts every layout above. With this commit's plugin the four failing layouts decline, every broadcast and length-1 case above still passes bitwise, and the forward cases give the same results as with the develop plugin. - The unit and integration tests pass. Each of 14 mutants that removes or widens one arm of the check (dropping a length-1 exemption, or treating an input as an output) makes one of the two tests fail. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
IsApplicableBoundsTheTsProductByTheResolvedTileSize (added by #14075) probes K sequence strides at and one past the Ts limit. With the gfx942 bf16 hd128 tile (ts = 192) the past-limit stride is odd, and isApplicable now also declines an odd stride on K's sequence axis and dK's head axis, because DQDKDV indexes them in 4-byte records. The test still passed with the Ts guard deleted, so it no longer tested the guard. The at-limit stride would also fail the parity check for a tile size that makes the limit odd. Both probes are now the nearest even strides on each side of the limit, so the Ts guard is the only check that separates them. Deleting the guard makes the test fail again. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 29, 2026
✅ All Checks Passed — Ready for Review
📖 Need help? See the Policy FAQ for details on every check and how to fix failures. |
|
🎉 All checks passed! This PR is ready for review. |
1 task
…n-packed layouts Review follow-up for the backward decline series. - IntegrationGpuSdpaBackward: add B=2, H=2 cases (no mask and top-left causal), so the LSE/D strides buildPlan derives from Q's dims are exercised with more than one batch and head. Every earlier case was B=1, H=1, where swapping the two derived values left every kernel argument unchanged. Add the same two cases with the non-packed layouts isApplicable accepts: Q, K, V and dO stored [B, S, H, D], O and dQ rows padded to D+1. - TestSdpaBwdPlanBuilder: probe each decline at more than one value (a head-dim stride of 0, a sequence stride of 0 with S=256, a 128-element row stride at D=192 on each output-side tensor), add sequence-length and head-dim mismatches to the dims test, and decline a dK with 5 strides or rank-3 dims. Make the accept test's header match its cases and name the device cases above, and drop an undefined test-plan ID from a comment. - Comments: buffer bounds are S * seq stride elements, not bytes; the sequence-stride rule is conservative for Q, K and V at D=192; the LSE/D strides are derived from Q's dims, not taken from the stats tensor. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… wording The accept test's header said "any stride on a length-1 axis", but with S=1 a sequence stride below D is still declined, and the byte-stride gate declines a negative or oversized stride on any axis. Say what is accepted: odd or zero batch and head strides on a length-1 axis, and an odd row stride of at least D with S=1. Comments only. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
brockhargreaves-amd
marked this pull request as ready for review
October 30, 2026 19:26
15 of 16 tasks
brockhargreaves-amd
added a commit
that referenced
this pull request
Nov 5, 2026
…rated bundles (#14622) ## Summary This PR adds the SDPA backward test plan required by RFC 0022 (Per-Op Test Plans, merged in #13937). It also adds a generator that writes the SdpaBackward bundles from the plan, and the bundles it writes. The 16 inherited SdpaBackward cases (all B = H = 1, packed BHSD, fixed scale) are replaced by 503 generated cases in four levels. Each case carries a purpose and traces to the plan items it covers. > Written with AI assistance (Claude Code). The plan follows the merged RFC 0022; it records one remaining deviation (DV-4) for reviewers to approve. JIRA ID : ALMIOPEN-2894 ## Risk Assessment Risk 2 of 5. The PR changes test data, test tooling, test configuration and documentation only; no library or provider code changes. The changes that reach beyond the SdpaBackward bundles: - `support_matrix_units.collect_sweep_units()` leaves out cases whose `metadata.purpose` is `probe`, as RFC 0022 §9 requires. Today only SdpaBackward cases carry a `purpose`, so other ops' matrices are unchanged. The committed `SUPPORT_MATRIX_OVERVIEW.md` is re-rendered. - `ASM_SDPA_ENGINE.toml`: two dtype-only SdpaBackward tolerance rows are replaced by 12 generated rows (seven tolerance classes), plus temporary skips for the open engine defects, each naming its ticket. - `ASM_SDPA_ENGINE_test_categories_integration.yaml`: six rejection probes that ASM_SDPA_ENGINE wrongly accepts are quarantined with their tickets (RFC 0022 §6). Both files affect the ASM lane only. - #14358's eight PyTorch golden cases move, unchanged, from `quick/SdpaBackward/{Default,AdditiveMask}/` to `quick/SdpaBackward/Golden/{Default,AdditiveMask}/`, so the generator owns the `Default` sweeps. They keep their fp16 tolerance row. `bhsd/` and the `*_fwd_pair` bundles are untouched. The main risk is CI noise from new cases. Every level has been run on gfx942 and gfx950 with no failure (see Testing Checklist). ## ASIC Coverage The bundles run in every provider lane whose tier YAML matches `*Sdpa*`. Only `ASM_SDPA_ENGINE` accepts SdpaBackward graphs today, and only on gfx942: its backward plan builder declines every other device ("Device string does not match gfx942"). Claims are harvested for gfx942 only. PR CI tests gfx942. On gfx950 every generated backward case is declined, so a gfx950 run only shows that nothing fails; one is recorded below. PR CI on gfx942 is sufficient. ## Testing Summary - **Generator tests** (`hipdnn_sdpa_bwd_bundle_generator_python_tests`, label `quick`, 19 tests). They fail when the checked-in sweeps or the TOML block drift from the generator. They also check legality, all-pairs coverage up to nightly, the per-case ceilings and cumulative budgets of each level, two-way traceability between plan items and cases, that every TOML skip still matches a written case, and that the tier-YAML quarantine holds only rejection probes. - **`generate_sdpa_bwd_bundles.py --dry-run --report`.** Reports counts, budgets, the all-pairs proof, legality, and each declared-but-gated case with its gate. - **Claims run** (2026-10-26, MI300X, gfx942). All generated bundles ran on `ASM_SDPA_ENGINE`, configured like CI. `harvest_support_claims.py` turned the passing cases into the 272 claims. Every claimed case passes its tolerance class with a margin of at least 2.4 (median 4.2). - **Measured run, every level on GPU** (2026-11-04, plan §4.5). `hipdnn_integration_tests` ran on `ASM_SDPA_ENGINE` configured like the CI lane: `--test-engine` (claims enforced), the PR's `ASM_SDPA_ENGINE.toml`, the tier YAML's quarantine as a GTest filter, device input fill and the GPU reference as oracle. It ran all four levels, on a fresh MI300X (gfx942) and an MI355X (gfx950) node, built from this branch. The bundles, TOML and YAML are identical to `6e014ad50e0`. - **PR CI** runs the quick and standard levels on gfx942. ## Testing Checklist - [x] Generator tests - CTest `hipdnn_sdpa_bwd_bundle_generator_python_tests` - 19 of 19 - Status: Passed - [x] Plan report - `python3 reference-data-scripts/generate_sdpa_bwd_bundles.py --dry-run --report` - 503 written, 77 gated, 0 legality violations, all-pairs 669 of 669 - Status: Passed - [x] Bundle and support-matrix checks - `verify_support_claims.py`, `render_support_matrix.py --output -`, `feature_matrix.py --check`; the bundle, claim, render and support-feature pytest suites - Status: Passed (`verify_golden_bundles.py` reports no SdpaBackward error; its 322 errors in other ops' bundles are on develop too) - [x] pre-commit on the changed files - Status: Passed - [x] Claims run - `hipdnn_integration_tests`, `ASM_SDPA_ENGINE`, MI300X (gfx942), 2026-10-26 - Status: Passed - [x] Measured run, gfx942 - `hipdnn_integration_tests --test-engine ASM_SDPA_ENGINE --test-config ASM_SDPA_ENGINE.toml '--gtest_filter=*SdpaBackward*-<the tier YAML quarantine>'` - MI300X, Slurm job 68275259 - Status: Passed. 553 tests in 43.3 s, 0 failed, no claim broken: - 289 executed and passed against the GPU reference, and 15 expected rejections rejected; - 226 declined by ASM, and 23 hit the DEF skips; - per level: quick 2.4 s, PR 2.8 s, nightly 16.5 s, full 21.4 s. - [x] Quarantine check, gfx942 - the six quarantined cases run alone - Status: all six fail as expected ("Engine ASM_SDPA_ENGINE accepted expected-rejection bundle"), which shows the quarantine is needed. - [x] Every level, gfx950 - same command - MI355X, Slurm job 68275260 - Status: Passed. 0 failed: ASM declines every backward graph on gfx950, and the rejection probes, quarantined ones included, are correctly rejected. - [x] The other SDPA bundles, same lane - `--gtest_filter=*Sdpa*:-*SdpaBackward*` - Status: Passed. gfx942: 47 passed, 84 skipped. gfx950: 16 passed, 115 skipped. 0 failed on either. - [ ] PR CI on gfx942 - TheRock multi-arch CI - Status: Pending on `6e014ad50e0`. The 2026-11-02 run failed one case, `prbr01`, which is now gated. Later runs failed only on the hipCCL configure break from #14976, which develop reverted in #15089 (merged into this branch). ## Technical Changes ### What this adds - **The plan:** `dnn-providers/integration-tests/docs/test-plans/sdpa-bwd.md`. It follows the RFC 0022 template: the operation, the feature inventory, the shape catalog, building the sweep (levels, budgets, probes, regressions, trade-off register), the golden reference, pass criteria, and exhaustive mode. - **The generator:** `reference-data-scripts/sdpa_bwd_plan.py` holds the declarations: axes, legality, the shape catalog, level rules and the cost model, one record per case. `generate_sdpa_bwd_bundles.py` writes the sweeps, the support-claim files and the engine-TOML tolerance block from them. Nobody edits the bundles by hand. RFC 0022 open question 1 cites this module as the per-op Python option. - **The bundles:** 503 written cases, spread across the levels: | Level | Directory | Cases | |---|---|---| | quick | `quick/` | 56 | | PR | `standard/` | 152 | | nightly | `comprehensive/` | 220 | | full | `full/` | 75 | - Each case carries `purpose` (`claim`, `probe` or `regression`) and its plan items. - 77 more cases are declared but not written yet, each waiting on a named gate: an oracle extension, a harness feature or golden data. - One of the 77 is PRB-R01 (`dropout_probability = 0`). Since #14358 the references decline any graph that sets `dropout_probability`, so it waits on ALMIOPEN-3149 or ALMIOPEN-3150. - **Levels:** the cost model assigns each case to the lowest level whose per-case limits it fits: | Level | Per-case time | Per-case bytes | Cumulative budget | |---|---|---|---| | quick | 1.5 s | 4 MiB | 20 s | | PR | 5 s | 16 MiB | 120 s | | nightly | 75 s | 64 MiB | 480 s | | full | 300 s | no limit | 1,800 s | Each cumulative budget covers that level and every level below it, and keeps 5 % in reserve. The budgets come from a CPU-reference cost model; with the GPU reference, the measured run above is far below them. The ASM lane YAML picks the cases up by GTest prefix (`quick_*Sdpa*`, `standard_*Sdpa*` and so on), and each level also runs every level below it. - **Rejection probes** (21) carry `metadata.expected_rejection` (#14346): the harness never executes them, and an engine that accepts one fails the lane. PRB-M02 and PRB-M02f (`right_bound = -2`) are not written, because the frontend rejects them since #14358; `TestSdpaBwdNode.PreValidateChecksDiagonalBandBounds` covers that rule. - **dBias:** the five dBias probes and the live GL-14 case are written, now that #14358's references model dBias. To keep PR and nightly inside their reserve, the plan's trim rule moved M07.pr to nightly and M26.n to full. - **Tolerance classes:** seven classes, written as 12 `[[tolerance_overrides]]` rows between generated BEGIN and END markers in `ASM_SDPA_ENGINE.toml`. - **Support claims:** 272 claims for `ASM_SDPA_ENGINE` on gfx942. - **Probes left out of the support matrices** (RFC 0022 §9). This is the `support_matrix_units` change above. - **Generator file I/O is UTF-8**, so its tests pass on Windows. ### Temporary ASM_SDPA_ENGINE exclusions These stay until each fix lands; the PR with the fix deletes its entries. **Open engine defects** (`[[test_skips]]` in `ASM_SDPA_ENGINE.toml`). These are valid graphs that ASM accepts and computes wrong. Other engines still run them. | Cases | What goes wrong | Ticket | Fix | |---|---|---|---| | DEF-01 | head-dim stride other than 1 | ALMIOPEN-3036 | #14684 | | DEF-02 | non-packed Stats | ALMIOPEN-3037 | #14684 | | DEF-04 | Hk = Hq > Hv | ALMIOPEN-3039 | #14684 | | DEF-05 and H61 | odd element strides | ALMIOPEN-3038 | #14684 | | DEF-06 | scale of 0 or below | ALMIOPEN-3043 | #14688 | | DEF-03 | fp16 dV precision in the AITER kernel | ALMIOPEN-3046 | none in hipDNN (kernel) | **Quarantined rejection probes** (`_common_excludes` in `ASM_SDPA_ENGINE_test_categories_integration.yaml`, as RFC 0022 §6 asks). These are undefined graphs ASM should decline but accepts. | Cases | What ASM accepts | Ticket | Fix | |---|---|---|---| | prbu01, prbu03 | O or dQ dims that differ from Q's | ALMIOPEN-3039 | #14684 | | prbu13 | a dQ sequence stride below D (overlapping rows) | ALMIOPEN-3038 | #14684 | | prbt04, prbt04n | an O dtype that differs from Q's | ALMIOPEN-3050 | none yet | | prbr05 | `dropout_scale_inv` without a dropout mask | ALMIOPEN-3051 | none yet | ### Dependencies (all merged) - #13937, RFC 0022 (2026-10-30). Its first-phase documents, the methodology guide and the `docs/test-plans/` index, are not on develop yet, so the plan links the RFC's sections directly. - #14312: O and Stats derived from the forward of the same inputs. - #14483: `left_bound` uses cuDNN's meaning. The bundles write `left_bound = W`. - #14358 (2026-11-02): SDPA references cover the full graph API, and the GPU reference is the first oracle in `auto` mode. It also adds frontend rule R14 (`right_bound >= -1`). - #14346 (2026-11-03): the `expected_rejection` and `no_*_reference` bundle flags. - #14709 (2026-11-02): zero strides in the data SDK `Tensor`. ### Interaction with other open PRs - **#14684, #14686, #14687, #14688** (ASM declines, ALMIOPEN-3035). Each deletes its own entries: TOML skips for the DEF cases, and tier-YAML lines for the quarantined probes it fixes (#14684: prbu01, prbu03, prbu13). Whichever of these and this PR lands second removes the entries. - **#14999** (SDPA forward plan bundles, ALMIOPEN-2893). Both PRs edit two files the same way: - `ASM_SDPA_ENGINE.toml`: keep this PR's generated block and put #14999's `SdpaFwdPlan` skips after the `# END SdpaBackward tolerance classes` line. The generator test only checks the BEGIN to END span. The filters do not overlap (`SdpaBackward` vs `SdpaFwdPlan`). - `SUPPORT_MATRIX_OVERVIEW.md`: re-render it; do not hand-merge. The two PRs also add lines near each other in `integration-tests/CMakeLists.txt` and `test_categories_external.yaml`; these auto-merge. ### Before review - [x] `prbr01` (`dropout_probability = 0`) gated; ALMIOPEN-3149 and ALMIOPEN-3150 track the decision. - [x] Rejection probes carry `expected_rejection`; the six ASM accepts are quarantined in the ASM tier YAML with their tickets. - [x] `prbm02` and `prbm02f` removed; the frontend unit test of R14 covers them. - [x] The five dBias probes and GL-14 written; REG-08 (rank-3 Stats) still waits for the derivation extension. - [x] The plan refreshed against the merged RFC: DV-1 and DV-2 now agree with it, DV-3 is an RFC §11 gap, and only DV-4 remains a deviation. - [x] The measured run (plan §4.5) recorded above. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
ASM_SDPA_ENGINEbackward accepts graphs that its gfx942 kernels address wrongly, and returns wrong gradients instead of declining. Some results change from run to run, and one case writes past the end of dV. This PR addsisApplicabledeclines for them. Tickets ALMIOPEN-3036 to ALMIOPEN-3040, epic ALMIOPEN-3035. The kernels are unchanged.Technical Details
One commit per class of defect, plus one test fix:
Unaddressable layouts (ALMIOPEN-3036, 3037, 3038). Declines:
[B, H_q, S_q(, 1)].buildPlannow derives the LSE/D strides from Q's dims.Mismatched dims (ALMIOPEN-3039). O, dO and dQ must have Q's dims, V, dK and dV must have K's dims, and K's batch must equal Q's.
H_k = H_q > H_vused to write dV past its buffer.Zero-stride outputs (ALMIOPEN-3040). Declines dQ, dK or dV with a zero batch or head stride on an axis longer than 1. Inputs with a zero batch or head stride (broadcasts), and a zero stride on a length-1 batch or head axis, stay accepted. A zero or short sequence stride is declined under item 1, on inputs too and on a length-1 sequence axis. Outputs whose nonzero strides overlap are still accepted, which is a known gap: a general footprint rule belongs in hipDNN graph validation.
Test fix. fix(hipdnn): range-check every SDPA kernarg narrowed to 32 bits #14075's
IsApplicableBoundsTheTsProductByTheResolvedTileSizeprobed with an odd stride, which the new parity check also declines, so the test no longer covered the Ts guard. It now uses even probes, so deleting the guard makes it fail again.Review follow-up.
IntegrationGpuSdpaBackwardgains B=2, H=2 cases, with no mask and top-left causal, both packed and with the non-packed layoutsisApplicableaccepts (Q, K, V and dO stored[B, S, H, D], O and dQ rows padded to D+1). Every earlier GPU case had B=1, H=1, where the LSE/D stridesbuildPlanderives from Q's dims are not discriminated. The unit tests probe each decline at more boundary values (head-dim stride 0, sequence stride 0, a short row at D=192, mismatched S and D, wrong rank or stride count), and stale comments are corrected.The new checks run after #14075's dims gate. Each commit message has the GPU reproducers and the mutation results, which were run on develop
61c26758398, before #14075 and #14483 changed the backward builder and its test; the results for this branch alone are under Test Result.Interaction with #14622 (draft SdpaBackward test plan): this PR lets #14622 delete its DEF-01, DEF-02, DEF-04, DEF-05/H61, prbu01/03 and prbu13
[[test_skips]](20 cases). Whichever PR lands second deletes them. A leftover skip is not an error.ASIC Coverage
Backward
isApplicableaccepts only gfx942 and declines every other device before the new checks, so the change affects gfx942 only. TheRock PR CI covers it on gfx94X-dcgpu (unit tests, provider integration tests and the ASM SDPA bundle lane). The gfx950 column below is supplementary: the backward tests skip there.Test Plan
ASM_SDPA_ENGINE, configured like the CI lane.Test Result
This branch alone at
7e19386ebce(the later90d97a9691achanges test comments only), built with thehip-kernel-providerpreset (-DGPU_TARGETS=gfx942 -DHIPDNN_ENABLE_SDPA=ON) and run on one MI300X (gfx942):hip_kernel_provider_tests --gtest_filter='TestSdpaBwd*'IsApplicableRejectsGfx950), 0 failhip_kernel_provider_integration_tests --gtest_filter='Smoke/IntegrationGpuSdpaBwd*'ctest -R '^hip-kernel-provider-asm-sdpa-external-integration_standard_suite$'statsStrideBatchandstatsStrideHeadswapped inbuildPlan, or withnumHeadsQdropped from the batch stride, exactly the eight new integration tests fail and the other sixteen pass.!= 1to> 1) each make a new unit test fail.Combined build on develop
98b504d92c5(after #14075; supplementary). The four ALMIOPEN-3035 ASM fix PRs (this PR, #14688, #14687, #14686) were built together for gfx942 and gfx950 and run on one MI325X (gfx942) and one MI355X (gfx950). Each branch was also checked on its own with a host-side runner of the realisApplicableand unit tests.hip_kernel_provider_testship_kernel_provider_integration_testsASM_SDPA_ENGINElane config, claims enforced138218c0755), its temporary skips removedclang-tidy 20 (
--warnings-as-errors='*') and clang-format 18 are clean on the changed files.IsApplicableAcceptsAddressableLayouts,RejectsNonUnitHeadDimStride,RejectsMisalignedOrShortRows,RejectsNonPackedStats,RejectsMismatchedTensorDimsandRejectsZeroStrideOutputs. Like the other backward isApplicable tests, they skip on gfx950.Submission Checklist
🤖 Generated with Claude Code