Skip to content

Refresh DeepSeek-V4 B200 SGLang AgentX MTP - #2578

Merged
cquil11 merged 5 commits into
mainfrom
agent/refresh-dsv4-b200-sglang-agentx
Aug 13, 2026
Merged

Refresh DeepSeek-V4 B200 SGLang AgentX MTP#2578
cquil11 merged 5 commits into
mainfrom
agent/refresh-dsv4-b200-sglang-agentx

Conversation

@cquil11

@cquil11 cquil11 commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Restore the purged B200 DeepSeek-V4-Pro SGLang AgentX resident, DP-attention, and HiCache grid.
  • Use stable SGLang v0.5.17 with native EAGLE MTP (3 steps, top-k 1, 4 draft tokens).
  • Pin throughput to the committed golden synthetic acceptance length 2.49 while keeping real MTP verification for eval.
  • Follow the official SGLang DeepSeek-V4 Blackwell recipe and require nonempty sglang: server metrics.

This supersedes the B200 portion of #2145.

Production data audit

The current production database has no aggregate B200 DeepSeek-V4 SGLang AgentX MTP results, so this refresh does not duplicate an up-to-date submission.

Validation

  • bash syntax
  • perf changelog validation and generation
  • 231 matrix tests
  • 28 MTP throughput points plus one real-verification evaluation point generated

@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 关于重新运行失败任务的文档

@cquil11
cquil11 force-pushed the agent/refresh-dsv4-b200-sglang-agentx branch from 7c7a5b4 to 721ec8d Compare August 12, 2026 17:12
@cquil11 cquil11 changed the title Refresh DeepSeek-V4 B200 SGLang AgentX Refresh DeepSeek-V4 B200 SGLang AgentX MTP Aug 12, 2026
@cquil11
cquil11 marked this pull request as ready for review August 12, 2026 17:12
@cquil11
cquil11 requested a review from a team August 12, 2026 17:12
@cquil11
cquil11 requested a review from Ankur-singh as a code owner August 12, 2026 17:12
@claude

claude Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Claude finished @cquil11's task in 8m 25s —— View job


PR Review

  • Gather context (diff, changed files, repo guidelines)
  • Review benchmark script dsv4_fp4_b200_sglang_mtp.sh
  • Review configs/nvidia-master.yaml changes (image accessibility, model prefix, EP flags)
  • Review perf-changelog.yaml entry position
  • Post review feedback

Summary

