Skip to content

perf(agentx): Refresh Qwen3.5 GB300 Pareto recipes - #2477

Open
csahithi wants to merge 3 commits into
mainfrom
nv-qwen35-agentx-gb300-pareto-recipes
Open

perf(agentx): Refresh Qwen3.5 GB300 Pareto recipes#2477
csahithi wants to merge 3 commits into
mainfrom
nv-qwen35-agentx-gb300-pareto-recipes

Conversation

@csahithi

@csahithi csahithi commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Refresh the Qwen3.5-397B-A17B NVFP4 GB300 AgentX frontier with the fourteen-point locally-validated curve: aggregate TP2 (c1/c24/c32/c40/ c48/c52/c64), disaggregate TP2/TP2 (c72), and disaggregate TP4/TP4 (c8/c16/c32/c64/c96/c128), all MTP/NEXTN + hicache with X-Dynamo-Session-ID affinity.

@github-actions

github-actions Bot commented Aug 3, 2026

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

@csahithi
csahithi force-pushed the nv-qwen35-agentx-gb300-pareto-recipes branch from 4360f90 to f211f95 Compare August 3, 2026 17:59
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Comment thread perf-changelog.yaml
Comment on lines +5376 to +5378

- config-keys:
- qwen3.5-fp4-gb300-dynamo-sglang-agentic-agg

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.

🔴 Restoring the trailing two spaces on the blank separator line (perf-changelog.yaml:5376) that separates the prior pull/2420 entry from this PR's new entry — the diff replaces (two trailing spaces) with a plain empty line, stripping pre-existing whitespace.

Extended reasoning...

perf-changelog.yaml is treated as an append-only, byte-exact history file, and utils/validate_perf_changelog.py enforces that at CI time. The blank separator line between the previous entry (pr-link: .../pull/2420) and the new entry this PR appends previously contained two trailing spaces before the newline. This diff's hunk shows that exact line removed (- , i.e. two spaces) and replaced with a plain empty line (+), which strips the trailing whitespace from pre-existing, historical content rather than leaving it untouched.

