Skip to content

Kimi K3 vllm GB200 Agentx - #2639

Merged
functionstackx merged 10 commits into
mainfrom
nv/k3-gb200
Aug 20, 2026
Merged

Kimi K3 vllm GB200 Agentx#2639
functionstackx merged 10 commits into
mainfrom
nv/k3-gb200

Conversation

@wzhao18

@wzhao18 wzhao18 commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

@github-actions

Copy link
Copy Markdown
Contributor

Thanks for the contribution! Please reach out to respective companies' CODEOWNER to fill in the latest PR_REVIEW_CHECKLIST.md before pinging core maintainer on Slack for review. In order for the signoff PR check bot to trigger, you must follow the PR_REVIEW_CHECKLIST.md template correctly, including the phrase As a PR reviewer and CODEOWNER, I have reviewed this and have.

For PR verification, add the full-sweep-fail-fast label (strongly recommended) to this PR — the benchmark sweep only runs on labeled PRs. Use full-sweep-enabled only if you need matrix jobs to keep running past a failure.

PR authors are responsible for ensuring that after merging, all GitHub Action jobs fully pass. A lot of the time, failures are just flakes and simply re-running the failed jobs will fix it. See GitHub's docs on re-running failed jobs


感谢你的贡献!请联系相应公司的 CODEOWNER 填写最新的 PR_REVIEW_CHECKLIST.md,然后再在 Slack 上联系核心维护者进行审阅。为了触发 signoff PR 检查机器人,你必须正确遵循 PR_REVIEW_CHECKLIST.md 模板,包括保留英文语句 As a PR reviewer and CODEOWNER, I have reviewed this and have

如需进行 PR 验证,请为此 PR 添加 full-sweep-fail-fast 标签(强烈推荐)— 基准测试 sweep 仅在带有标签的 PR 上运行。仅当需要矩阵任务在失败后继续运行时才使用 full-sweep-enabled

PR 作者有责任确保合并后所有 GitHub Action 任务完全通过。 很多时候失败只是偶发抖动(flake),重新运行失败的任务即可解决。参见 GitHub 关于重新运行失败任务的文档

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for the contribution! Please reach out to respective companies' CODEOWNER to fill in the latest PR_REVIEW_CHECKLIST.md before pinging core maintainer on Slack for review. In order for the signoff PR check bot to trigger, you must follow the PR_REVIEW_CHECKLIST.md template correctly, including the phrase As a PR reviewer and CODEOWNER, I have reviewed this and have.

For PR verification, add the full-sweep-fail-fast label (strongly recommended) to this PR — the benchmark sweep only runs on labeled PRs. Use full-sweep-enabled only if you need matrix jobs to keep running past a failure.

PR authors are responsible for ensuring that after merging, all GitHub Action jobs fully pass. A lot of the time, failures are just flakes and simply re-running the failed jobs will fix it. See GitHub's docs on re-running failed jobs


感谢你的贡献!请联系相应公司的 CODEOWNER 填写最新的 PR_REVIEW_CHECKLIST.md,然后再在 Slack 上联系核心维护者进行审阅。为了触发 signoff PR 检查机器人,你必须正确遵循 PR_REVIEW_CHECKLIST.md 模板,包括保留英文语句 As a PR reviewer and CODEOWNER, I have reviewed this and have

如需进行 PR 验证,请为此 PR 添加 full-sweep-fail-fast 标签(强烈推荐)— 基准测试 sweep 仅在带有标签的 PR 上运行。仅当需要矩阵任务在失败后继续运行时才使用 full-sweep-enabled

PR 作者有责任确保合并后所有 GitHub Action 任务完全通过。 很多时候失败只是偶发抖动(flake),重新运行失败的任务即可解决。参见 GitHub 关于重新运行失败任务的文档

@github-actions

Copy link
Copy Markdown
Contributor

Comment thread perf-changelog.yaml Outdated
Comment on lines +6079 to +6088
- config-keys:
- kimik3-fp4-gb200-dynamo-vllm-agentic-dspark-mooncake-dcp16-disagg
- kimik3-fp4-gb200-dynamo-vllm-agentic-dspark-mooncake-dcp16-agg
- kimik3-fp4-gb200-dynamo-vllm-agentic-mooncake-dcp16-agg
scenario-type:
- agentic-coding
description:
- "Add Kimi-K3 GB200 DCP16 AgentX configurations with Mooncake DRAM offload."
- "Cover 1P1D, DSpark max-num-seqs 2, and no-spec aggregate profiles using the rebuilt vLLM image."
pr-link: TBD

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.

🔴 perf-changelog.yaml still has pr-link: TBD (line 6088), but this diff is PR #2639, which already exists. Per docs/configuration-procedures.md:254, TBD is only a placeholder used before the PR exists and must be replaced with the real URL immediately after creation; line 272 lists a lingering TBD as a hard stop condition that blocks sweep readiness. Fix: set pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2639.

Extended reasoning...

What's wrong

The new perf-changelog.yaml entry added by this PR (lines 6079-6088) leaves pr-link: TBD. Every sibling entry in the same file — including the three immediately preceding this one (PRs #2621, #2619, #2636) — carries a concrete https://github.com/SemiAnalysisAI/InferenceX/pull/<n> URL. This new entry is the odd one out.

Why it's a bug, not a style nit

docs/configuration-procedures.md:254 spells out the exact rule this repo enforces for this field:

Before the PR exists, the model+hardware playbook permits pr-link: TBD. Replace it with the real URL immediately after creating the PR.

And docs/configuration-procedures.md:272 lists a stop condition that blocks a config from being sweep-ready:

The changelog change ... still has TBD when the PR is otherwise ready for sweep.

This diff is PR #2639 (per pr-metadata: created 2026-08-18, title "Test Kimi Agentx GB200"). Since the PR already exists at the time this changelog entry is being added, the TBD placeholder condition ("before the PR exists") no longer applies — the entry should have been created with (or promptly updated to) the real URL, not left as TBD.

Why nothing else catches this

YAML parsing/schema validation won't flag pr-link: TBD as invalid — it's a syntactically valid string in a string field, so a naive "does this file parse" check passes. The enforcement is procedural: troubleshooting.md confirms this correction is "enforced by the validator, not by a visually valid YAML parse," i.e. it requires a dedicated readiness check that inspects the value semantically, not the YAML loader itself. Nothing in this diff's three other changed files (the two agg recipes, the disagg recipe, or configs/nvidia-master.yaml) touches or re-derives this field, so it will persist as-is unless someone catches it in review.

Step-by-step proof

  1. docs/configuration-procedures.md:254 establishes: TBD is valid only while the PR does not yet exist.
  2. pr-metadata for this diff shows PR Kimi K3 vllm GB200 Agentx #2639 already created at 2026-08-18T02:35:20Z.
  3. Therefore, at the time this changelog entry exists in the diff, the PR already exists, and the "before PR exists" exception no longer holds.
  4. The entry at perf-changelog.yaml:6088 reads pr-link: TBD, violating the "replace immediately after creating the PR" instruction.
  5. docs/configuration-procedures.md:272 explicitly lists "still has TBD when the PR is otherwise ready for sweep" as a stop condition — meaning a downstream readiness validator will block this configuration from being marked sweep-ready until fixed.
  6. Fix: change line 6088 to pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2639, matching the convention used by every adjacent entry (.../pull/2621, .../pull/2619, .../pull/2636).

Fix

  pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2639

Comment on lines +119 to +146
tensor-parallel-size: 16
decode-context-parallel-size: 16
enable-cumem-allocator: true
trust-remote-code: true
no-enable-flashinfer-autotune: true
max-cudagraph-capture-size: 512
# Cap prefill scheduling below the available Mamba cache-block count.
# The largest configured benchmark point is c48.
max-num-seqs: 512
stream-interval: 10
max_num_batched_tokens: 16384
language-model-only: true
attention-backend: "TOKENSPEED_MLA"
attention-config: '{"mla_prefill_backend": "TRTLLM_RAGGED", "use_prefill_query_quantization": true}'
speculative-config: '{"model":"Inferact/Kimi-K3-DSpark","attention_backend":"TOKENSPEED_MLA","method":"dspark","num_speculative_tokens":4,"draft_sample_method":"probabilistic","rejection_sample_method":"block"}'
# Explicit budgets leave room for the TP16/DCP16 all-gather and graph
# workspace on a 184 GiB GB200 GPU.
kv-cache-memory: 10737418240
decode:
kv-transfer-config: '{"kv_connector":"MultiConnector","kv_role":"kv_both","kv_load_failure_policy":"recompute","kv_connector_extra_config":{"connectors":[{"kv_connector":"NixlConnector","kv_role":"kv_both","kv_load_failure_policy":"fail","kv_buffer_device":"cuda","kv_connector_extra_config":{"enforce_handshake_compat":false,"enable_cross_layers_blocks":false}},{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_both","kv_load_failure_policy":"recompute","kv_connector_extra_config":{"load_async":true,"lookup_async":true,"enable_cross_layers_blocks":false,"enable_offload":false}}]}}'
served-model-name: "moonshotai/Kimi-K3"
enable-prefix-caching: true
prefix-match-unit: 128
load-format: "safetensors"
safetensors-load-strategy: "lazy"
kv-cache-dtype: "fp8"
tensor-parallel-size: 16
decode-context-parallel-size: 16

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.

🟡 The disagg Kimi-K3 DCP16 recipe never sets dcp-comm-backend in its prefill (line 120) or decode (line 146) vllm_config blocks, even though decode-context-parallel-size: 16 is set in both. The two sibling GB200 DCP16 aggregate recipes added in this same PR (and the single-node Kimi-K3 vLLM launcher) always pin dcp-comm-backend: "a2a" alongside DCP16, so this recipe likely runs on a different, unvalidated DCP collective backend than its siblings, undermining benchmark comparability. Recommend adding dcp-comm-backend: "a2a" to both blocks to match the agg profiles.

Extended reasoning...

Both new sibling aggregate recipes in this PR (agg-gb200-dcp16-dspark4-maxseq2-mooncake-agentic.yaml:92 and agg-gb200-dcp16-nospec-mooncake-agentic.yaml:92) pair decode-context-parallel-size: 16 with an explicit dcp-comm-backend: "a2a" line. The disagg recipe added in the same PR sets the identical decode-context-parallel-size: 16 in both its prefill (line 120) and decode (line 146) vllm_config blocks, but never sets dcp-comm-backend in either block. The existing single-node Kimi-K3 launcher (kimik3_fp4_b300_vllm_mtp.sh:47) reinforces that this is a deliberate, non-default pairing for this model: it unconditionally appends --dcp-comm-backend a2a any time DCP is enabled, which would be redundant if vLLM's default DCP backend were already a2a.

The internal-consistency signal is the strongest piece of evidence: the disagg recipe's prefill_environment/decode_environment block (shared via the &kimi_env YAML anchor) sets VLLM_USE_DIRECT_DCP_A2A: "0", VLLM_USE_DIRECT_DCP_Q_GATHER: "0", and VLLM_USE_DIRECT_DCP_KV_GATHER: "0" — the exact tuning knobs that only have meaning once the a2a DCP backend is actually selected. The agg siblings carry the same env vars and explicitly pin dcp-comm-backend: "a2a"; the disagg recipe carries the env vars but omits the backend selector that activates them. That looks like an oversight rather than an intentional divergence, since the author clearly intended to carry over the a2a-specific tuning.

Proof by walkthrough: (1) agg-gb200-dcp16-nospec sets tensor-parallel-size: 16, decode-context-parallel-size: 16, dcp-comm-backend: "a2a" at lines 90-92. (2) The disagg recipe's decode block sets the same tensor-parallel-size: 16 and decode-context-parallel-size: 16 at lines 145-146, but the next config key is enable-cumem-allocator — dcp-comm-backend is simply absent. (3) When vLLM parses this config, it falls back to whatever its internal default DCP comm backend is (not necessarily a2a), so the actual collective implementation exercised on the disagg workers can differ from the agg siblings' validated a2a path, even though every other DCP-adjacent knob (the VLLM_USE_DIRECT_DCP_* env vars) is identical.

The refutation raises a fair point: without confirming vLLM's actual default DCP backend, we can't be certain this causes a functional divergence — if the default already resolves to a2a, the omission is harmless redundancy elsewhere. It's also correct that the DeepSeek-V4 launchers use DCP without an explicit backend, showing the pattern isn't universal across models in this repo. But that only shows DCP-without-backend is acceptable for DeepSeek; it doesn't establish that a2a is the vLLM default, and the Kimi-K3-specific evidence (single-node launcher's unconditional flag, and the a2a-only env knobs mirrored in this exact recipe) points the other way. Because there's no crash and the recipe still executes and returns results either way, this reads as a benchmark-fidelity/consistency gap rather than a functional break — the disagg numbers might not be comparable to the agg numbers the PR is meant to validate against.

