Skip to content

fix(tensilelite): use the 1024-byte LDS granularity on gfx11 - #10078

Merged
mgehre-amd merged 1 commit into
developfrom
users/mgehre/gfx11-lds-granule
Sep 3, 2026
Merged

mgehre-amd merged 1 commit into
developfrom
users/mgehre/gfx11-lds-granule

Conversation

@mgehre-amd

@mgehre-amd mgehre-amd commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

KernelWriterAssembly.getLdsLimitedOccupancy rounded every target's LDS usage to a 256-byte granule:

ldsSize = min(ldsSize + 255, deviceLdsSize) & 0xffffff00  # 256-byte granularity

gfx11 allocates LDS in 1024-byte granules, so occupancy was over-estimated wherever a kernel's LDS fell strictly between two 1024-byte boundaries: the model fitted a workgroup the hardware cannot place.

The granule becomes a hardware capability, archCaps["LdsGranularity"] (1024 on gfx11, 256 everywhere else), which getOccupancy passes to getLdsLimitedOccupancy.

Only gfx11 changes behaviour. Follow up PRs should address this for gfx10 and gfx12, where the LDS granularity is also 1024.

Validation

Rebuild all gfx11 kernels. 19 changes their assembly (they are occupancy limited due to LDS with the correct rounding; so they used additional VGRPs). All of those were benchmarked and their A/B perf was within noise.

  • Tensile/Tests/unit occupancy lane (test_occupancy.py, test_occupancy_buildtime.py, test_occupancy_hip.py, test_custom_kernel_occupancy.py, test_PrefetchAcrossPersistent.py): 144 passed, 11 skipped.
  • Tensile/Tests/unit/characterization/_codegen: 254 passed, 60 snapshots passed
  • Full pytest -m unit -n4 Tensile/Tests/unit was run on this branch and on its base commit and compared test-by-test

Fixes #10049

@codecov

codecov Bot commented Aug 15, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #10078      +/-   ##
===========================================
- Coverage    63.78%   63.78%   -0.00%     
===========================================
  Files         2825     2825              
  Lines       469128   469124       -4     
  Branches     69270    69270              
===========================================
- Hits        299226   299223       -3     
  Misses      148858   148858              
+ Partials     21044    21043       -1     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 39.07% <ø> (ø) Carriedforward from eaf498c
TensileLite-Unit 75.53% <ø> (-<0.01%) ⬇️ Carriedforward from eaf498c
hipBLAS 90.62% <ø> (ø) Carriedforward from eaf498c
hipBLASLt 35.22% <ø> (+<0.01%) ⬆️
hipCUB 82.68% <ø> (ø) Carriedforward from eaf498c
hipDNN 86.95% <ø> (ø) Carriedforward from eaf498c
hipFFT 43.67% <ø> (ø) Carriedforward from eaf498c
hipRAND 76.12% <ø> (ø) Carriedforward from eaf498c
hipSOLVER 68.92% <ø> (ø) Carriedforward from eaf498c
hipSPARSE 86.99% <ø> (ø) Carriedforward from eaf498c
rocBLAS 0.28% <ø> (ø) Carriedforward from eaf498c
rocFFT 45.91% <ø> (ø) Carriedforward from eaf498c
rocRAND 56.91% <ø> (ø) Carriedforward from eaf498c
rocSOLVER 76.83% <ø> (ø) Carriedforward from eaf498c
rocSPARSE 74.61% <ø> (ø) Carriedforward from eaf498c
rocThrust 91.60% <ø> (ø) Carriedforward from eaf498c

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

Files with missing lines Coverage Δ
...blaslt/tensilelite/Tensile/KernelWriterAssembly.py 70.04% <ø> (-0.01%) ⬇️

... and 1 file 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.

@mgehre-amd
mgehre-amd force-pushed the users/mgehre/maxoccupancy-range-64 branch from a80d66f to 6dd0548 Compare September 1, 2026 16:06
Base automatically changed from users/mgehre/maxoccupancy-range-64 to develop September 2, 2026 06:10
@therock-pr-bot

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

getLdsLimitedOccupancy rounded every target's LDS to a 256-byte granule. gfx11
allocates LDS in 1024-byte granules, so occupancy was over-estimated wherever a
kernel's LDS fell between two 1024-byte boundaries: the model fitted a workgroup
the hardware cannot place.

The granule is now the archCaps["LdsGranularity"] hardware capability, 1024 on
gfx11 and 256 elsewhere, which getOccupancy passes to getLdsLimitedOccupancy.

Changes:
- getLdsLimitedOccupancy takes the granule as a required argument rather than
  defaulting it, so no caller can silently assume 256; the two gfx950 unit-test
  callers pass it explicitly. Only gfx11 changes behaviour.
- The updateOccupancyFromMaxVgpr test stub builds archCaps by hand, so it gains
  the new key too; it mirrors the real cap (1024 for the gfx11 case the stub
  models, 256 for CDNA) rather than hardcoding one granule.
