Repository navigation
[Feat] [MI355X] kimi_k3/kimi_k31: Kimi-K3's gfx950 launches, and Kimi-K3.1 steps of up to 8 rows on them - #103
Merged
Merged
Conversation
…i-K3.1 steps of up to 8 rows on them Kimi-K3 (kimi_k3, from #13): per-step monokernels at TP8 for decode and DSpark verify steps of up to 8 rows. K1 on the KDA layers (in_proj, the conv window, the recurrence and the gated norm, reading the committed state in place or the ReplaySSM ring), the MLA projection front on the MLA layers (mla_pre: the AttnRes seam, fused_qkv_a, the gates, q / kv norms, q_b and the q absorb), and the layer launch (o_proj to the MoE output: the seam, the router, top-16 by candidate rank, the latent MoE and the shared expert) on every MoE layer, with sentinel all-reduces on its o_proj, latent and final reductions. Kimi-K3.1 (kimi_k31/spec.py): steps of up to 8 rows (a decode step, or a verify step of one request) run the Kimi-K3 launches; DSpark and DFLASH verify steps of 2 .. 48 requests keep the wide layer launch from #102. SGLANG_AMD_MONO_K31_WIDE=0 serves the narrow steps only (no ReplaySSM needed). Under DCP the MLA layers keep SGLang's projection front. muse_spark: its DFlash2 draft spec names its hidden size, so SGLang can tell a Kimi-K3.1 DFlash2 draft (same architecture and model type) apart and keep that draft's forward. Co-authored-by: billishyahao <bill.he@amd.com> Co-authored-by: wunhuang <wunhuang@amd.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kevin-mii
requested review from
HaiShaw,
alexnails,
kkHuang-amd and
zijiecode
as code owners
November 4, 2026 18:38
Collaborator
Author
|
Review pass before merge (an independent read of the diff, then fixes in this commit): Fixed here:
Left as they are, for follow-ups:
|
4 of 5 tasks
kevin-mii
added a commit
to sgl-project/sglang
that referenced
this pull request
Nov 4, 2026
sgl-project/sgl-amd-mono#103 (ce1290efc4) serves Kimi-K3.1 steps of up to 8 rows on Kimi-K3's gfx950 launches and keeps #102's wide launch above them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 4, 2026
5 tasks
yuychang
added a commit
to yuychang/sgl-amd-mono
that referenced
this pull request
Nov 10, 2026
- Upstream sgl-project#103 squashed this branch's first commits; conflicts resolved against 88aee67 as the effective base - kda/k1: take upstream's ReplaySSM ring and init_committed; re-apply the FP8 in-proj (wfmt) and bf16 state on top - k1: find a KDA layer's state via upstream's state_layer().view_layer_id (sgl-project#113) instead of mamba_map - k1: keep the request-scoped ring decline and check state dtypes for both the scratch and committed pools - spec: drop _k1_bank_rows, upstream's warmup bank already holds the block-write row (sgl-project#108) - layer/oproj: keep the FP8 o_proj (ofmt, w_os) next to upstream's fold, OPT bits and sentinel all-reduce - check_k2: FP8 o_proj modes alongside upstream's fold / OPT checks; test_kimi_k3_spec follows _state_config - GPU: test_kimi_k3_k1 17 passed, test_kimi_k3_kernels (TP8) 3 passed, test_kimi_k3_mla_pre 6 passed
bingxche
added a commit
that referenced
this pull request
Nov 10, 2026
…es, per PR and nightly (#107) ## What CI on two dedicated MI355X nodes that runs the checks of the PR review guideline, split in two: - **PR test** (`pr-test-amd.yml`), maintainer-gated, for each model a PR touches: its unit, kernel and serving tests, the kernel-only timing scripts, GSM8K with the monokernels on and off, and InferenceX fixed-length speed against the base branch. The workflow posts the result as an `AMD PR test` commit status and keeps one PR comment updated with a checklist in the guideline's order (rules, scope, accuracy, kernel microbenchmark, E2E performance, tests, doc). - **Nightly** (`nightly-amd.yml`), on main and the newest SGLang ROCm image: for each Phase 1 model, GSM8K, GPQA (and MMMU-Pro for vision models) and the speed test with the monokernels on, held to the model's fixed baseline. Saturday's **weekly** run adds AIME26 ×4 and runs every benchmark with the monokernels on and off. ## Why The guideline asks reviewers to approve only when these checks pass, plus a ≥5% gain for performance work. Today authors run the checks by hand and paste the numbers. The long benchmarks would make every PR run take most of a day, so GPQA runs nightly and AIME26 ×4 (~23K tokens per answer, the costliest) runs weekly. A PR run keeps only the checks that can block a merge. ## How it works - Trigger: a maintainer adds the `run-ci` label, or runs the workflow with a PR number. `run-ci-extra` does the same and adds GPQA, which catches long-context accuracy losses that GSM8K's short answers can't show. It's meant for PRs that touch attention, the KV cache or long sequences. The run removes the label and pins the PR head SHA it saw, so any later push needs a maintainer again. - Scope (`scripts/ci/scope.py`): a model whose own package or tests changed runs the full tier. A change to `common/`, `__init__.py` or `pyproject.toml` runs every other model's smoke tier (tests, plus speed at the covered widths only) and `common` (the unit tests and the guard/dispatch kernel tests). The CI's scripts and `models.py` come from the base branch, so a model package that `models.py` there doesn't list (a model new in the PR) isn't run: the report warns ("New model"), and the author gives its results by hand until its entry merges. - Sides (`scripts/ci/run_model.py`): every server is the model's `test/e2e` recipe from the PR. **base** is the PR's merge-base with its base branch, monokernels on, used for speed only. **on** is the PR with monokernels on. **off** is the same build with monokernels off, i.e. SGLang's own path. The off side doesn't depend on the package, so the weekly run's off result for the model's recipe is kept as the **monokernel-off reference** (`$CI_SHARED_DIR/monokernel_off_ref`, on shared storage so either node can read it): the PR test and the nightly compare against it, a PR runs off itself only when the reference has no entry yet, and only a weekly run writes it. The container mounts it directly, writable in a weekly run and read-only in the PR test and the nightly, so PR code can't change it. - With monokernels on, an eval sends no more concurrent requests than the launches cover (for Kimi-K3, one request; for DeepSeek-V4.1, eight). A wider step falls back to SGLang's path, and the score would not measure the kernels. - Gate (`scripts/ci/report.py`): - GSM8K (all 1319 questions, plus GPQA with `run-ci-extra`) is compared on vs off question by question with an exact one-sided McNemar test, and a significant loss with monokernels on (p < 0.05) fails; - a median-TPOT (p50) loss of more than 2% vs base fails at a covered concurrency and warns at the model's other concurrencies; `[Perf]`/`[Feat]` PRs also need a ≥5% gain at a covered concurrency of one of the PR's models. Output throughput is reported next to it and warns on a loss over 2%. Other serving metrics swing too much with the monokernels, so the report leaves them out; - failed tests fail, and so do a server that logs no monokernel routing and a step of the run that raises an error; - edits to existing `.github/CODEOWNERS` lines fail, while an added owner line for a new model is only a warning. - The nightly holds each on score to a per-model `baseline` in `models.py` (GSM8K below it fails, the rest warn). Each weekly report suggests baselines from its off scores; the baselines start empty and get set from the first weekly run. The weekly run gates on the paired GSM8K test like a PR run; GPQA and AIME26 ×4 warn when they fall 5 and 3 points below the off run (Zijie's numbers), and MMMU-Pro 3 points. - Before installing main, the nightly also checks the sgl-amd-mono the SGLang image pins (`/sgl-workspace/sgl-amd-mono`): its `test_contract.py`, and a server per model with the monokernels on answering a few requests. A field SGLang adds to an op that the pinned commit doesn't set fails that check the day the image picks it up (Kk's case). - Isolation: the PR workflow uses `pull_request_target`, and the scripts that run outside the container come from the base branch. PR code runs only inside the SGLang ROCm container. The cluster job fetches both commits itself. ## Notes for the reviewer - max-tokens leaves room for thinking models: 16384 for GSM8K, 64K for GPQA and AIME26. - Phase 1 nightly models: DeepSeek-V4.1-Flash, GLM-5.3, GLM-5.3-Flash, Kimi-K3, Qwen3.8-Flash-Next. - GLM-5.3-Flash and Qwen3.8-Flash-Next: their MXFP4 checkpoints aren't on shared storage, but they were downloaded straight into both nodes' mirror, so the nightly serves them (their completeness hasn't been checked by a run yet). - MiniMax-M3 is marked blocked until sgl-project/sglang#41998 and #41708 merge, because SGLang refuses `--enable-amd-monokernel` for it without them. - Kimi-K3.1, MiniMax-M3.1 and Muse-Spark run their unit and kernel tests only, until their SGLang support lands. - Not in CI: OCRBench and LiveCodeBench (sgl-eval doesn't run them yet). SWE-bench stays with the author. - GPQA is a gated dataset: the job fills the dataset cache with the HF token in the runner account's `~/.sgl_amd_mono_ci/hf_token` (set up on the cluster) before any PR code runs. - Setup: the `run-ci` and `run-ci-extra` labels exist and the runners are registered. Optionally, a repo admin can make `AMD PR test` a required status after merge. - Nodes: a job takes whichever of the two CI nodes is free; `slurm_launch.sh` keeps jobs off the shared partition's other nodes with a versioned `SLURM_EXCLUDE` list. A runner's `.env` must not pin a node: Spur's `sbatch` honors `SBATCH_NODELIST` and ignores `SLURM_NODELIST` (tested on the nodes; the stale `SLURM_NODELIST` lines in r1/r2's `.env` are removed). - Runners: r1/r2 (`sgl-project/sgl-amd-mono`) on the `crs-m2m-cpu-spur-arc-016` runner VM, account `z1_sglangci`; each node keeps its checkouts, checkpoint mirror and caches under `/mnt/m2m_nobackup/sgl-amd-mono-ci`. r3/r4 are temporary runners on the fork for the end-to-end trials below; unregister them after merge. - A run of the nightly workflow with `weekly` ticked rewrites the monokernel-off reference from whichever branch it runs, so run it by hand on `main` only. ## Test plan End-to-end on the fork (michaelzhang-ai/sgl-amd-mono) with this PR's CI on top of current `main` (fork branch `e2e-base`), on the two MI355X nodes, with the full settings (all 1319 GSM8K questions, every concurrency): - [PR test](https://github.com/michaelzhang-ai/sgl-amd-mono/actions/runs/42789607786) with `run-ci-extra` on [fork PR #2](michaelzhang-ai#2) (a `deepseek_v41`-only change), CI at d356704: label trigger and removal, scope, merge-base base side, base speed test and timing script, unit/kernel/serving tests, the on server (both launches routed: target_verify steps of batch size 1–8), the off side, the report, the PR comment and the `AMD PR test` status all ran. GSM8K on vs off: 0.9666 → 0.9666, 5 lost / 5 gained, p = 0.623. Median TPOT base → PR within ±1% at the covered concurrencies. The status is red for reasons outside this PR: GPQA could not be loaded (the HF token cannot fetch `Idavidrein/gpqa`; f1eec28 now reports that as not run instead of an error), main's known unit failures, and one serving test that imports `sglang.srt.utils.hf_transformers_utils`, which SGLang moved in sgl-project/sglang#48781. - [Weekly run](https://github.com/michaelzhang-ai/sgl-amd-mono/actions/runs/42789589746) (`common` + `deepseek_v41`): the pinned-mono check correctly fails (the 11-09 image pins sgl-amd-mono e52803f, which lacks #118, so DeepSeek-V4.1 cannot start with the monokernels on that image); on and off with GSM8K and AIME26 ×4 ran. Writing and then reading the monokernel-off reference (weekly → nightly) is still running. - Cancelling a run cancels its cluster job ([run](https://github.com/michaelzhang-ai/sgl-amd-mono/actions/runs/42771116642), on earlier CI code). - Kernel compilation dominates the kernel tests (DeepSeek-V4.1's took 1 h 38 min, mostly FlyDSL JIT on a cold cache); persisting the compile caches is a follow-up. Also: - Ran `scope.py` against the file lists of #95, #96, #97, #101, #103 and #105; the models and rule results match what each PR touched (#96 and #103 trip the CODEOWNERS rule). - `report.py` produced the expected verdicts on synthetic results (paired GSM8K: 7 of 7 discordant lost fails at p = 0.008, a 1/1 split passes), and the review fixes were checked with mocks (step isolation, PR runs not writing the reference, the PR-wide speed gain). The reference's direct mount was tested on v3-060 with the SGLang image: a weekly-mode write and read-back, a read-only mount refusing the write (EROFS) while reads work, and the files handed to the runner account. - Every supported checkpoint the cluster has (16 of 17; `moonshotai/Kimi-K3.1` isn't on HF or the cluster) is mirrored to both nodes' NVMe. --------- Co-authored-by: bingxche <Bingxu.Chen@amd.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Zijie Chen <300606707+zijiecode@users.noreply.github.com>
This was referenced Nov 11, 2026
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
Kimi-K3.1 on MI35x is fastest when each step size runs the launch built for it. #102 covers verify steps of 2 .. 48 requests with the wide layer launch, and leaves a step of one request (6 rows with DFLASH at 6 draft tokens) on SGLang's path. This PR serves those steps on Kimi-K3's per-step launches, which K3.1 shares (the shapes are the same; K3.1 adds the DSA layers, which keep SGLang's attention up to o_proj).
It carries Kimi-K3's gfx950 launches from #13 (@billishyahao), with the work on top of them that the K3.1 bring-up measured, and supersedes #13.
Modifications
kimi_k3: Kimi-K3's launches at TP8, for decode and verify steps of up to 8 rows (from [Feat] [AMD] kimi_k3: Kimi-K3 layer monokernel on gfx950 #13, plus):--enable-linear-replayssm-spec; the conv window is staged and handed back in one Triton launch each.mla_pre, one launch a MLA (DSA) layer: the AttnRes seam, fused_qkv_a, the gates, the q / kv norms, q_b, the indexer projections and the q absorb (q_nope @ w_kc). SGLang takes its outputs through_mono_pre/q_nope_out.SGLANG_AMD_MONO_K3_K2_OPT).kimi_k31/spec.py: steps of up to 8 rows run thekimi_k3launches; DSpark and DFLASH verify steps above 8 rows keep [Feat] [MI355X] kimi_k31: Wide-row layer launch for Kimi-K3.1 verify steps #102's wide launch.SGLANG_AMD_MONO_K31_WIDE=0serves the narrow steps only, without ReplaySSM. The wide launch's requirements (ReplaySSM, 6 or 8 draft tokens, a speculative algorithm) are config refusals that name the switch.muse_spark/draft.py: the DFlash2 draft spec names its hidden size inrequires.hf_config. Kimi-K3.1's DFLASH draft is alsoDFlash2DraftModelwith model typeqwen3, so under--enable-amd-monokernelit picked up the Muse Spark spec and the load failed ('DFlashMLAAttention' object has no attribute 'qkv_proj'). SGLang keeps a draft's forward when the spec names another model ([Feat] [AMD] model: Add Kimi-K3.1 MI35x support sglang#48427).common: the sentinel-word helpers (sync.py), wave and CTA prefix scans (ops.py).test/kernels/kimi_k3(K1, K2 and mla_pre against torch references,check_k2,time_k2),test/unit/test_kimi_k3_spec.py,test_kimi_k31_spec.py(narrow / wide routing), and the forward drift pins re-read against the current SGLang..github/CODEOWNERS, README.Tested against SGLang sgl-project/sglang#48427 (
kimi-k3.1-day-0-amd, which carries the_mono_pre/q_nope_outhooks) plus its binding fix.Accuracy Tests
Kimi-K3.1-Pro, DFLASH (
K31-DFlash2-MLA5-...-step55000, 6 draft tokens), TP8 on 8x MI350X,--enable-linear-replayssm-spec, on sgl-project/sglang#48427 plus its binding fix:main(other models' contracts against this SGLang); every kimi_k3 / kimi_k31 test passesSpeed Tests and Profiling
Step time of one request (cc1, 10K-token prompts, 1024 out, real acceptance, median over 2-3 rounds), same SGLang tree and session:
1ce5a34, then the final commit)mainThe gap to the pre-merge build is within run-to-run spread (13.42 .. 13.51 ms across earlier runs of that build). Verify steps of 2 .. 48 requests run #102's wide launch unchanged and were not re-measured here.
Not covered: DCP8 on the narrow path (the MLA front is declined under DCP; K1 and the layer launch were measured at DCP1 only).
Checklist
pre-commit run --all-filespasses.test/cover the change..github/CODEOWNERSthat names its owner.🤖 Generated with Claude Code