Fix: add dcp-comm-backend: "a2a" to both the prefill (near line 120) and decode (near line 146) vllm_config blocks in disagg-gb200-1p1d-dcp16-dcp16-dspark4-mooncake-agentic.yaml, matching the two agg siblings added in this PR.

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

@wzhao18 wzhao18 changed the title Test Kimi Agentx GB200 Kimi K3 vllm GB200 Agentx Aug 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

@functionstackx

Copy link
Copy Markdown
Collaborator

/stage-results 32180077157

@functionstackx

Copy link
Copy Markdown
Collaborator

/reuse-sweep-run 32180077157

@functionstackx

Copy link
Copy Markdown
Collaborator

/stage-results 32180077157

@cquil11

cquil11 commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator
CleanShot 2026-08-19 at 15 06 13

@cquil11

cquil11 commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

/stage-results 32180077157

@xinli-sw

Copy link
Copy Markdown
Collaborator

@cquil11 how do we move forward with this ? worse case we trigger a re-run, lmk :)

Add TP16/DCP16 Mooncake configurations for 1P1D and aggregate AgentX coverage using the rebuilt vLLM image.

新增使用重建 vLLM 镜像的 TP16/DCP16 Mooncake 配置,覆盖 1P1D 与聚合 AgentX 场景。