I verified this at the byte level directly against the repository history:

  • git show e275f56:perf-changelog.yaml | sed -n "5376p" | cat -A renders as $ — two literal space characters followed by end-of-line — confirming the base file's separator line has two trailing spaces.
  • git show 4360f90:perf-changelog.yaml | sed -n "5376p" | cat -A (this PR's HEAD) renders as $ with no trailing spaces — confirming the two spaces were stripped by this PR.

This matters because validate_raw_change() in utils/validate_perf_changelog.py (lines 211-223) enforces byte-for-byte preservation of history when new entries are appended:

if additions:
    if not head_raw.startswith(base_raw):
        raise ChangelogValidationError(
            "appended entries changed historical perf-changelog.yaml bytes; "
            "restore the base file byte-for-byte and append at the end"
        )

base_raw (the file at the merge-base/previous state) ends in ...pull/2420\n \n — i.e., the byte immediately after the trailing \n following pull/2420 is a space character (the start of the two-space separator line). head_raw (this PR's file) instead has ...pull/2420\n\n- config-keys:... — a newline in that same position instead of a space. Because head_raw does not start with the exact byte sequence of base_raw, head_raw.startswith(base_raw) evaluates to False, and the validator raises "appended entries changed historical perf-changelog.yaml bytes; restore the base file byte-for-byte and append at the end".

This is exactly the failure mode AGENTS.md explicitly warns about: "Never delete or modify whitespace in perf-changelog.yaml - CI depends on exact whitespace (including trailing spaces on blank separator lines). Altering it breaks CI." Nothing else in the existing code prevents this — a plain-text/YAML edit that "looks" like a no-op whitespace cleanup silently trips a strict byte-comparison check that isn't visible from casually reading the diff.

The fix is mechanical: restore the two trailing spaces on perf-changelog.yaml line 5376 (the blank line right after the pull/2420 entry) so the file is byte-identical to history up to that point, with the new entry still appended after it.

Comment on lines 7107 to 7130
agentic-coding:
- dram-utilization: 0.80
search-space:
- spec-decoding: "mtp"
- search-space:
- spec-decoding: mtp
conc-list: [1]
kv-offloading: dram
kv-offload-backend: { name: hicache }
prefill:
num-worker: 1
tp: 4
tp: 2
ep: 1
dp-attn: false
additional-settings:
- "CONFIG_FILE=recipes/sglang/qwen3.5/gb300-fp4/agentic/agg-gb300-tp4-c1-mtp-hicache-jid2191933.yaml"
- "CONFIG_FILE=recipes/sglang/qwen3.5/gb300-fp4/agentic/agg-gb300-tp2-c1-mtp-hicache-jid2530006.yaml"
decode:
num-worker: 0
tp: 4
num-worker: 1
tp: 2
ep: 1
dp-attn: false
- spec-decoding: "mtp"
conc-list: [96]
kv-offloading: dram
kv-offload-backend: { name: hicache }
- spec-decoding: mtp
conc-list: [24]
prefill:
num-worker: 1
tp: 4
tp: 2
ep: 1
dp-attn: false
additional-settings:

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.

🔴 All 7 refreshed entries in qwen3.5-fp4-gb300-dynamo-sglang-agentic-agg set decode.num-worker: 1 / decode.tp: 2 alongside prefill.num-worker: 1 / prefill.tp: 2, even though these are single-worker aggregated (disagg: false) recipes where one 2-GPU worker serves both prefill and decode. Because process_agentic_result.py only zeroes out the decode side when num_decode_gpu <= 0, this makes it compute num_gpus=4 and tp=4 for what is actually a 2-GPU TP2 deployment, halving the reported per-GPU throughput and mislabeling TP for all 7 new aggregate curve points (conc 1/24/32/40/48/52/64). Please set decode.num-worker back to 0 on all 7 entries, matching the prior version of this config and the sibling aggregated configs.

Extended reasoning...

The bug: In configs/nvidia-master.yaml's qwen3.5-fp4-gb300-dynamo-sglang-agentic-agg block (lines ~7107-7130), all 7 newly refreshed search-space entries set both prefill.num-worker: 1/tp: 2 and decode.num-worker: 1/tp: 2. This block is aggregated (disagg: false), and each entry's recipe yaml (e.g. agg-gb300-tp2-c1-mtp-hicache-jid2530006.yaml) confirms agg_workers: 1, gpus_per_agg: 2 — a single 2-GPU worker that performs both prefill and decode. There is no separate decode worker to count.\n\nWhy it matters / the code path: utils/agentic/aggregation/process_agentic_result.py computes GPU/TP accounting as:\n\nThe zeroing guard only fires when num_decode_gpu <= 0. With decode.num-worker: 1, num_decode_gpu = 1*2 = 2 > 0, so the guard is skipped: num_gpus becomes 2 + 2 = 4 instead of the real 2, and tp becomes 2 + 2 = 4 instead of the real 2. num_gpus is then the divisor used to compute per-GPU output/input/total throughput, so every one of these 7 points reports half its true per-GPU throughput, and is mislabeled as TP4 instead of TP2.\n\nWhy existing code doesn't prevent it: the guard only protects against decode workers being present when they shouldn't be if the config author remembers to zero num-worker; it can't detect "this num-worker field is wrong for an aggregated deployment" — that invariant has to be maintained in the YAML by the PR author, and this PR broke it for all 7 entries in this block.\n\nStep-by-step proof (conc=1 entry, jid2530006):\n1. Recipe yaml: resources.agg_workers: 1, resources.gpus_per_agg: 2 → real deployment is 1 worker, 2 GPUs total, TP2.\n2. nvidia-master.yaml sets prefill.num-worker: 1, prefill.tp: 2, decode.num-worker: 1, decode.tp: 2.\n3. These flow via PREFILL_NUM_WORKERS/DECODE_NUM_WORKERS env vars into process_agentic_result.py.\n4. num_prefill_gpu = 1*2 = 2; num_decode_gpu = 1*2 = 2. Since num_decode_gpu > 0, the zeroing branch does not run.\n5. num_gpus = 2 + 2 = 4 (should be 2); tp = 2 + 2 = 4 (should be 2).\n6. Per-GPU throughput = total_throughput / num_gpus = total_throughput / 4, when it should be total_throughput / 2 — exactly half the correct value. TP is also reported as 4 instead of 2.\n\nCorroboration: the prior version of this exact config used decode.num-worker: 0 (visible in the diff removing the old TP4 entries); sibling aggregated configs dsv4-fp4-gb300-dynamo-vllm-agentic-mtp-agg and dsv4-fp4-gb300-dynamo-sglang-agentic-agg explicitly keep decode.num-worker: 0 with a comment explaining exactly this invariant. The disagg block in this same PR correctly uses decode.num-worker: 1 because there decode really is a separate worker — reinforcing that the agg block's use of 1 is simply wrong.\n\nFix: set decode.num-worker: 0 on all 7 aggregate entries (conc-list [1], [24], [32], [40], [48], [52], [64]) in qwen3.5-fp4-gb300-dynamo-sglang-agentic-agg, matching the pattern used everywhere else in this file for aggregated deployments.\n\nImpact if merged as-is: since this PR's entire purpose is to publish a refreshed, accurate 14-point Pareto frontier, merging with this bug means all 7 aggregate points on that frontier report exactly half their true per-GPU throughput and the wrong TP — corrupting the primary metric the PR exists to produce.

Comment thread perf-changelog.yaml Outdated
Comment on lines +5379 to +5384
- qwen3.5-fp4-gb300-dynamo-sglang-agentic-disagg
description:
- "Refresh the Qwen3.5 GB300 AgentX frontier after aiperf 381758a restored real conversation pacing; replace the stale nine-point sweep with a complete fourteen-point locally validated curve: disaggregate TP4/TP4 c8/c16/c32/c64/c96/c128, disaggregate TP2/TP2 c72, and aggregate TP2 c1/c24/c32/c40/c48/c52/c64."
- "The 30-minute local re-sweep covered low, mid, and high concurrency across aggregate TP2, disaggregate TP2/TP2, and disaggregate TP4/TP4. All 33 new-client steady-state samples completed with zero request errors and zero retract events; using the same historical output-token-throughput-per-user p50 metric as the old curve, the fourteen submitted points are the strict non-dominated set. The InferenceMAX sweep keeps the canonical 60-minute AgentX benchmark duration."
- "Align both configurations on the 2026-07-24 SGLang container, current aiperf be758d6, the merged Dynamo #12081 commit 5a638087, X-Dynamo-Session-ID affinity with the removed legacy conv-aware CLI path explicitly disabled, and NVIDIA/srt-slurm v1.0.36 while keeping the recipe and nvidia-master entries synchronized."
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/XXXX

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 new perf-changelog.yaml entry's pr-link is left as https://github.com/SemiAnalysisAI/InferenceX/pull/XXXX (four X's) instead of the real PR number, 2477. This isn't just a cosmetic placeholder — utils/validate_perf_changelog.py's validate_added_pr_link only accepts the exact three-X placeholder (XXX / .../pull/XXX) or the real .../pull/{pr_number} link on a PR run, so pull/XXXX matches neither and the changelog-validation CI check will fail. Fix by replacing XXXX with 2477.

Extended reasoning...

What the bug is: The changelog entry appended at perf-changelog.yaml:5384 ends with:

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

That is four literal X characters, not the real PR number (this PR is #2477). Every other entry in the file — including the three immediately above it (pull/2360, pull/2213, pull/2421, pull/2420) — carries a real, resolved PR number, confirming XXXX is an unfilled template placeholder left over from drafting rather than an intentional value.

The exact code path that fails: utils/validate_perf_changelog.py defines:

PR_LINK_PLACEHOLDERS = {
    "XXX",
    "https://github.com/SemiAnalysisAI/InferenceX/pull/XXX",
}

and validate_added_pr_link(link, pr_number), called on a PR run with pr_number=2477, does:

expected = f"https://github.com/SemiAnalysisAI/InferenceX/pull/{pr_number}"
if link not in PR_LINK_PLACEHOLDERS and link != expected:
    raise ChangelogValidationError(...)

Note the placeholder set uses exactly three Xs (XXX), matching the documented template in AGENTS.md. The submitted value https://github.com/SemiAnalysisAI/InferenceX/pull/XXXX has four Xs, so it is neither in PR_LINK_PLACEHOLDERS nor equal to expected (.../pull/2477). The function raises ChangelogValidationError, which fails the changelog-validation check.

Why existing tooling doesn't catch/prevent it upstream: The validator only checks the format of the link (exact placeholder string, or the exact expected PR URL) — it has no way to auto-correct a near-miss like an extra character, so a typo'd placeholder is treated as an arbitrary invalid string rather than "close enough" to the accepted placeholder.

Step-by-step proof:

  1. PR perf(agentx): Refresh Qwen3.5 GB300 Pareto recipes #2477 runs the changelog validator with pr_number=2477.
  2. The validator reads the new entry's pr-link: "https://github.com/SemiAnalysisAI/InferenceX/pull/XXXX".
  3. expected = "https://github.com/SemiAnalysisAI/InferenceX/pull/2477".
  4. Check 1: is link in PR_LINK_PLACEHOLDERS ({"XXX", ".../pull/XXX"})? No — XXXX (four X's) != XXX (three X's) as a substring match on the full string.
  5. Check 2: is link == expected? No — XXXX != 2477.
  6. Both checks fail → ChangelogValidationError is raised → the changelog-validation CI job fails.

Impact: This blocks the changelog-validation CI gate on this PR (not just a traceability nit) until fixed, though the fix is a one-character-format substitution.

Fix: Replace the placeholder value with the real PR number:

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

Refresh the Qwen3.5-397B-A17B NVFP4 GB300 AgentX frontier with the
fourteen-point locally-validated curve: aggregate TP2 (c1/c24/c32/c40/
c48/c52/c64), disaggregate TP2/TP2 (c72), and disaggregate TP4/TP4
(c8/c16/c32/c64/c96/c128), all MTP/NEXTN + hicache with
X-Dynamo-Session-ID affinity.
@csahithi
csahithi force-pushed the nv-qwen35-agentx-gb300-pareto-recipes branch from f211f95 to a020236 Compare August 3, 2026 18:42
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

The 7 aggregated (disagg: false) agg entries run a single 2-GPU worker
serving both prefill and decode. With decode.num-worker: 1,
process_agentic_result.py counts num_gpus=4/tp=4 instead of 2/2 —
halving reported per-GPU throughput and mislabeling TP4. Set decode
num-worker back to 0 to match the sibling aggregated configs.
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

…0-pareto-recipes

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

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant