Skip to content

fix(tensilelite): AmaxD inter-wave reduction LDS write-after-read race - #15040

Merged
mengzcai merged 4 commits into
ROCm:developfrom
mengzcai:users/mengzcai/amaxd_inter_wave_war
Nov 6, 2026
Merged

mengzcai merged 4 commits into
ROCm:developfrom
mengzcai:users/mengzcai/amaxd_inter_wave_war

Conversation

@mengzcai

@mengzcai mengzcai commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

JIRA ID : AIHPBLAS-5448

Motivation

matmul_fp8_dst_fp8_amaxD_1250 fails intermittently on gfx1250 HW CI: the GPU AmaxD is low by a fixed amount per shape (TT 768x4096x768 bf8 x f8: CPU 211540, GPU 207480).

Root cause: in amax_inter_wave_reduction, each tree step has upper waves store to slot w - Offset, a barrier, then lower waves load slot w. Every step reuses slots from 0, and nothing orders step i's loads before step i+1's stores. With 4 waves, w1 can store max(w1, w3) to slot 0 in step 2 before w0 has read w2's value from it in step 1, so w2's partial max is lost. The code is old and shared by all archs; it surfaced after #13300 made gfx1250 ship AmaxD kernels.

Technical Details

  • Wave w stores to slot w; lower wave w loads slot w + Offset. Each wave stores once per reduction, so no slot is reused and no barrier is added. Slot 0 stays free for the broadcast; LDS reservation is unchanged.
  • Reject OutputAmaxD with a non-power-of-two NumWaves: the tree halves the wave count, so e.g. 3 waves would drop w2. Shipped AmaxD solutions use 1, 2 or 4 waves.
  • Tests: unit tests for the slot addressing (every power-of-two wave count a valid WorkGroup allows, wave32 and wave64) and the reject; the gfx1250 AmaxD tox YAML ran only 1-wave workgroups, so it now also runs 2 and 4 waves.

Test Plan

On gfx1250 (MI450X B0), develop d1dd5a8 vs this branch: hipblaslt-test *amaxD_1250*, the tox YAML, and the new unit tests. To make the race deterministic, a debug-only build delays wave 0 with s_sleep before its inter-wave load.

Test Result

test develop this PR
*amaxD_1250* x200 pass (race too rare in one process) pass
*amaxD_1250* + forced delay 80/384 fail every repeat; same values as CI (211540 vs 207480) pass (x20)
tox amax_gfx1250.yaml + forced delay 7 of 30 4-wave runs fail; 1/2 waves pass pass
tox amax_gfx1250.yaml - pass
new unit tests fail pass
TensileLite unit + characterization, pre-commit - pass

gfx942 shares the codegen and is covered by the wave64 unit test only.

Submission Checklist

Every step of the inter-wave tree reused LDS slots from 0, and its one
barrier did not order step i's loads before step i+1's stores, so a
partial max could be overwritten before it was read and AmaxD came out
low. Store wave w's value to slot w and load slot w + Offset: each slot
is written once per reduction, so no extra barrier is needed.

JIRA: AIHPBLAS-5448
@therock-pr-bot

therock-pr-bot Bot commented Nov 4, 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 4, 2026

Copy link
Copy Markdown

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

mengzcai added 3 commits November 4, 2026 10:19
…Groups

Take the wave counts from makeValidWorkGroups() and the target's
WavefrontSize instead of a hardcoded list, emit the reduction for each,
and check its start Offset. Only power-of-two counts are tested: the
tree halves Offset each iteration.
The inter-wave amax reduction halves the wave count each step, so with
e.g. 3 or 6 waves some partial maxima are never reduced. No shipped
AmaxD solution uses such a count (1, 2 or 4 waves); reject it at
solution derivation instead of producing a wrong amax.
Every group used MIWaveGroup [1, 1], a one-wave workgroup, so the
inter-wave amax reduction never ran a step. Add [2, 1] and [2, 2]; the
second step, where the LDS slot reuse raced, only exists at 4 waves.
@codecov

codecov Bot commented Nov 4, 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 (53.94%) 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   #15040      +/-   ##
===========================================
+ Coverage    77.43%   77.64%   +0.21%     
===========================================
  Files         2902     2902              
  Lines       489842   490184     +342     
  Branches     74142    74226      +84     
===========================================
+ Hits        379301   380580    +1279     
+ Misses       85573    84660     -913     
+ Partials     24968    24944      -24     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 53.94% <ø> (+2.99%) ⬆️
TensileLite-Unit 84.37% <100.00%> (+0.32%) ⬆️
hipBLAS 90.62% <ø> (ø) Carriedforward from f44ee05
hipBLASLt 68.88% <ø> (+0.47%) ⬆️
hipCUB 82.68% <ø> (ø) Carriedforward from f44ee05
hipDNN 87.20% <ø> (ø) Carriedforward from f44ee05
hipFFT 42.47% <ø> (ø) Carriedforward from f44ee05
hipRAND 76.12% <ø> (ø) Carriedforward from f44ee05
hipSOLVER 69.67% <ø> (ø) Carriedforward from f44ee05
hipSPARSE 87.03% <ø> (ø) Carriedforward from f44ee05
rocBLAS 69.19% <ø> (ø) Carriedforward from f44ee05
rocFFT 47.28% <ø> (ø) Carriedforward from f44ee05
rocRAND 57.32% <ø> (ø) Carriedforward from f44ee05
rocSOLVER 76.74% <ø> (ø) Carriedforward from f44ee05
rocSPARSE 83.54% <ø> (ø) Carriedforward from f44ee05
rocThrust 93.15% <ø> (ø) Carriedforward from f44ee05

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

Files with missing lines Coverage Δ
...lt/tensilelite/tensilelite/KernelWriterAssembly.py 79.27% <100.00%> (+0.34%) ⬆️
...ensilelite/tensilelite/SolutionStructs/Solution.py 73.02% <100.00%> (+3.24%) ⬆️

... and 43 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.

@mengzcai

mengzcai commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

The only FFM failure is fixed by "fix(tensilelite): turn off USO in gsuasb_fp32_atomic_gfx1250" (AIHPBLAS-5447).

@mengzcai
mengzcai merged commit 97c299d into ROCm:develop Nov 6, 2026
477 of 496 checks passed
@mengzcai
mengzcai deleted the users/mengzcai/amaxd_inter_wave_war branch November 6, 2026 04:44
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.

3 participants