Co-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Wei Zhao <51183510+wzhao18@users.noreply.github.com>
Updated PR link for Kimi-K3 GB200 DCP16 AgentX configurations.
Use the same NVIDIA/srt-slurm v1.0.36 tag as the GB300 AgentX profiles so Mooncake-backed DCP16 recipes use the expected schema.

与 GB300 AgentX 配置统一使用 NVIDIA/srt-slurm v1.0.36,确保 Mooncake DCP16 配置使用兼容的 schema。

Co-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Wei Zhao <51183510+wzhao18@users.noreply.github.com>
Keep max-num-seqs below the Mamba page capacity provided by the explicit 10 GiB KV cache allocation.

Co-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Wei Zhao <51183510+wzhao18@users.noreply.github.com>
wzhao18 and others added 6 commits August 19, 2026 20:26
Drop the 1P1D DCP16/DCP16 disaggregated profile and sweep the two
aggregate arms across their intended concurrency ranges: max-num-seqs
512 over 8-48 for the no-spec arm, max-num-seqs 2 over 1-16 for the
DSpark K=4 arm.

Load weights with fastsafetensors and size the KV cache from
gpu-memory-utilization 0.92 (matching agg-gb200-tp16-latency) instead of
an explicit 10 GiB kv-cache-memory budget.

Mooncake's global_segment_size is per TP rank, so the 96GB setting took
4 x 96 GiB = 412 GB per four-GPU GB200 node while dram-utilization
0.1065 reported only 96 GB. Use 128 GiB per rank (512 GiB per node) with
dram-utilization 0.61, the budget already validated for Kimi-K3 on
cluster:gb200-nv and consistent with the DeepSeek-V4 GB200 recipes.

Signed-off-by: Wei Zhao <51183510+wzhao18@users.noreply.github.com>

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Wei Zhao <51183510+wzhao18@users.noreply.github.com>

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Run 32144394011 failed all three DCP16 aggregate points with two
distinct out-of-memory errors.

The DSpark arm died in fastsafetensors get_empty_tensor at shard 5/6:
a 2.19 GiB staging buffer failed with 47.58 GiB free, i.e. HBM
fragmentation rather than exhaustion. Every other GB200 Kimi-K3 recipe
sets PYTORCH_ALLOC_CONF=expandable_segments:True and these two did not,
including the two siblings that load a DSpark draft under fastsafetensors
without trouble.

The no-spec arm loaded, then OOMed in cudagraph capture_end at graph
57/83 with the KV cache at 30.34 GiB. Graph 57 is capture size 608 --
above max-num-seqs 512, and with no drafting capture sizes are sequences,
so 32 of the 83 graphs were unreachable. Cap the ladder at max-num-seqs
and give the graph pool 3.68 GiB back by derating to 0.90; the DSpark
arm's ladder is capped at 64 for the same reason, since 2 seqs x (1+4)
tokens can never exceed 10.

Signed-off-by: Wei Zhao <51183510+wzhao18@users.noreply.github.com>

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Capture sizes are tokens when drafting and prefill batches run on the
captured graphs too, so a 64-wide ladder would have pushed short
prefills into eager mode. Match the no-spec arm at 512, which still
drops the tail above 512 where cudagraph capture OOMed.

Signed-off-by: Wei Zhao <51183510+wzhao18@users.noreply.github.com>

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Run 32155647152 sat in the health-check loop for over 90 minutes with
no worker registering and no crash, so the fastsafetensors path is not
worth further iteration on GB200.

- Restore load-format safetensors with the lazy strategy on both
  aggregate arms. Slower, but it does not stage shards on the GPU.
- Derate gpu-memory-utilization to 0.85. At 0.92 the KV cache took
  30.34 GiB and cudagraph capture OOMed; 0.85 leaves the graph pool,
  the FlashInfer MoE workspace and fragmentation more room.
- Cut the health-check window from 2 hours to 1 (360 x 10s), matching
  VLLM_ENGINE_READY_TIMEOUT_S, so a wedged worker fails fast instead of
  holding four GB200 nodes for a second idle hour.

Signed-off-by: Wei Zhao <51183510+wzhao18@users.noreply.github.com>

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Roll the two aggregate recipes back to 55d3cd5, keeping only the two
intended changes on top: drop the 1P1D DCP16 disaggregated profile and
sweep the aggregate arms across concurrency.

The tuning attempts layered on since then are all reverted -- the
fastsafetensors loader, the removed kv-cache-memory budget, the
gpu-memory-utilization derate, the narrowed cudagraph ladder, the
expandable-segments allocator config, the 128 GiB Mooncake segment and
the shortened health-check window. Neither aggregate arm has completed a
run at these settings, so keep the checked-in baseline and change one
thing at a time from here.

Signed-off-by: Wei Zhao <51183510+wzhao18@users.noreply.github.com>

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@functionstackx
functionstackx merged commit 64c7b61 into main Aug 20, 2026
4 of 6 checks passed
@functionstackx
functionstackx deleted the nv/k3-gb200 branch August 20, 2026 00:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

4 participants