One 🔴 BLOCKING issue (inline comment posted): the new perf-changelog.yaml entry is inserted mid-file (line ~5441, right after the PR #2508 entry) instead of appended to the end of the file — utils/validate_perf_changelog.py enforces append-only byte-for-byte history and will reject this against current main. Please move the entry to the bottom of the file.

Everything else checks out:

  • benchmarks/single_node/agentic/dsv4_fp4_b200_sglang_mtp.sh follows the established glm5.2/qwen3.5 B200 SGLang AgentX patterns (router via consistent hashing + correlation-ID keys, wait_for_ready/write_command/run_eval lib signatures all correct, multi-line server command, sglang: metrics gate).
  • Golden synthetic acceptance length 2.49 matches the committed DSv4 3-step golden (benchmarks/multi_node/amd_utils/server_sglang.sh DSV4_GOLDEN_AL=2.49) and the existing DSv4 vLLM recipes; the simulation env vars are correctly skipped for EVAL_ONLY, so eval keeps real MTP verification.
  • The agentic replay legitimately omits --use-chat-template (documented convention — AIPerf drives /v1/chat/completions, prompts are already chat-formatted).
  • lmsysorg/sglang:v0.5.17-cu130 is a public Docker Hub image already used elsewhere in nvidia-master.yaml; launcher routing (launch_b200-dgxc.sh) resolves the new config key to the new script and exports PORT.
  • Parser names (deepseekv4 / deepseek-v4), --swa-full-tokens-ratio, and flashinfer_mxfp4 MoE backend all match the existing DSv4 SGLang srt-slurm recipes; the chat template file exists.

@cquil11
cquil11 force-pushed the agent/refresh-dsv4-b200-sglang-agentx branch from 721ec8d to 8b73f94 Compare August 12, 2026 17:16
@github-actions

Copy link
Copy Markdown
Contributor

Comment thread perf-changelog.yaml Outdated
Comment on lines +5441 to +5449
- config-keys:
- dsv4-fp4-b200-sglang-agentic-hicache-mtp
scenario-type:
- agentic-coding
description:
- "Refresh the purged B200 DeepSeek-V4-Pro SGLang AgentX resident, DP-attention, and HiCache grid on SGLang v0.5.17."
- "Use native EAGLE MTP (3 steps, top-k 1, 4 draft tokens) and golden synthetic acceptance length 2.49 for throughput; eval retains real verification."
- "Follow the official SGLang DeepSeek-V4 Blackwell recipe and require nonempty SGLang server metrics."
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2578

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.

🔴 BLOCKING: New perf-changelog.yaml entry is inserted mid-file instead of appended to the end.

Why it matters: The file is read chronologically (oldest at top, newest at bottom — it starts at PR #95 and ends at PR #2562's entry on line 5906). This entry was inserted at line 5441, right after the PR #2508 entry, with ~450 lines of existing history below it. Beyond breaking the ordering convention, utils/validate_perf_changelog.py enforces append-only byte-for-byte history (head_raw.startswith(base_raw) in validate_raw_change), so CI changelog validation will fail with "appended entries changed historical perf-changelog.yaml bytes; restore the base file byte-for-byte and append at the end".

Fix: Delete this entry from here and append it verbatim after the last entry in the file (currently the qwen3.5-fp4-mi355x-sglang-agentic-mtp entry for PR #2562, ending at line 5906), separated by exactly one empty line.

Fix this →

Comment on lines +259 to +262
if [ "${#METRICS_ARGS[@]}" -gt 0 ]; then
capture_cache_metrics
trap capture_cache_metrics EXIT
fi

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 EXIT trap guard if [ "${#METRICS_ARGS[@]}" -gt 0 ] at line 259 is always true, since METRICS_ARGS is set unconditionally at line 103 to a fixed 2-element array and is never emptied or reassigned on any path. It reads as though metrics capture is optional (mirroring the genuinely-conditional CACHE_ARGS pattern above it), but it isn't — either drop the guard or make METRICS_ARGS actually conditional.

Extended reasoning...

The bug: METRICS_ARGS is declared once, unconditionally, at line 103:

METRICS_ARGS=(--enable-metrics --enable-cache-report)

It is never reassigned, appended to, or emptied anywhere else in the script — a grep for METRICS_ARGS across the file turns up exactly three hits: the assignment at line 103, its expansion into SGLANG_CMD at line ~204, and the guard at line 259:

if [ "${#METRICS_ARGS[@]}" -gt 0 ]; then
    capture_cache_metrics
    trap capture_cache_metrics EXIT
fi

Since the array always has exactly 2 elements, ${#METRICS_ARGS[@]} is always 2, and the condition is always true. The if block is dead weight — capture_cache_metrics and the EXIT trap install unconditionally regardless of what this guard says.

Why it's misleading rather than merely redundant: the script has one real precedent for this shape a few lines earlier — CACHE_ARGS. That array starts empty (CACHE_ARGS=()) and is populated only inside the require_agentic_kv_offload_backend hicache branch, so a length check on it is a legitimate runtime conditional. METRICS_ARGS copies that visual pattern (an array-length guard right before use) without the underlying conditionality that makes the pattern meaningful. A reader skimming the script would reasonably assume metrics/cache-report capture is optional in some configuration, when in fact it is always on.

Step-by-step proof:

  1. Line 103 executes unconditionally on every invocation of the script: METRICS_ARGS=(--enable-metrics --enable-cache-report).
  2. No branch (HiCache on/off, DP-attention on/off, eval-only or not) touches METRICS_ARGS again before line 259.
  3. At line 259, ${#METRICS_ARGS[@]} evaluates to 2 in every possible run.
  4. [ 2 -gt 0 ] is always true, so capture_cache_metrics is always invoked immediately and the trap capture_cache_metrics EXIT is always installed.
  5. Therefore no execution path skips this block — the guard has no observable effect on behavior.

Impact: none functionally — this doesn't change program behavior since the branch is always taken anyway. It's purely a readability/maintainability nit: a future editor could plausibly try to make metrics capture conditional by clearing METRICS_ARGS somewhere, not realizing the guard already silently assumed that possibility without it ever occurring.

Fix: either (a) drop the if and call capture_cache_metrics/install the trap unconditionally, since metrics are always enabled, or (b) if optional metrics capture was actually intended, make METRICS_ARGS conditionally empty (e.g., only set it under a flag) so the guard reflects real behavior.

Comment on lines +50 to +57
# processing use the isolated environment when InferenceX is mounted at /ix.
SGLANG_PYTHON="$(command -v python3)"
if [[ "$INFMAX_CONTAINER_WORKSPACE" != /workspace ]]; then
AGENTIC_VENV="${AGENTIC_VENV:-/tmp/inferencex-agentic-venv}"
"$SGLANG_PYTHON" -m venv "$AGENTIC_VENV"
export PATH="$AGENTIC_VENV/bin:$PATH"
fi
install_agentic_deps

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.

🟡 In eval-only mode, the empty AGENTIC_VENV created at dsv4_fp4_b200_sglang_mtp.sh:52-56 shadows python3 before transformers is installed into it, so get_native_max_context_length's bare-python3 probe (benchmark_lib.sh:908) fails silently and falls back to a hardcoded 16384 instead of DeepSeek-V4-Pro's real native context. For this specific recipe the fallback is harmless in practice (the single-node agentic eval runs GSM8K, whose prompts/outputs fit well inside 16384), but the detection is still silently wrong and worth fixing, e.g. by creating the venv with --system-site-packages so the native-context probe still sees the system transformers.

Extended reasoning...

The mechanism is real. When INFMAX_CONTAINER_WORKSPACE != /workspace (the documented normal case for this B200 image, since it mounts InferenceX at /ix), the script runs "$SGLANG_PYTHON" -m venv "$AGENTIC_VENV" with no --system-site-packages, then prepends $AGENTIC_VENV/bin to PATH. This venv starts completely empty. install_agentic_deps (benchmark_lib.sh:1826) builds a separate AIPERF_VENV via uv --python "$AIPERF_PYTHON" and never touches AGENTIC_VENV, so the new venv stays empty until _install_lm_eval_deps eventually runs python3 -m pip install ... lm-eval[api] into it.

In EVAL_ONLY=true mode, run_eval (benchmark_lib.sh:1689-1690) calls compute_eval_context_length before _install_lm_eval_deps runs (that install happens later, inside run_lm_eval, at line 1008). compute_eval_context_length calls get_native_max_context_length (line 908), which shells out to a bare python3 -c '... from transformers import AutoConfig ...'. Since AGENTIC_VENV/bin is first on PATH and empty at this point, the import raises, the except swallows it, and the probe prints 0. Because MAX_MODEL_LEN is unconditionally unset for agentic callers (benchmark_lib.sh:77) and this recipe never calls setup_eval_context, compute_eval_context_length sees benchmark_ctx=0 and native_max=0 and falls through to eval_ctx=${MAX_MODEL_LEN:-16384}=16384 (line 946), emitting a WARN to stderr along the way.

Step-by-step proof:

  1. INFMAX_CONTAINER_WORKSPACE resolves to /ix (not /workspace) for this image, so the script hits the if branch and creates AGENTIC_VENV empty, then export PATH="$AGENTIC_VENV/bin:$PATH".
  2. EVAL_ONLY=true → the script calls run_eval --port "$PORT".
  3. run_eval sees EVAL_MAX_MODEL_LEN unset → calls compute_eval_context_length "$MODEL" "${MAX_MODEL_LEN:-0}" with MAX_MODEL_LEN unset (→ 0).
  4. compute_eval_context_length calls get_native_max_context_length, which runs bare python3 -c '...AutoConfig...'. python3 now resolves inside the empty AGENTIC_VENV, transformers isn't installed there yet, import fails, function prints 0.
  5. Both benchmark_ctx and native_max are 0 → fallback branch: eval_ctx=16384, EVAL_MAX_MODEL_LEN=16384.
  6. Later, run_lm_eval passes max_length=16384 and computes max_output_tokens=16384-4096=12288 for lm_eval --model_args/--gen_kwargs.
  7. Without the venv (the /workspace case), bare python3 resolves to the image's system Python, which already has transformers installed, so the probe would have returned DeepSeek-V4-Pro's real (larger) native context instead of 0.

Where the original framing overreaches (addressing the refutation). One verifier objection is correct and should be acknowledged: AGENTIC_VENV is not simply redundant dead weight. _install_lm_eval_deps (benchmark_lib.sh:870-887) and the lm_eval invocation itself (line 1029) use bare python3 -m pip install --break-system-packages ... / python3 -m lm_eval. Without something ahead of the system Python on PATH, those bare-python3 calls would install/upgrade lm-eval[api] (and transitively transformers) directly into the SGLang server's system interpreter — exactly the corruption the script's own comment says it's trying to avoid. So the venv does serve a real isolation purpose for the eval path; it isn't redundant with AIPERF_VENV.

The refutation's second point is also correct and matters for grading severity: this config has multinode: false, and per utils/matrix_logic/generate_sweep_configs.py:289-291/405-406, single-node agentic entries run their eval through the GSM8K lm-eval path, not SWE-bench. GSM8K prompts and chain-of-thought generations are far shorter than 16384 tokens, and max_output_tokens still comes out to 12288 either way, so for this recipe's actual eval point there is no truncation or observable score impact — the fallback happens to be harmless here.

Why it's still worth flagging. The detection is genuinely broken (a documented-intent violation per benchmark_lib.sh:70-71, "agentic replays must use the model's native context limit"), it fails silently (only a stderr WARN, no exit), and it's not obviously scoped to "harmless for GSM8K" from the call site — the same pattern will silently misconfigure any future agentic recipe/eval-task combination where the actual context matters, and it's easy to overlook since nothing crashes. A simple, low-risk fix: create AGENTIC_VENV with --system-site-packages (so the bare-python3 native-context probe still resolves transformers from the image's system install while pip installs continue to prefer the venv's own site-packages), or resolve the native-context probe via $SGLANG_PYTHON explicitly instead of a bare python3.

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

…00-sglang-agentx

# Conflicts:
#	perf-changelog.yaml
@github-actions

Copy link
Copy Markdown
Contributor

@cquil11

cquil11 commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

/stage-results 31665831034

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

@cquil11 staged run 31665831034: https://inferencemax-app-git-staging-semianalysisai.vercel.app/inference?i_dates=2026-08-13~r31665831034

This run remains available across future /stage-results requests. Staging the same run ID again updates its staged data. Staging workflow

@cquil11

cquil11 commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

/reuse-sweep-run 31665831034

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.

1 participant