Repository navigation
Conversation
Mono's GEMVs read only bf16, so the agentic recipe's C1 launch kept five dense projections (KDA in_proj and f_b, o_proj, the shared experts' gate-up and down) out of the ptpc_fp8 quant. K1 and K2 now read those FP8 planes in place (E4M3 in AITER's (16, 16) preshuffle, an fp32 scale per row). FP8 widens exactly to bf16, so activations, MFMAs and summation order are unchanged; each row is scaled before its bf16 rounding. bf16 builds keep their argument layout. weights._dense refuses planes the kernels can't read, forward_pre_o no longer fuses o_proj's activation quant, and the C1 launch no longer excludes the five. Tests: tests/models/test_kimi_k3_mono_dense_bind.py. Signed-off-by: Rebecca Lee <rebecca.lee@amd.com>
Contributor
🏷️ CI GuideRuns automatically on every eligible PR before approval:
Heavy model tests:
|
valar-cop
reviewed
Nov 4, 2026
| ) | ||
| _need(w.shape[0] % 16 == 0, f"{name} is {tuple(w.shape)}: rows not padded to 16") | ||
| # the binders' constant K: the GEMVs walk it in 128-wide chunks | ||
| assert k % 128 == 0, f"{name}: K {k} not a multiple of 128" |
There was a problem hiding this comment.
use _need here too, bare assert breaks the file's own discipline..
| "delta": True, | ||
| "debug": False, | ||
| # this build takes no row scales: o_proj in bf16 only | ||
| "w8": False, |
There was a problem hiding this comment.
these two builds unused? remove them or thread the scale args through..
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.
Summary
Mono decode reads only bf16 weights, so mono deployments, including the agentic recipe's C1
launch, exclude five dense projections from the
ptpc_fp8quant: KDA'sin_projandf_b(K1),and
o_projand the shared experts (K2). C1 then carries 5.3 GiB more weight per rank and runsbf16 GEMMs on every prefill.
This PR has K1 and K2 read the FP8 planes in place (E4M3 in AITER's (16, 16) preshuffle, an fp32
scale per row). FP8 widens exactly to bf16, so activations, MFMAs and summation order are
unchanged, and bf16 planes run as before. C1 now quantizes all five, like the other bands, which
don't run mono and are unchanged.
8x MI355X, the agentic C1 launch, against main
58ba50180; 3 launches per arm, ranges apartunless noted:
K1 (2445 to 1775 us per target forward, -27.4%), whose largest plane,
in_proj, is now halfthe bytes.
32768, because prefill runs the five as FP8 GEMMs.
served model all 2720
in_projchecks are within rounding error of an fp64 recompute.o_projbecomes FP8 too, making the draft forward 27 us slower; thedecode numbers above include it.
Changes
atom/mono/device/gemv.py(shared by K1, K2 and the DSA indexer) gains an FP8 (w8) path: inAITER's (16, 16) preshuffle a lane's 8 K columns are 8 contiguous bytes, so it loads 2 dwords
instead of 4, widens them to bf16 and scales each reduced row before the bf16 rounding.
kda.py) readsin_projandf_bas FP8; K2 (layer.py,back.py,stages/moe.py)reads
o_projand the shared experts. The router and the latent projection stay bf16.runner.pyaddsw8to the K1 / K2 build keys and passes the row scales as the last kernelarguments, so bf16 builds keep their argument layout.
weights.pybinds FP8 planes in place and refuses what the kernels can't read, such as anon-E4M3fn or unpadded plane, a bias, or bf16 and FP8 mixed in one build.
model.py:_gated_coregainsfuse_o_quant, so mono'sforward_pre_ono longer fuses anFP8
o_proj's activation quant into the MLA gate; productionforwardis unchanged.needs on main), and
Kimi-K3.mddrops the exclusion advice.Performance
8x MI355X, the agentic C1 launch, ATOM main
58ba50180with and without this commit (without it,the five are excluded, as the recipe does; both arms use fp32 KDA state). 3 interleaved launches
per arm; mean, with the range in parentheses.
peak_torch, worst rankaverages 382 us faster, but its launches spread over up to 860 us, so that part is unresolved.
Net of the draft's 27 us, the step is 0.75 ms shorter in median ITL (1.05 ms profiled).
prompt beats main's fastest.
Method
rocm/atom-dev:nightly_202611011508-rocm10.0, ATOM main58ba50180mounted over the image's,with and without this commit. Every arm preloads the image's
libgomp.so.1, which main'sloader needed on this image before fix(loader): resolve OpenMP symbol through torch #2936;
58ba50180includes fix(loader): resolve OpenMP symbol through torch #2936, and the preload is keptso every arm runs the same way.
recipes/Agentic-Kimi-K3.md's C1 launch: TP8, DCP1, DSpark with 7 speculative tokens, syntheticacceptance length 3.84, mono decode on.
atom.benchmarks.benchmark_serving, random dataset, 8192 in / 1024 out (range ratio0.8),
--ignore-eos, 5 prompts at concurrency 1, seed 0; a warmup wave, then two timed waves.With speculative decoding each step streams one chunk, so the median ITL is the step period.
per length, no shared prefixes), 8 output tokens, one request at a time. The benchmark's
initial test request caches each set's first prompt, so TTFTs are over prompts 2 to 12.
peak_torch(weights plus peak activations) and KV blocks are from the server log. K1, K2, thedraft forward and the step period are medians over rank 0's graph replays in a torch-profiler
window during a third wave; the profiler lengthens the step, so its period only compares arms.
Limitations
differ on the same plane; mono's are closer to the exact product (see Testing).
gfx942, is refused at bind. The (16, 16) layout isn't recorded on the tensor, so this relies on
ATOM's linears shuffling only at that default.
o_projis now FP8, as at every other band (+27 us a draft forward; it affectsacceptance, not output). A C1-only exclusion of
layers.*.self_attn.o_proj, which matches onlythe draft's, would recover this, but would bring back a C1-only quant override, and its effect
on acceptance is unmeasured.
Testing
gfx950 (MI355X),
rocm/atom-dev:nightly_202611011508-rocm10.0.tests/models/test_kimi_k3_mono_dense_bind.py(new), CPU: bf16 and FP8 planes bind inplace, unreadable formats and mixed bf16 / FP8 layers are refused, and the kernels' FP8 operand
addresses match AITER's
shuffle_weight(layout=(16, 16)).gemv's bf16 and FP8 paths equal the dequantized product bitfor bit at 1, 5 and 16 tokens and read all 254 finite E4M3 codes exactly; breaking the row
scale or the dword order fails them.
in_proj(C2, C8, and concurrency 5 and 8 atC4 settings, 5 to 64 rows) are within worst-case fp32 rounding of an fp64 recompute, with
relative L2 error 1.7e-3 against 1.1e-2 to 1.3e-2 for the production GEMM.
f_bis checkedonly by GSM8K.
instructions (three gain one
s_nop), the DSA indexer is byte-identical, and no FP8 buildspills a VGPR.
testspackage shadows ATOM's and must be masked; otherwise 2 fail, on main too.
off); McNemar p = 1.00. Draft acceptance 53.1% on both. Main's runs are on
606aceb11, with thesame mono kernels.
blackandruffclean.