- No characterization golden covers gfx11 codegen (the _codegen data is gfx90a,
  gfx908, gfx942, gfx1201, gfx1250), so none needed re-recording. Confirmed by
  running Tests/unit before and after: the snapshot tally is unchanged.
- Touches rocisa C++: a rocisa reinstall is needed to pick up the new cap.
@mgehre-amd
mgehre-amd force-pushed the users/mgehre/gfx11-lds-granule branch from d599c32 to 617f656 Compare September 2, 2026 16:23
@mgehre-amd
mgehre-amd marked this pull request as ready for review September 2, 2026 16:27
@mgehre-amd
mgehre-amd requested a review from a team as a code owner September 2, 2026 16:27
@therock-pr-bot

therock-pr-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown

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

@mgehre-amd mgehre-amd changed the title fix(tensilelite): use the 1024-byte LDS granule on gfx11 fix(tensilelite): use the 1024-byte LDS granularity on gfx11 Sep 3, 2026
@mgehre-amd
mgehre-amd merged commit fd61638 into develop Sep 3, 2026
149 of 154 checks passed
@mgehre-amd
mgehre-amd deleted the users/mgehre/gfx11-lds-granule branch September 3, 2026 14:05
tony-davis pushed a commit that referenced this pull request Sep 3, 2026
#11672)

This reverts commit fd61638 - PR #10078

## Motivation

hipblaslt build failed with this PR. 

## Technical Details

ldsGranularity exception error observed with this PR. 

## Test Plan
Build hipblalslt.
Running hipblaslt CI tests.

## Test Result
Build was successful after revert.

Co-authored-by: Babak <bpoursar@amd.com>
@assistant-librarian

Copy link
Copy Markdown
Contributor

TheRock Submodule Bump Activity

Newest first

mgehre-amd added a commit that referenced this pull request Sep 9, 2026
archCaps has two independent producers: rocisa's hardware_caps.hpp and
stinkytofu's python_module/src/HardwareCaps.cpp, reached through
rocisa_stinkytofu_adaptor when ROCISA_BACKEND=stinkytofu. #10078 added
LdsGranularity to the first only, so any build served by the stinkytofu
provider got a fully populated archCaps missing exactly that key, and
getOccupancy died with KeyError: 'LdsGranularity' in globalWriteElementBatch.
That is what got #10078 reverted in #11672.

The reverted build's own capability dump is the evidence: it lists DeviceLDS
but neither CacheLineBytes nor NumXCD, and those two exist only in rocisa's
initArchCaps (added 2026-07-24, well before that build). The table is a union
over every probed ISA, so their absence identifies stinkytofu as the provider.
No stale rocisa binary is involved -- a clean build fails the same way.

Because the stinkytofu provider probes comgr against the target ISA name and
ignores the host GPU, this reproduces on any machine with -DGPU_TARGETS=gfx1250;
the hardware is not needed.

Changes:
- The expression matches rocisa's exactly, so both providers stay in lock-step;
  verified by linking initArchCaps and dumping it (gfx11 -> 1024, gfx942/gfx950/
  gfx1030/gfx1201/gfx1250 -> 256).
- Tests pin it on both sides of the adaptor: presence in the adaptor's dynamic
  caps test, and the gfx1250 value in the comgr cap table test, so a future cap
  added to one provider and not the other fails here rather than in codegen.
mgehre-amd added a commit that referenced this pull request Sep 9, 2026
…fu table

regCaps has two independent producers: rocisa's hardware_caps.hpp and
stinkytofu's python_module/src/HardwareCaps.cpp, reached through
rocisa_stinkytofu_adaptor when ROCISA_BACKEND=stinkytofu. The preceding commit
raised PhysicalMaxSgpr to 2048 on gfx11 in the first only; this brings the
second in line so the two cannot disagree about the same key.

Changes:
- The expression matches rocisa's exactly, so both providers stay in lock-step.
  This is the same drift class that got #10078 reverted in #11672 (a cap added
  to one provider and not the other).
- No behavioural effect today: STINKYTOFU_ALL_ARCHS is Gfx1250/Gfx1250v0 only
  (cmake/StinkytofuArchList.cmake), so HardwareCaps::query returns an empty
  result for every gfx11 triple and the new branch is unreachable until a gfx11
  backend exists. The change is for consistency, not to fix an observed failure.
- Tests can only pin the non-gfx11 branch on this side, for the same reason:
  test_comgr.py asserts the gfx1250 value stays 800 so the expression cannot be
  folded back to a flat constant, and the adaptor's dynamic caps test asserts
  the key is present. The gfx11 value stays covered on the rocisa side in
  Tensile/Tests/unit/test_occupancy.py.
- Not addressed here: stinkytofu also reports MaxWavesPerSimd = 10 for gfx11
  where rocisa reports 16. That is a separate pre-existing divergence and
  changing it would alter occupancy on the stinkytofu path.
mgehre-amd added a commit that referenced this pull request Sep 10, 2026
…fu table

regCaps has two independent producers: rocisa's hardware_caps.hpp and
stinkytofu's python_module/src/HardwareCaps.cpp, reached through
rocisa_stinkytofu_adaptor when ROCISA_BACKEND=stinkytofu. The preceding commit
raised PhysicalMaxSgpr to 2048 on gfx11 in the first only; this brings the
second in line so the two cannot disagree about the same key.

Changes:
- The expression matches rocisa's exactly, so both providers stay in lock-step.
  This is the same drift class that got #10078 reverted in #11672 (a cap added
  to one provider and not the other).
- No behavioural effect today: STINKYTOFU_ALL_ARCHS is Gfx1250/Gfx1250v0 only
  (cmake/StinkytofuArchList.cmake), so HardwareCaps::query returns an empty
  result for every gfx11 triple and the new branch is unreachable until a gfx11
  backend exists. The change is for consistency, not to fix an observed failure.
- Tests can only pin the non-gfx11 branch on this side, for the same reason:
  test_comgr.py asserts the gfx1250 value stays 800 so the expression cannot be
  folded back to a flat constant, and the adaptor's dynamic caps test asserts
  the key is present. The gfx11 value stays covered on the rocisa side in
  Tensile/Tests/unit/test_occupancy.py.
- Not addressed here: stinkytofu also reports MaxWavesPerSimd = 10 for gfx11
  where rocisa reports 16. That is a separate pre-existing divergence and
  changing it would alter occupancy on the stinkytofu path.
mgehre-amd added a commit that referenced this pull request Sep 11, 2026
…fu table

regCaps has two independent producers: rocisa's hardware_caps.hpp and
stinkytofu's python_module/src/HardwareCaps.cpp, reached through
rocisa_stinkytofu_adaptor when ROCISA_BACKEND=stinkytofu. The preceding commit
raised PhysicalMaxSgpr to 1696 on gfx11 in the first only; this brings the
second in line so the two cannot disagree about the same key.

Changes:
- The expression matches rocisa's exactly, so both providers stay in lock-step.
  This is the same drift class that got #10078 reverted in #11672 (a cap added
  to one provider and not the other).
- No behavioural effect today: STINKYTOFU_ALL_ARCHS is Gfx1250/Gfx1250v0 only
  (cmake/StinkytofuArchList.cmake), so HardwareCaps::query returns an empty
  result for every gfx11 triple and the new branch is unreachable until a gfx11
  backend exists. The change is for consistency, not to fix an observed failure.
- Tests can only pin the non-gfx11 branch on this side, for the same reason:
  test_comgr.py asserts the gfx1250 value stays 800 so the expression cannot be
  folded back to a flat constant, and the adaptor's dynamic caps test asserts
  the key is present. The gfx11 value stays covered on the rocisa side in
  Tensile/Tests/unit/test_occupancy.py.
- Not addressed here: stinkytofu also reports MaxWavesPerSimd = 10 for gfx11
  where rocisa reports 16. That is a separate pre-existing divergence and
  changing it would alter occupancy on the stinkytofu path.
mgehre-amd added a commit that referenced this pull request Sep 11, 2026
…fu table

regCaps has two independent producers: rocisa's hardware_caps.hpp and
stinkytofu's python_module/src/HardwareCaps.cpp, reached through
rocisa_stinkytofu_adaptor when ROCISA_BACKEND=stinkytofu. The preceding commit
raised PhysicalMaxSgpr to 1696 on gfx11 in the first only; this brings the
second in line so the two cannot disagree about the same key.

Changes:
- The expression matches rocisa's exactly, so both providers stay in lock-step.
  This is the same drift class that got #10078 reverted in #11672 (a cap added
  to one provider and not the other).
- No behavioural effect today: STINKYTOFU_ALL_ARCHS is Gfx1250/Gfx1250v0 only
  (cmake/StinkytofuArchList.cmake), so HardwareCaps::query returns an empty
  result for every gfx11 triple and the new branch is unreachable until a gfx11
  backend exists. The change is for consistency, not to fix an observed failure.
- Tests can only pin the non-gfx11 branch on this side, for the same reason:
  test_comgr.py asserts the gfx1250 value stays 800 so the expression cannot be
  folded back to a flat constant, and the adaptor's dynamic caps test asserts
  the key is present. The gfx11 value stays covered on the rocisa side in
  Tensile/Tests/unit/test_occupancy.py.
- Not addressed here: stinkytofu also reports MaxWavesPerSimd = 10 for gfx11
  where rocisa reports 16. That is a separate pre-existing divergence and
  changing it would alter occupancy on the stinkytofu path.
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.

TensileLite MaxOccupancy valid range capped at 40, limiting LDS-budget tuning granularity

2 participants