Prune SM90 kernel configs whose accumulator does not fit in registers#3372
Open
hamuzhan wants to merge 1 commit into
Open
Prune SM90 kernel configs whose accumulator does not fit in registers#3372hamuzhan wants to merge 1 commit into
hamuzhan wants to merge 1 commit into
Conversation
Each SM90 math warp group keeps its 4-byte accumulator fragment in the register file: TmaWarpSpecialized and Pingpong schedules compute one full CTA tile per math warp group (cta_m * cta_n / 128 registers per thread), while Cooperative schedules split the tile across two warp groups (cta_m * cta_n / 256 registers per thread). Above 128 accumulator registers per thread the accumulator does not fit in the 255-register budget together with mainloop state, and ptxas spills it to local memory on every mainloop iteration. Measured on H100 (16-bit dense GEMM, 8192^3, CUDA 13.2): - 128x256/256x128 pingpong and warpspecialized: 44-90 TFLOP/s - 256x256 cooperative: ~43 TFLOP/s, 256x256 pingpong: ~18 TFLOP/s - Nsight Compute shows accumulator spilling (710M local-memory spill requests per launch vs 0 for fitting configs; 43% of executed instructions are local loads/stores) - cuobjdump shows a non-zero stack frame starting at 128 regs per thread - fitting configs reach ~900 TFLOP/s on the same problem The same limit is already in the C++ layers. The ping-pong kernel adjusts its register split above 208 regs per thread but still spills for these tiles (sm90_gemm_tma_warpspecialized_pingpong.hpp), and the builder KernelScheduleAuto path picks cooperative for TileShape_M > 64 (sm90_gmma_builder.inl). This change applies the same limit in the library generator. Prune at instantiation level 0 following the existing early-pruning pattern; higher instantiation levels still emit these configs. Removes 712 of 2417 (-29%) kernels from the default 16-bit SM90 manifest. Across 22k measurements over LLM-style GEMM shapes (FP16 and BF16), none of the pruned configs reach the top 3 for any (shape, M) point. Signed-off-by: hamuzhan <hamzayigitkltr@gmail.com>
Author
Member
|
i think u likely tag the wrong person? |
Author
|
@XiaoSongXS Sorry to bother you. Since I saw you were a reviewer on a PR related to Blackwell, I figured you were the person in charge of this topic. sorry again |
Member
|
Author
|
Thanks, this changes how I’m thinking about the issue. I’ll expand the profiling across fixed problem sizes, CTA tiles, cluster shapes, and schedules before deciding whether generator-side pruning is appropriate |
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.
Prune SM90 kernel configs whose accumulator does not fit in registers
Problem
The SM90 library generator emits kernel configs whose FP32 accumulator cannot
fit in the register file. Each math warp group holds its accumulator fragment
in registers:
TmaWarpSpecialized,TmaWarpSpecializedPingpongcta_m * cta_n / 128(full CTA tile per math warp group)TmaWarpSpecializedCooperativecta_m * cta_n / 256(tile split across two math warp groups)Above 128 accumulator registers per thread, the accumulator no longer fits in
the 255-register budget together with mainloop state, so ptxas spills it to
local memory on every mainloop iteration.
Evidence (H100, CUDA 13.2, 16-bit dense GEMM, M=N=K=8192, TN)
Throughput by per-warp-group accumulator size. FP16 and BF16 give the same
numbers:
Nsight Compute for
..._128x256x64_..._pingpong_epi_tma(BF16 and FP16 reportthe same count):
Compile-time check with
cuobjdump --dump-resource-usageon the built library(FP16, TN, cluster 1x2, epi_tma; BF16 matches):
The stack frame becomes non-zero at exactly 128 registers per thread, matching
the formula above.
This matches limits already present in the C++ layers
The same limit already exists in the kernel and builder code. This PR applies
it in the library generator as well:
producer/consumer register split when it reaches 208 registers per thread
(
include/cutlass/gemm/kernel/sm90_gemm_tma_warpspecialized_pingpong.hpp:143-148).For the pruned configs the accumulator alone needs 256 or more registers, so
the 240-register consumer budget still spills.
KernelScheduleAutopath selects ping-pong only whenTileShape_M == 64and cooperative otherwise(
include/cutlass/gemm/collective/builders/sm90_gmma_builder.inl:1021-1022),so it never picks ping-pong for these tiles.
The builder path already avoids these configs. Only the library generator still
emits them.
Change
Prune these configs in
get_valid_schedulesat instantiation level 0, usingthe existing early-pruning pattern. Higher instantiation levels
(
CUTLASS_LIBRARY_INSTANTIATION_LEVELwith a non-zero pruning digit) still emitthem, so exhaustive-search builds are unchanged.
ScheduleAutois gated by thecooperative (split-tile) budget, since the builder resolves large tiles to a
cooperative schedule.
The rule uses the accumulator size, which is 4 bytes for F16/BF16/TF32/FP8/INT8,
so it applies to all of these paths. The measurements above are from the 16-bit
path.
Impact
pingpong, 120 warpspecialized, 176 cooperative (256x256), 40 auto (256x256).
Library build time drops with the kernel count.
783 to 697 (-11%), int8 155 to 141 (-9%), tf32 287 to 215 (-25%), grouped f16
753 to 465 (-38%). All generator paths configure without error.
Llama-8B/70B layers plus a 128k-vocab LM head, FP16 and BF16, default and
extended instantiation levels) shows none of the pruned configs reaching the
top 3 for any (shape, M) point.
CUTLASS_LIBRARY_INSTANTIATION_LEVEL >= 1xxxbuilds (checked:level 1242 still emits the pruned configs).
Validation
removals and 0 additions.
cutlass_profilerfrom the pruned manifest. All 1904 surviving gemmoperations verify
Passedagainst the device reference (m=640, n=768, k=1024;beta=0.5 for source-C kernels, beta=0 for void-C).
--mode=enumerateon the pruned manifest.cutlass_test_unit_gemm_device_tensorop_sm90is unaffected (unit tests do notgo through the library generator); spot re-run passes.
Repro: