[AgentX] Mirror GB300 MTP tuning (#2571) to GB200 with 4-GPU->8-GPU workers - #2619
[AgentX] Mirror GB300 MTP tuning (#2571) to GB200 with 4-GPU->8-GPU workers#2619xinli-sw wants to merge 11 commits into
Conversation
|
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 For PR verification, add the 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 模板,包括保留英文语句 如需进行 PR 验证,请为此 PR 添加 PR 作者有责任确保合并后所有 GitHub Action 任务完全通过。 很多时候失败只是偶发抖动(flake),重新运行失败的任务即可解决。参见 GitHub 关于重新运行失败任务的文档 |
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=31893849841 |
| description: | ||
| - "Inject the committed synthetic MTP acceptance length only for GB300 AgentX throughput; keep eval-only jobs on real target verification." | ||
| pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2571 | ||
|
|
||
|
|
||
| - config-keys: | ||
| - dsv4-fp4-gb200-dynamo-vllm-agentic-mtp2-agg | ||
| - dsv4-fp4-gb200-dynamo-vllm-agentic-mtp2-disagg | ||
| scenario-type: | ||
| - agentic-coding | ||
| description: | ||
| - "Add GB200 DeepSeek-V4-Pro FP4 Dynamo-vLLM AgentX mirroring the GB300 PR #2571 MTP tuning, with every GB300 4-GPU worker sized to 8 GPUs on GB200." | ||
| pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/XXX | ||
|
|
There was a problem hiding this comment.
🔴 perf-changelog.yaml is documented as append-only and byte-sensitive (AGENTS.md), but this diff rewrites the prior entry's trailing separator line — changing it from two trailing spaces to a plain empty line — instead of leaving it untouched and appending after it. This mutates historical bytes and fails utils/validate_perf_changelog.py's validate_raw_change check (head_raw.startswith(base_raw)), which is enforced in CI by run-sweep.yml's "Validate perf-changelog matrix" step. Fix: restore the original two-space separator line ( \n) after the pull/2571 pr-link and append the new entry after that.
Extended reasoning...
What the bug is: AGENTS.md states the perf-changelog invariant explicitly: "The file is append-only and byte-sensitive. Preserve all existing bytes and separator whitespace, and append only at the tail." This PR's diff to perf-changelog.yaml violates that invariant by modifying an existing byte sequence rather than purely appending.
Where it happens: At the tail of the base file (verified via git show d136fa6:perf-changelog.yaml), the previous entry ends with:
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2571
<- this line is two literal spaces, then a newline
The diff shows:
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2571
-
+
+- config-keys:
+ ...
i.e. it deletes the two-space separator line and inserts a plain empty line before appending the new entry. That is an edit to a historical byte, not an append.
Why nothing else catches this: The file is YAML, so a two-space line and an empty line are semantically identical to a YAML parser — nothing in normal linting or schema validation would flag this. The invariant is enforced by a dedicated byte-level tool, not by YAML semantics.
Why it matters / the concrete failure mode: utils/validate_perf_changelog.py's validate_raw_change function requires head_raw.startswith(base_raw) whenever changelog entries are appended, raising ChangelogValidationError('appended entries changed historical perf-changelog.yaml bytes; restore the base file byte-for-byte and append at the end') otherwise. Because the base file's byte immediately after pull/2571\n is a space (' ') and the head file's corresponding byte is a newline ('\n'), head_raw.startswith(base_raw) is False, so this raises. This validator runs in CI as the "Validate perf-changelog matrix" step in .github/workflows/run-sweep.yml (with --base-ref origin/main and the PR head as --head-ref), and is also invoked by prepare_perf_changelog_merge.py / utils/merge_with_reuse.sh, the canonical merge path for these PRs. So this isn't a style nit — it's a required, automated gate that will fail as the diff currently stands.
Step-by-step proof:
git show d136fa6:perf-changelog.yaml | tail -1shows the last line is" "(two spaces), confirmed viacat -Ashowing$(two spaces before the end-of-line marker).base_raw(bytes oforigin/main'sperf-changelog.yaml) therefore ends in...pull/2571\n \n.- The PR diff replaces that final
\nline with a bare\n, then appends the new entry, sohead_rawat that same offset reads...pull/2571\n\n- config-keys:.... head_raw.startswith(base_raw)compares byte-by-byte: both match throughpull/2571\n, but the next base byte is' 'while the corresponding head byte is'\n'— mismatch, sostartswithreturnsFalse.validate_raw_changeraisesChangelogValidationError, which fails the "Validate perf-changelog matrix" CI job.
Fix: Leave the original two-space separator line intact after the pull/2571 line, and append the new - config-keys: entry after it (rather than replacing it with a blank line). This is a trivial one-line whitespace fix.
4cabf21 to
9749e1e
Compare
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=31904915528 |
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=31907559278 |
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=31920499327 |
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=31923718025 |
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=31907559278 |
…orkers Adds a GB200 counterpart to the GB300 AgentX DSV4 MTP recipes tuned in PR #2571. Every setting is copied unchanged except workers that used 4 GPUs on GB300 now use 8 on GB200 (agg TP4->TP8, disagg prefill DEP4->DEP8); worker sizes that were already 8/12/16 GPUs are untouched. New recipe files and dsv4-fp4-gb200-dynamo-vllm-agentic-mtp2-{agg,disagg} master-config keys are kept separate from the existing GB200 AgentX MTP recipes/keys, which have unrelated tuning and are left untouched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The GB300-pinned nightly-dev-arm64-cu13.0.1-426e59f tag is an ephemeral dev-branch build that has already been pruned from Docker Hub, and it exists specifically to carry deep_gemm_amxf4_mega_moe (W4A4 MegaMoE) support that isn't in stock vLLM nightly. Since these GB200 recipes don't need to stay on that dev branch, switch to vllm/vllm-openai:nightly and drop back to the regular deep_gemm_mega_moe backend that stock nightly supports. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…gaMoE" This reverts commit 9749e1ef489e06744ff661e5eb5f97036e613ea3.
Job 23562 (disagg-gb200-2p1d-dep8-dep16-c1024-mtp2-agentic, conc=1024) died silently mid-run: one prefill worker process was killed with no CUDA-OOM warning or traceback (exit code: None), which cascaded into an EngineDeadError and aborted the whole disagg job. No host-RAM telemetry was captured to confirm the cause, but the recipe reserves a 180GB host Mooncake KV-store segment per node on top of whatever vLLM/Dynamo itself uses, so as a mitigation: drop global_segment_size to 160GB across all three GB200 mtp2 disagg recipes, and halve each large-conc file's target concurrency (and rename/re-point accordingly) to reduce memory pressure: c256 -> c128 (disagg-gb200-1p1d-dep8-dep8) c1024 -> c512 (disagg-gb200-2p1d-dep8-dep16) c1152 -> c576 (disagg-gb200-2p1d-dep8-dep12) configs/nvidia-master.yaml's mtp2-disagg search-space conc-list and CONFIG_FILE references are updated to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Job 23607 (disagg-gb200-1p1d-dep8-dep8-c128-mtp2-agentic) OOM'd during decode CUDA-graph capture: 183.24 GiB already in use on a 184 GiB GB200 GPU, then the capture-size warmup forward pass needed another 768 MiB it didn't have. The decode block's max-num-seqs (256) and max-cudagraph-capture-size (1024) were still sized for the pre-rename c256 concurrency, not the current c128 target. max-cudagraph-capture-size should track (num_speculative_tokens + 1) * max-num-seqs for MTP-3 decode graphs. Set decode max-num-seqs to 128 (matching the file's concurrency) and max-cudagraph-capture-size to 512 (4 * 128). The other two GB200 disagg mtp2 decode blocks (c576, c512) already satisfy this (64 * 4 = 256); prefill blocks are unaffected. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Job 23635 got past startup (decode capture-size fix from the previous commit held) but crashed ~4 min into serving: three prefill DP ranks hit torch.OutOfMemoryError inside the MTP speculator's draft-token prefill pass (speculator.py:_prefill -> wq_b block-scaled matmul), with the GPU already at 183.03/184 GiB in use. prefill's gpu-memory-utilization: 0.92 (copied from the GB300 source) reserves too much of the 184 GiB GB200 GPU for vLLM's static pool, leaving too little headroom for transient MTP draft-prefill activations on large-batch requests. Drop prefill gpu-memory-utilization to 0.85; decode is untouched since this failure was prefill-only. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2a41dd7 to
3914b27
Compare
Job 23715 (c576, global_segment_size 160GB) still died silently after ~1h51m of steady serving with no CUDA-OOM/cuBLAS error, matching the same host-RAM-exhaustion signature as job 23562 (180GB). Lower global_segment_size to 140GB across all three GB200 mtp2 disagg recipes as a further mitigation. Job 23714 (c128, fixed decode/prefill sizing) completed successfully. Its GPU KV-cache usage peaked at ~80% on prefill and ~39% on decode -- not maxed out -- so add the next concurrency point (256) on the same 1p1d dep8/dep8 topology rather than jumping to 2p1d: create disagg-gb200-1p1d-dep8-dep8-c256-mtp2-agentic.yaml as a clone of the working c128 file (decode max-num-seqs/max-cudagraph-capture-size and prefill gpu-memory-utilization left unchanged, since DEP8 replication already gives 8x the c128 file's per-rank max-num-seqs budget, well above a conc=256 target) and add its conc-list: [256] search-space entry to dsv4-fp4-gb200-dynamo-vllm-agentic-mtp2-disagg. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=31951030152 |
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=31965016666 |
1 similar comment
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=31965016666 |
|
/reuse-sweep-run 31965016666 |
kedarpotdar-nv
left a comment
There was a problem hiding this comment.
As a PR reviewer and CODEOWNER, I have reviewed this and have:
- Verified that as of the moment of typing this, this is the latest version of PR_REVIEW_CHECKLIST.md
- Verified that the general code quality meets the InferenceX standard and does not make the code quality any worse.
- Verified that this PR has passed PR validation. GitHub Actions run 31965016666
- Verified that this PR passes evals. GitHub Actions run 31965016666
- Verified that speculative decoding PRs uses chat templates to align the AL distribution to real world
- For agentic workloads: verified that speculative-decoding configs (EAGLE / MTP / draft models) run with simulated synthetic acceptance, with the acceptance-length value taken from the committed golden AL curve in golden_al_distribution/ for that model, thinking mode, and draft length. A submission may choose any supported draft length, but it may not substitute a different acceptance target.
- Verified against the current MODELS.md that this PR does not submit a deprecated model, scenario, or model-scenario combination.
- Verified that the model architecture isn't changed with benchmark hacks like using --hf-overrides to skipping indexer for every x layers on models that don't natively support this. As a general rule, we won't accept optimizations that reduces the number of model architecture FLOPs. Anything that makes that same computation run faster is fair game; FLOPs at lower precisions is fine, given that the config passes private evals. As an general north star princple, we should only use optimizations which is used in production by customers that care about accuracy
- If an company claims that they support vLLM/SGLang as first class LLM inference engines on their hardware, I have verified that the respective vLLM submission made using upstream https://hub.docker.com/u/vllm docker repo, upstream SGLang https://hub.docker.com/u/lmsysorg docker repo. The only exceptions are for new hardware, such as MI455X UALoE72, Vera Rubin NVL72, Rubin NVL8, etc., and for new model architectures where there is an actual reason why vLLM/SGLang does not fundamentally support them yet as supported by vLLM/SGLang community maintainers
- If an company claims that they support vLLM/SGLang as first class upstream in-tree LLM inference engines on their hardware, I have have verified that the respective vLLM/SGLang submission has been made before additional frameworks (TRT-LLM, ATOM, etc.). The only exceptions are for new hardware, such as MI455X UALoE72, Vera Rubin NVL72, Rubin NVL8, etc., and for new model architectures where there is an actual reason why vLLM/SGLang does not fundamentally support them yet.
- Verified that every single-node vLLM/SGLang recipe in this PR is documented in the official vLLM recipes and/or the SGLang cookbook:
- I linked the corresponding upstream PR in the vLLM recipe repo or SGLang repo and verified that it is MERGED before this InferenceX PR merges. An opened, draft, or closed-without-merge upstream PR does not satisfy this requirement. If the matching recipe was already published, I linked the published recipe/cookbook page in the additional detail section below.
- Verified that this PR does not patch the inference engine or serving stack — the pinned image must run as shipped. This covers .patch files / git apply / patch, inline patches embedded in benchmark scripts (e.g. a python3/sed heredoc that rewrites installed engine sources before serving), in-place edits of site-packages, monkey-patching, overwriting container files, and installing forked/rebuilt engine wheels on top of the pinned image. The only exception is a patch covered by a filled-out waiver at docs/waiver/
<PR_NUMBER>.md— named after the PR that introduces the patch and filed in that same PR, stating what is patched, why the unmodified upstream image cannot run this benchmark, the upstream PR/issue link, and the removal plan — which I have linked below in the additional detail section. - If this PR uses
append-only: true, verified that it only adds generated points or recipe variants inside a selected existing config/scenario and existing same-image visual curve: every previously generated point remains present with the same recipe, no prior point is removed or rerun, and every benchmark-affecting change in the complete diff can affect only the corresponding newly appended points (never an existing point), regardless of which file contains it. - If any of the above criteria cannot reasonably be satisfied, I have provided additional reasoning below.
Additional detail section:
- Run 31965016666 passed all seven unique GB200 AgentX benchmark points and all four selected eval variants.
- GSM8K strict-match scores were
0.9227–0.9295, above the required0.91threshold. - MTP uses three speculative tokens with synthetic acceptance length
2.49, matching the committed DeepSeek-V4-Prothinking_ongolden AL.EVAL_ONLYkeeps real target verification. - AgentX traffic uses the chat-completions endpoint.
- The submission uses the upstream
vllm/vllm-openai:nightly-dev-arm64-cu13.0.1-426e59fimage. - This PR contains only multi-node recipes, so the single-node upstream-recipe documentation requirement is not applicable.
- The diff contains no engine patch, model-architecture FLOP-reduction override, or
append-only: true. - Sweep reuse was authorized in this comment.
Signed: @kedarpotdar-nv
|
/stage-results 31965016666 |
|
@cquil11 staged run 31965016666: https://inferencemax-app-git-staging-semianalysisai.vercel.app/inference?i_dates=2026-08-16~r31965016666 This run remains available across future |
…4-GPU->8-GPU workers (SemiAnalysisAI#2619) * [AgentX] Mirror GB300 MTP tuning (SemiAnalysisAI#2571) to GB200 with 4-GPU->8-GPU workers Adds a GB200 counterpart to the GB300 AgentX DSV4 MTP recipes tuned in PR SemiAnalysisAI#2571. Every setting is copied unchanged except workers that used 4 GPUs on GB300 now use 8 on GB200 (agg TP4->TP8, disagg prefill DEP4->DEP8); worker sizes that were already 8/12/16 GPUs are untouched. New recipe files and dsv4-fp4-gb200-dynamo-vllm-agentic-mtp2-{agg,disagg} master-config keys are kept separate from the existing GB200 AgentX MTP recipes/keys, which have unrelated tuning and are left untouched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fill in pr-link for GB200 mtp2 changelog entry Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Switch GB200 mtp2 recipes to stock nightly image + regular MegaMoE The GB300-pinned nightly-dev-arm64-cu13.0.1-426e59f tag is an ephemeral dev-branch build that has already been pruned from Docker Hub, and it exists specifically to carry deep_gemm_amxf4_mega_moe (W4A4 MegaMoE) support that isn't in stock vLLM nightly. Since these GB200 recipes don't need to stay on that dev branch, switch to vllm/vllm-openai:nightly and drop back to the regular deep_gemm_mega_moe backend that stock nightly supports. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Revert "Switch GB200 mtp2 recipes to stock nightly image + regular MegaMoE" This reverts commit 9749e1ef489e06744ff661e5eb5f97036e613ea3. * GB200 mtp2 disagg: lower Mooncake segment to 160GB, halve conc points Job 23562 (disagg-gb200-2p1d-dep8-dep16-c1024-mtp2-agentic, conc=1024) died silently mid-run: one prefill worker process was killed with no CUDA-OOM warning or traceback (exit code: None), which cascaded into an EngineDeadError and aborted the whole disagg job. No host-RAM telemetry was captured to confirm the cause, but the recipe reserves a 180GB host Mooncake KV-store segment per node on top of whatever vLLM/Dynamo itself uses, so as a mitigation: drop global_segment_size to 160GB across all three GB200 mtp2 disagg recipes, and halve each large-conc file's target concurrency (and rename/re-point accordingly) to reduce memory pressure: c256 -> c128 (disagg-gb200-1p1d-dep8-dep8) c1024 -> c512 (disagg-gb200-2p1d-dep8-dep16) c1152 -> c576 (disagg-gb200-2p1d-dep8-dep12) configs/nvidia-master.yaml's mtp2-disagg search-space conc-list and CONFIG_FILE references are updated to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fix decode CUDA-graph capture size on GB200 c128 disagg recipe Job 23607 (disagg-gb200-1p1d-dep8-dep8-c128-mtp2-agentic) OOM'd during decode CUDA-graph capture: 183.24 GiB already in use on a 184 GiB GB200 GPU, then the capture-size warmup forward pass needed another 768 MiB it didn't have. The decode block's max-num-seqs (256) and max-cudagraph-capture-size (1024) were still sized for the pre-rename c256 concurrency, not the current c128 target. max-cudagraph-capture-size should track (num_speculative_tokens + 1) * max-num-seqs for MTP-3 decode graphs. Set decode max-num-seqs to 128 (matching the file's concurrency) and max-cudagraph-capture-size to 512 (4 * 128). The other two GB200 disagg mtp2 decode blocks (c576, c512) already satisfy this (64 * 4 = 256); prefill blocks are unaffected. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Lower GB200 c128 prefill gpu-memory-utilization to leave OOM headroom Job 23635 got past startup (decode capture-size fix from the previous commit held) but crashed ~4 min into serving: three prefill DP ranks hit torch.OutOfMemoryError inside the MTP speculator's draft-token prefill pass (speculator.py:_prefill -> wq_b block-scaled matmul), with the GPU already at 183.03/184 GiB in use. prefill's gpu-memory-utilization: 0.92 (copied from the GB300 source) reserves too much of the 184 GiB GB200 GPU for vLLM's static pool, leaving too little headroom for transient MTP draft-prefill activations on large-batch requests. Drop prefill gpu-memory-utilization to 0.85; decode is untouched since this failure was prefill-only. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * GB200 mtp2 disagg: 140GB Mooncake segment, add 1p1d c256 point Job 23715 (c576, global_segment_size 160GB) still died silently after ~1h51m of steady serving with no CUDA-OOM/cuBLAS error, matching the same host-RAM-exhaustion signature as job 23562 (180GB). Lower global_segment_size to 140GB across all three GB200 mtp2 disagg recipes as a further mitigation. Job 23714 (c128, fixed decode/prefill sizing) completed successfully. Its GPU KV-cache usage peaked at ~80% on prefill and ~39% on decode -- not maxed out -- so add the next concurrency point (256) on the same 1p1d dep8/dep8 topology rather than jumping to 2p1d: create disagg-gb200-1p1d-dep8-dep8-c256-mtp2-agentic.yaml as a clone of the working c128 file (decode max-num-seqs/max-cudagraph-capture-size and prefill gpu-memory-utilization left unchanged, since DEP8 replication already gives 8x the c128 file's per-rank max-num-seqs budget, well above a conc=256 target) and add its conc-list: [256] search-space entry to dsv4-fp4-gb200-dynamo-vllm-agentic-mtp2-disagg. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Update perf-changelog.yaml --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Cameron Quilici <cjquilici@gmail.com>
Summary
benchmarks/multi_node/srt-slurm-recipes/vllm/deepseek-v4/agentic/and newdsv4-fp4-gb200-dynamo-vllm-agentic-mtp2-{agg,disagg}keys inconfigs/nvidia-master.yaml, kept separate from the existing (differently tuned) GB200 AgentX MTP recipes/keys to avoid touching them.runners/launch_gb200-nv.shalready had the synthetic-acceptance injection, so no runner changes were needed.Test plan
changelog validationCI gate passes (perf-changelog entry usespull/XXXplaceholder, update to this PR's number)dsv4-fp4-gb200-dynamo-vllm-agentic-mtp2-agg/-disaggruns green on the gb200-nv cluster