Skip to content

perf(moe): specialize Kimi-K3 B1 gate projection (gfx950) - #6

Open
JohnQinAMD wants to merge 2 commits into
mainfrom
perf/kimi-k3-b1-gate-projection
Open

JohnQinAMD wants to merge 2 commits into
mainfrom
perf/kimi-k3-b1-gate-projection

Conversation

@JohnQinAMD

@JohnQinAMD JohnQinAMD commented Jul 29, 2026

Copy link
Copy Markdown
Owner

[Kimi-K3] Add gfx950 B1 router projection specialization

Summary

This change adds a narrow FlyDSL BF16 router-projection specialization for the
Kimi-K3 TP8 B1 decode shape on gfx950. The upstream branch is based directly
on AITER origin/main; it does not depend on the separate route-plus-sort
optimization.

The new kernel computes 1x7168 @ 896x7168.T with one 64-thread workgroup per
contiguous expert row. Lanes accumulate in FP32, reduce with a wave DPP tree,
round to BF16 to preserve GateLinear's output contract, and store FP32 logits.
It launches 896 workgroups rather than serializing the 12.85 MB router weight
matrix through one CU.

Dispatch is intentionally isolated:

  • supports_kimi_k3_b1_gate_projection is the single named support predicate.
  • kimi_k3_gate_projection_dispatch is the single named dispatch decision.
  • It requires gfx950, FlyDSL, B1x7168 contiguous BF16 hidden states, and
    896x7168 contiguous expert-major BF16 weights.
  • Generic shapes, B8/B16, other AMD architectures, and NVIDIA are unchanged.

This is projection-only. It chains into the Phase B route-sort mechanism but
does not fuse projection with selection or metadata. That avoids introducing a
margin-dependent local-candidate reduction while production routing margins
remain unavailable.

Performance

Measured on MI355X/gfx950 with CUDA graph capture, 100 operations per graph,
100,000 warmup operations, 21 trials, and two independent Python processes:

The complete-boundary table below was measured with the independent projection
stacked on the separately proposed route-plus-sort optimization:

Batch Route/sort base, runs 1/2 Stacked candidate, runs 1/2 Mean result
1 24.4290 / 24.4066 us 15.8737 / 15.8429 us 1.5398x
8 42.7152 / 42.6656 us 42.8511 / 42.7903 us +0.305%
16 41.8848 / 41.2968 us 41.7855 / 41.7647 us +0.443%

B1 projection alone improves from 13.6949/13.6825 us to
4.2076/4.2236 us. Cross-process complete-boundary deltas are 0.194%,
0.142%, and 0.050% for B1/B8/B16.

The existing generic FlyDSL candidates bottomed out at 19.686 us complete,
and the dedicated small-M candidates bottomed out at 21.842 us; neither met
the 18.5 us complete gate. The retained one-expert-per-wave layout also beat
two experts per wave (17.788 us complete) and four experts per wave
(20.484 us).

The exact stacked TP8 B1 endpoint was then measured twice on MI355X with 8K
input, 1K output, and no speculative decoding. It reached 50.7012 and
50.5690 decode tok/s (50.6351 mean, 0.261% spread), with 19.7234 and
19.7750 ms mean TPOT. This is 1.143% above the prior 50.0628 tok/s checkpoint.
The endpoint image includes AITER ROCm#4405 as a benchmark dependency; ROCm#4405 is
intentionally not bundled in this isolated AITER PR diff.

Correctness and policy

The frozen 24-case campaign passes:

  • Ordinary projected-route expert IDs are exact versus GateLinear plus AITER.
  • Ordinary routing weights are bit-identical (0 relative RMSE).
  • Projected logits have maximum absolute difference 6.103515625e-05.
  • The existing Phase B tie, non-finite, repeatability, Opus metadata, MXFP4
    bytes/scales, and zero-token policies remain unchanged and pass.
  • No host synchronization, repair copy, or metadata conversion is inserted
    before GEMM1.

The measured synthetic ordinary top-k margin is 5.7739e-04. Production
routing margins are unavailable, so margin-dependent production claims remain
provisional. No exact artificial-tie claim is made for engineered
hidden/weight matrices. Projection-route fusion is not part of this change.

Kernel resources

  • 896 workgroups, one 64-lane wave per workgroup
  • VGPR 44, SGPR 22, AGPR 0
  • LDS 0 bytes, private segment 0 bytes
  • VGPR/SGPR spills 0/0
  • Cache artifact SHA256:
    1d04d17f5ed6e274a32e6ec3e2444b8cb4f2f4ca389ef36328bb40b87a96193a

Validation

  • Focused gfx950 pytest on the independent PR branch: 7 passed in 6.74s
  • Combined route/sort plus projection reviewer suite: 11 passed in 6.84s
  • Frozen campaign correctness: 24/24 passed
  • Ruff clean
  • Black clean
  • Python bytecode clean
  • AITER and vLLM diff checks clean
  • vLLM unchanged at 3d309473bbb8d7261c9d9bbfd13082d1d6ab42ef
  • No profiler
  • Exact 28-file live overlay and missing-overlay negative guard passed

Files

  • aiter/ops/flydsl/kernels/kimi_k3_b1_gate_projection.py
  • aiter/ops/flydsl/kimi_k3_gate.py
  • op_tests/flydsl_tests/test_kimi_k3_b1_gate_projection.py

Disclosure

Developed with assistance from OpenAI Codex. The author reviewed the dispatch
contract, reduction order, numerical policy, tests, and endpoint evidence.

Add a narrow gfx950 FlyDSL projection for the production 1x7168 by 896x7168 BF16 router shape. Preserve the GateLinear BF16 output contract, isolate dispatch behind a named capability predicate, and leave unsupported shapes on their existing paths.

Assisted-by: Codex
Signed-off-by: Yanyuan Qin <yanyuan.qin@amd.com>
@github-actions

Copy link
Copy Markdown

🏷️ CI Guide

Runs automatically on every PR:

  • ✅ Pre-checks (submodule verification, code formatting)
  • ✅ Aiter op tests (gfx942 + gfx950)
  • ✅ Triton tests on MI35X (only when aiter/ops/triton/** or related paths are changed)

Extended tests (opt-in via labels):

Label Tests
ci:triton-300x Run an additional Triton test job on MI300X in PRs; main branch always runs both MI35X and MI300X
ci:sglang SGLang integration tests: DeepSeek-R1-MXFP4 accuracy, Qwen 3.5 accuracy
ci:atom ATOM benchmark: DeepSeek-R1-0528, GPT-OSS-120B
ci:atom_full ATOM accuracy suite for PR and main models from ATOM models_accuracy.json
ci:vllm vLLM benchmark: GPT-OSS-120B, DeepSeek-R1-0528, Kimi-K2.5
ci:all All standard extended tests (excludes ci:atom_full)

Only add ci:atom_full for FlyDSL or Triton upgrades.
Add labels via the sidebar or gh pr edit 6 --add-label <label>

Keep the FlyDSL launcher ABI unchanged while making the intentional stream construction explicit to Ruff.

Assisted-by: OpenAI Codex
Signed-off-by: Yanyuan Qin <yanyuan.qin@amd.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant