Repository navigation
Conversation
added 3 commits
October 28, 2026 15:41
… every CTA Not bitwise. Each q_a / kv_a tile's first 4096 K run on its own CTA, the remaining 2048 on one of the 92 CTAs past the tiles (two tiles' rests a CTA), so every CTA streams at most 64 KB of weights instead of 96 KB on 164 CTAs. Neither part normalizes its input rows: each multiplies bf16(x * gamma), and q_norm and the cache tasks add the two partial sums (q_a2, kv_a2 hold the rests') and scale them by the row's rstd, which they compute from x before their wait. The index projections keep their whole-K tiles, on the CTAs with one tile's rest (the NextN entry starts past them); the MoE stages keep their CTAs. A layer from pushed rows (layer 0, the NextN layer) reads them in both parts and in the rstd, its weights issued before the rows' wait. The front asserts FP8 block-128 q_a / kv_a weights.
Each of the 8 rounds took two wave reductions: the key's maximum, then the smallest ID among the lanes that hold it. When one lane holds the maximum (all but exactly equal f32 keys), its head is the pick: a ballot and a lane read replace the second reduction. Same picks in the same order.
… the rstd Not bitwise (the router logits only). A router task staged the RMS-normalized row: the sum of squares' block reduction, two barriers, then the scaled stores. It now stores bf16(a * gamma) as the rows arrive, with each wave's sum of squares beside them, and one barrier serves both: the GEMV reads the row, and the rstd (summed in the same order, so the activation blocks keep their bits) scales the FP8 activation blocks and the 8 logits.
Collaborator
Author
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
Stacked on the previous PR (shared layer, MoE and NextN entry, itself on sgl-project#75). Merge that first; this PR's diff is its last three commits.
The front of a GLM-5.3 layer launch (q_a | kv_a, 2,624 rows over the 6,144-wide input) ran as 164 whole-K tiles. 164 CTAs each streamed 96 KB of weights while the other 92 waited. Then two parts of the routing window run long. Each top-8 round takes two wave reductions, though the second matters only on exact ties. And the router task normalizes its row before the GEMV, which costs a block reduction and two barriers.
This PR:
Numerics change (not bitwise):
Result on MI355X, the previous PR → this PR (TP8, FP8 E4M3 KV, MTP 3-1-4 at the golden accept length 2.99, 8K):
Modifications
Three commits, one per change. Each has its own numerics check against its parent (Accuracy Tests) and its own kernel-only estimate (Speed Tests).
q_a2,kv_a2hold the rests) and scale them by the row's rstd, which they compute from x before their wait. The index projection tiles keep whole K, on the CTAs with one rest, and the NextN entry starts past them. The MoE stages keep their CTAs. A launch from pushed rows (layer 0, NextN) reads them in both parts and in the rstd, with its weights issued before the rows' waitqkv_ahas a task on every CTA.q_norm,q_b,split,ukanduvfollow at CTA 0, in the order they had before, andostarts at split's first CTA as before.router,uganddownkeep the CTAs they had with whole tiles. New scratch:q_a2andkv_a2.Accuracy Tests
The kernel checks ran on one GPU: one process runs rank 0 of a TP8 (or TP4) launch alone, with its peers' partial sums zeros tagged with the launch's epoch. The out-of-tree harness wraps
check_layer.pyandcheck_nextn.pyunchanged.Numerics per commit. A shared and an indexer launch from the same input rows on both trees: widths 2, 4 and 8, one request a row, bf16 and E4M3 MLA cache. The table gives relative L2 distances against the parent commit (q_an, KV latent rows written, router scores, output) and the routed experts that differ, out of 8 a row. Ranges are over 2 / 4 / 8 rows.
The top-8 shortcut is bitwise: dumps of commit 2 against commit 1 (
check_layer.py --dump, the previous PR's set: shared, index, model order, dense; 2 / 4 / 8 rows; p0, p1, v4; both caches; 3 steps): TP8 6,588 equal, 0 differ; TP4 6,588 equal, 0 differ; no error word.NextN launch = plain launch fed its own x, bitwise on this head (
check_nextn.py --only entry: NextN index at 4 and 8 rows, NextN shared at 2, 4 and 8, with and without pad rows; TP8 and TP4, bf16 and E4M3): 20 / 20 checks pass in each of the 4 runs. Entry against the torch entry: up to 2.8e-5. Against f32: 2.4e-3. The swapped-norm control gives 0.14.Serving accuracy: TBD at TP8 (GSM8K with MTP, A/A pair; KL decode ‖ prefill;
SGLANG_AMD_MONO_CHECK=1).Unit tests on a CPU-only host, in the image: 330 passed, with the same 7 failures and 3 collection errors as [Feat] [MI355X] glm53: The NextN draft steps on their own launches sgl-project/sgl-amd-mono#75 (spec-registration and contract tests that need the SGLang overlay; deepseek_v4, minimax).
Speed Tests and Profiling
Setup as sgl-project#75 (image
lmsysorg/sglang-rocm:v0.5.22-rocm720-mi35x-20261025, squashfssha256:fb07e0ef78fe, SGLangpython/sglangat5044779f,zai-org/GLM-5.3atba32f8c1, FP8 E4M3 KV).TP8, MTP 3-1-4 at AL 2.99, cycle in ms: TBD (previous PR → this PR, 1 and 2 requests, 8K and 128K).
Kernel-only (
time_layers.py), each commit against its parent: TBD.Registers
The compile survey covers every kind at TP4 and TP8, widths 2 / 4 / 8, both caches,
stopon and off: 148 keys a commit. Every key builds on every commit.stop=True: 20–28 → 0).stop=True): six kernel arguments (s_q_b…w_o) are loaded and never read, the miscompile class of SGPR-spilled kernarg restores. Its SGPR spills go 240 → 756 with the front. The builds are deterministic for this key: a rebuild gives the same object on commit 1, the head and the previous PR's head. The head's object is clean.Reviewer notes
route_top8, which the 4-row per-row up/gate path also uses for tied rows.Checklist
pre-commit run --all-filespasses. (ruff, ruff-format and isort clean on the touched files; full run TBD)test/cover the change. (The existing kernel tests; numerics are bounded by the serving check).github/CODEOWNERSthat names its owner. (No new model.)