Skip to content

Add SGLang Kimi-K3 for MI355X - #183

Open
coketaste wants to merge 2 commits into
ROCm:developfrom
coketaste:coketaste/add_sglang_kimi_k3
Open

Add SGLang Kimi-K3 for MI355X#183
coketaste wants to merge 2 commits into
ROCm:developfrom
coketaste:coketaste/add_sglang_kimi_k3

Conversation

@coketaste

Copy link
Copy Markdown
Contributor

Summary

Adds pyt_sglang_kimi-k3 and pyt_sglang_kimi-k3_dspark, benchmarking
moonshotai/Kimi-K3 online serving with SGLang on MI355X. Both track the AMD
day-0 recipes in sgl-project/sglang#32548 (day-0 support: sgl-project/sglang#32541).

  • Two model entries rather than one: the two published recipes differ only in
    speculative decoding (DSPARK with the RadixArk/Kimi-K3-DSpark draft) and are
    reported as separate rows in the tracking issue. They share a model repo, so
    the runner gains a --variant filter to select between them.
  • New scripts/sglang/run_sglang.py + scripts/sglang/configs/kimi_k3.yaml:
    a config-driven online serving runner structured after
    scripts/vllm/run_vllm.py, emitting the same perf CSV schema so
    multiple_results ingestion is shared. The existing
    scripts/sglang/run.sh (offline bench_one_batch / bench_offline_throughput
    path, gated to gfx94x) is untouched.
  • New docker/pyt_sglang_kimi_k3.ubuntu.amd.Dockerfile, pinned to
    lmsysorg/sglang-rocm:rocm720-mi35x-k3-20260727, the day-0 image the
    issue's MI355X tables were measured against — kept separate from
    docker/pyt_sglang (still on lmsysorg/sglang:v0.4.5-rocm630) so the
    existing SGLang entry doesn't move onto a pre-release base. Fold back once
    K3 lands in a versioned ROCm image.
  • TP8 gfx950 only (skip_gpu_arch: gfx942). Both entries are left out of any
    sweep tag so a tag run does not pull the ~1.56 TB checkpoint and hold 8
    GPUs; they're invocable explicitly by name.

Deviations from the recipe (intentional)

  • Runner emits --tp-size, not the recipe's --tp: there is no --tp server
    argument, tp_size declares the single alias --tensor-parallel-size, and
    --tp only resolves through argparse prefix matching, which any future
    --tp* option would silently break.
  • Server-start timeout raised to 5400s (SGLANG_SERVER_START_TIMEOUT) from
    run_vllm.py's 1800s, which is tight for a checkpoint this size.
  • No gsm8k accuracy stage: K3's always-on reasoning is returned inline over
    /v1/completions and exhausts the hardcoded 2048-token budget, making the
    score meaningless (same reasoning as the sibling vLLM K3 entry).
  • Input/output lengths (8192/1024) aren't stated in the issue; they're
    recovered from its own tables — (E2EL - TTFT) / TPOT + 1 lands on ~1024
    output tokens on every row, and concurrency * (inp + out) / E2EL
    reproduces the reported total throughput only at 8192 input tokens.
    --random-range-ratio is pinned to 1.0 to keep that shape (it defaults to
    0.0, which randomizes lengths down to a single token).

Verification

Verified statically only, no hardware run:

  • Config expansion (expand_configs) yields 5 configs per variant, and the
    --variant filter separates nospec/dspark correctly.
  • All 14 server flags and 11 benchmark flags were checked against
    [Kimi] Support kimi-k3 sgl-project/sglang#32541's head branch (not mainkimi_k3 is absent
    from main's reasoning DetectorMap, so the parser names and DSPARK
    support only exist inside the pinned image).
  • sglang.benchmark.serving's CLI flags, output JSON keys, and append-mode
    --output-file behavior were checked against the upstream source, matching
    what run_sglang.py expects.
  • Synthetic results were fed through the CSV writer; schema matches
    multiple_results ingestion.
  • filter_images_by_skip_gpu_arch skips both new entries on gfx942 and runs
    them on gfx950, with no existing entry affected.

Test plan

  • Run pyt_sglang_kimi-k3 on an 8x MI355X node and confirm the server
    starts and perf_Kimi-K3.csv is produced with the expected metrics.
  • Run pyt_sglang_kimi-k3_dspark and confirm the accept_length column
    is populated.
  • Confirm both entries are skipped on gfx942 hardware.

coketaste and others added 2 commits July 28, 2026 17:22
Add pyt_sglang_kimi-k3 and pyt_sglang_kimi-k3_dspark benchmarking
moonshotai/Kimi-K3 online serving, mirroring the vLLM K3 entry added in
a40063d. Both track the AMD day-0 recipes in sgl-project/sglang#32548;
K3 support itself is sgl-project/sglang#32541.

Two entries rather than one because the two published recipes differ
only in speculative decoding (DSPARK with the RadixArk/Kimi-K3-DSpark
draft) and are reported as separate rows in the tracking issue, so both
are worth tracking. They share a model repo, which is why the runner
gains a --variant filter: the existing --model filter cannot select
between them.

Add scripts/sglang/run_sglang.py and configs/, a config-driven serving
runner structured after scripts/vllm/run_vllm.py and emitting the same
perf CSV schema, so multiple_results ingestion is shared. The existing
scripts/sglang/run.sh is left untouched; it is bound to the offline
getopts path and hard-exits on non-gfx94* GPUs.

Add docker/pyt_sglang_kimi_k3 pinned to
lmsysorg/sglang-rocm:rocm720-mi35x-k3-20260727, the day-0 image the
issue's MI355X tables were measured against, rather than retargeting
docker/pyt_sglang, which is still on lmsysorg/sglang:v0.4.5-rocm630 and
would move the existing SGLang entry onto a pre-release base. A newer
-20260728 tag exists but nothing published ties it to the recipe, so it
is deliberately not adopted. Fold back once K3 lands in a versioned ROCm
image.

TP8 gfx950 only, hence skip_gpu_arch gfx942. Both are left out of any
sweep tag so a tag run does not pull the checkpoint and hold 8 GPUs;
they are invocable explicitly by name.

Three deviations from the recipe are intentional. The runner emits
--tp-size where the recipe writes --tp: there is no --tp server
argument, tp_size declares the single alias --tensor-parallel-size, and
--tp resolves only through argparse prefix matching, which any future
--tp* option would silently break. The server-start timeout is raised to
5400s from run_vllm.py's 1800s, which that commit already flagged as
tight for a checkpoint this size. There is no gsm8k accuracy stage, for
the same reason as the vLLM entry: K3's always-on reasoning is returned
inline over /v1/completions and exhausts the hardcoded 2048-token
budget.

The issue does not state its input and output lengths. They were
recovered from its own tables, where (E2EL - TTFT) / TPOT + 1 lands on
~1024 output tokens on every row and concurrency x (inp + out) / E2EL
reproduces the reported total throughput only at 8192 input tokens;
keeping that shape is what makes these numbers comparable to the issue's.
--random-range-ratio is pinned to 1.0 because it defaults to 0.0, which
would randomize lengths down to a single token.

Verified statically only, no hardware run. Config expansion yields 5
configs per variant and the variant filter separates them; an
end-to-end dry run with subprocess stubbed produced the expected server
and benchmark argv, both hf download calls, and correctly ignored a
stale leading line in the appended JSONL output. All 14 server flags and
11 benchmark flags were validated against #32541's head branch rather
than sglang main, which matters: the PR is still open and kimi_k3 is
absent from main's reasoning DetectorMap, so the parser names and DSPARK
are only valid inside the pinned image. Synthetic results were fed
through madengine's handle_multiple_results, and
filter_images_by_skip_gpu_arch skips both entries on gfx942 and runs
them on gfx950 with no existing entry changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Blueprints table in the root README is the entry point to each
framework's landing page, so the SGLang row's Models column should name
K3 now that both entries exist. The landing page itself,
benchmark/sglang/README.md, was updated in ede3844.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coketaste coketaste self-assigned this Jul 28, 2026
Copilot AI review requested due to automatic review settings July 28, 2026 23:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new MAD benchmarks for SGLang online serving of moonshotai/Kimi-K3 on MI355X (gfx950/TP8), including a DSpark speculative-decoding variant, using a dedicated ROCm day-0 Docker image and a new config-driven serving runner.

Changes:

  • Introduces scripts/sglang/run_sglang.py (config-driven SGLang online serving benchmark runner) and scripts/sglang/configs/kimi_k3.yaml (nospec + dspark variants).
  • Adds scripts/sglang/run_kimi_k3.sh entrypoint and registers two new model entries in models.json.
  • Adds a dedicated Dockerfile pinned to the MI35x K3 day-0 image and updates docs/README to list Kimi-K3 under SGLang.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
scripts/sglang/run_sglang.py New config-driven SGLang online serving runner producing MAD multiple-results CSV output.
scripts/sglang/run_kimi_k3.sh Entry script to execute the Kimi-K3 serving benchmark and move perf CSV to parent dir.
scripts/sglang/configs/kimi_k3.yaml Serving sweep configuration for Kimi-K3 nospec/dspark variants (8192/1024, conc 2–32).
models.json Adds two new SGLang Kimi-K3 benchmark entries (nospec + dspark) gated off gfx942.
docker/pyt_sglang_kimi_k3.ubuntu.amd.Dockerfile Dedicated ROCm day-0 SGLang image pinned for Kimi-K3 support on MI35x.
benchmark/sglang/README.md Documents the special-case Kimi-K3 entries, invocation, and rationale for settings.
README.md Adds Kimi-K3 to the top-level supported SGLang models list.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +256 to +258
# only reported under speculative decoding
if output.get("accept_length"):
metrics["accept_length"] = str(output["accept_length"])
Comment on lines +274 to +281
finally:
# kill server and children
parent = psutil.Process(server.pid)
for child in parent.children(recursive=True):
child.send_signal(signal.SIGINT)
server.send_signal(signal.SIGINT)
_ = server.communicate()
del server
Comment on lines +145 to +148
# split config into common args and list args
common_cfgs = {k: v for k, v in cfg.items() if k not in SUPPORTED_LIST_ARGS}
list_cfgs = {k: str(v).split(' ') for k, v in cfg.items() if k in SUPPORTED_LIST_ARGS}
# expand list args into one dict per combination
Comment on lines +59 to +64
python3 -u run_sglang.py --config $CONFIG --model $MODEL --variant $VARIANT

# move the output csv to parent directory
MODEL_NAME=$(basename $MODEL)
OUTPUT_CSV="perf_${MODEL_NAME}.csv"
mv $OUTPUT_CSV ../
Comment on lines +49 to +50
# record configuration for posterity
RUN pip3 list
@coketaste coketaste changed the title Add SGLang Kimi-K3 for MI355X [WIP] Add SGLang Kimi-K3 for MI355X Jul 29, 2026
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.

2 participants