Skip to content

Fix GB300 DeepSeek-V4 AgentX worker metrics / 修复 GB300 DeepSeek-V4 AgentX worker 指标采集#2291

Open
cquil11 wants to merge 2 commits into
mainfrom
agent/capture-gb300-dsv4-worker-metrics
Open

Fix GB300 DeepSeek-V4 AgentX worker metrics / 修复 GB300 DeepSeek-V4 AgentX worker 指标采集#2291
cquil11 wants to merge 2 commits into
mainfrom
agent/capture-gb300-dsv4-worker-metrics

Conversation

@cquil11

@cquil11 cquil11 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • collect AIPerf Prometheus metrics from the Dynamo frontend and every logical SGLang prefill/decode worker for all six GB300 DeepSeek-V4 AgentX recipes
  • directly validate NVIDIA/srt-slurm #276 at immutable head 3fe5508, fetched through the upstream pull ref with no downstream patch or custom-fork clone
  • derive stable leader-only worker URLs inside the InferenceX custom benchmark from the full Slurm allocation and recipe-provided logical worker widths, without requiring scontrol in the model container
  • include SGLang running/queued request metrics in the inter-concurrency drain gate
  • add the missing cluster:gb300-nv hardware metadata required by current AgentX DRAM-offload matrix generation
  • update the appended perf-changelog entry for the same two config keys introduced by Add GB300 DeepSeek-V4 Dynamo-SGLang AgentX aggregated and disaggregated recipes / 新增 GB300 DeepSeek-V4 Dynamo-SGLang AgentX 聚合式与分离式配方 #2157

Root cause and consequences

AIPerf supports multiple values after one --server-metrics flag, and InferenceX already forwards AIPERF_SERVER_METRICS_URLS. Upstream srt-slurm also passes benchmark.env to benchmark.type: custom commands unchanged. Released upstream srt-slurm versions only auto-discover worker endpoints for built-in AIPerf runners, not custom commands, and PR #2157 did not otherwise populate the variable. This PR keeps an InferenceX fallback for released tags and directly validates NVIDIA/srt-slurm #276, which exports the authoritative ordered endpoint list to custom benchmarks.

Its successful sweep therefore scraped only http://localhost:8000/metrics. The benchmark results contained Dynamo router/frontend metrics but no direct sglang:* worker series, which removed observability for SGLang token/cache/HiCache and queue metrics. The InferenceX aggregation layer already normalizes captured SGLang metrics; the data was simply never collected. The drain gate also previously checked only vLLM queue names, so its worker-side check was ineffective for SGLang.

Validation

  • python -m pytest utils/agentic/test_srt_metrics_endpoints.py utils/matrix_logic/ -q — 232 passed
  • python -m pytest utils/agentic/test_srt_metrics_endpoints.py utils/agentic/aggregation/test_process_agentic_result.py -q — 39 passed
  • clean, detached NVIDIA/srt-slurm v1.0.10 with all six recipes overlaid: pytest tests/test_configs.py tests/test_benchmarks.py -q — 168 passed
  • exact NVIDIA/srt-slurm Update NVIDIA DeepSeek sglang Docker image from v0.5.5 to v0.5.6 #276 head fetched through pull/276/head, with all six recipes overlaid: focused custom-benchmark, node-placement, and recipe-loading tests — 16 passed
  • python utils/validate_perf_changelog.py --base-ref origin/main --head-ref HEAD
  • bash -n benchmarks/multi_node/agentic_srt.sh runners/launch_gb300-nv.sh
  • generated the complete nine-job GB300 DSV4 Dynamo-SGLang AgentX matrix locally
  • full sweep runs under full-sweep-enabled

中文说明

概述

  • 为全部 6 个 GB300 DeepSeek-V4 AgentX 配方采集 Dynamo frontend 以及每个逻辑 SGLang 预填充/解码 worker 的 AIPerf Prometheus 指标
  • 直接验证 NVIDIA/srt-slurm #276 的不可变 Head Commit 3fe5508;通过上游 Pull Request 引用拉取,不应用下游补丁,也不克隆自定义 Fork
  • 由 InferenceX 自定义基准测试根据完整的 Slurm 资源分配和配方中声明的逻辑 worker 节点宽度,推导顺序稳定且仅包含 leader 的 worker 指标端点;模型容器内无需安装 scontrol
  • 在并发点切换前的排空检查中加入 SGLang 正在运行和排队中的请求指标
  • 补充当前 AgentX DRAM KV 卸载矩阵生成所需的 cluster:gb300-nv 硬件元数据
  • 更新针对 Add GB300 DeepSeek-V4 Dynamo-SGLang AgentX aggregated and disaggregated recipes / 新增 GB300 DeepSeek-V4 Dynamo-SGLang AgentX 聚合式与分离式配方 #2157 所引入同一组配置键追加的 perf-changelog 条目

根因与影响

AIPerf 支持在单个 --server-metrics 参数后传入多个端点,InferenceX 也已支持转发 AIPERF_SERVER_METRICS_URLS。上游 srt-slurm 同样会把 benchmark.env 原样传给 benchmark.type: custom 命令。但已发布的上游 srt-slurm 版本只会为内置 AIPerf Runner 自动发现 Worker 端点,不会为自定义命令执行该操作,而 PR #2157 也未通过其他方式设置此变量。本 PR 为已发布版本保留 InferenceX 侧的回退逻辑,并直接验证 NVIDIA/srt-slurm #276;该上游 PR 会向自定义基准测试导出权威且有序的端点列表。

因此,原扫描虽然成功,却只抓取了 http://localhost:8000/metrics。结果中包含 Dynamo 路由器/frontend 指标,但没有任何直接的 sglang:* worker 时序数据,导致 SGLang token、缓存、HiCache 和队列指标不可观测。InferenceX 聚合层已经支持归一化采集到的 SGLang 指标,问题仅在于这些数据此前从未被抓取。另外,原排空检查只识别 vLLM 的队列指标名,因此其 worker 侧检查对 SGLang 实际无效。

验证

  • python -m pytest utils/agentic/test_srt_metrics_endpoints.py utils/matrix_logic/ -q — 232 项通过
  • python -m pytest utils/agentic/test_srt_metrics_endpoints.py utils/agentic/aggregation/test_process_agentic_result.py -q — 39 项通过
  • 在干净、分离的 NVIDIA/srt-slurm v1.0.10 工作树中覆盖全部 6 个配方后运行 pytest tests/test_configs.py tests/test_benchmarks.py -q — 168 项通过
  • 通过 pull/276/head 拉取 NVIDIA/srt-slurm Update NVIDIA DeepSeek sglang Docker image from v0.5.5 to v0.5.6 #276 的精确 Head Commit,并覆盖全部 6 个配方;自定义基准测试、节点放置和配方加载相关测试 — 16 项通过
  • python utils/validate_perf_changelog.py --base-ref origin/main --head-ref HEAD
  • bash -n benchmarks/multi_node/agentic_srt.sh runners/launch_gb300-nv.sh
  • 已在本地生成完整的 9 任务 GB300 DSV4 Dynamo-SGLang AgentX 矩阵
  • 通过 full-sweep-enabled 执行完整扫描

@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 marked this pull request as ready for review July 20, 2026 23:07
@cquil11
cquil11 requested a review from a team July 20, 2026 23:07
@cquil11
cquil11 force-pushed the agent/capture-gb300-dsv4-worker-metrics branch from 7cd3b30 to b4dbfa7 Compare July 20, 2026 23:07
@cquil11
cquil11 requested a review from a team July 20, 2026 23:07
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Claude finished @cquil11's task in 6m 5s —— View job


PR Review

  • Gather context and read PR diff
  • Verify aiperf_server_metrics key consumption and srt-slurm patch layering
  • Check perf-changelog entry placement and config keys
  • Check runners.yaml hardware metadata usage
  • Review launch_gb300-nv.sh changes
  • Post review feedback

Summary

1 warning, no blocking issues. The one finding (posted inline on agg-gb300-tp4-mtp-kvoffload.yaml:130): populating AIPERF_SERVER_METRICS_URLS with SGLang endpoints exposes a gap in agentic_srt.sh's wait_for_agentic_servers_idle — it sums only vllm:num_requests_running/vllm:num_requests_waiting, and SGLang exports sglang:num_running_reqs/sglang:num_queue_reqs instead (verified against the SGLang metrics collector). So the worker half of the inter-concurrency drain gate is a silent no-op for these recipes, and an unreachable worker URL would hard-fail the agg run at the drain step after 1800s. Metric capture (the PR's main goal) is unaffected — AIPerf scrapes and exports whatever the endpoints serve.

Everything else checks out:

  • Recipe YAMLs: aiperf_server_metrics: true placement matches the existing GB200 vLLM agentic precedent, applied consistently to all six recipes.
  • launch_gb300-nv.sh: pinned v1.0.10 + cherry-pick of cquil11/srt-slurm-nv@de59739b is deterministic (both sides pinned; set -e fails loudly on conflict), and that exact fork SHA is already load-bearing on main via launch_gb200-nv.sh, so no new supply-chain surface. Enroot docker:// import pattern is present.
  • perf-changelog.yaml: entry is appended at the end of the file ✓, both config keys (dsv4-fp4-gb300-dynamo-sglang-agentic-{agg,disagg}) exist in configs/nvidia-master.yaml ✓, PR link correct ✓.
  • configs/runners.yaml: cluster:gb300-nv hardware block matches the key those master configs use as runner:, and mirrors the cluster:gb200-nv shape (4 GPUs/node, same Grace DRAM), which is consistent with GB300 NVL72 tray topology.
  • No master-config or benchmarks/*.sh changes, so the related checklist rules don't apply.

Note: I could not re-run the pytest/validator commands in this sandbox (execution not permitted) or fetch the fork commit contents directly — I relied on the author-reported validation, the fork SHA's existing use on main, and CI, which runs the matrix/changelog checks anyway.


benchmark:
type: custom
aiperf_server_metrics: true

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.

🟡 WARNING: The inter-concurrency drain gate can't see SGLang worker activity — it only sums vLLM metric names.

Why it matters: This flag now populates AIPERF_SERVER_METRICS_URLS with SGLang worker endpoints, and wait_for_agentic_servers_idle in benchmarks/multi_node/agentic_srt.sh:78-79 sums only vllm:num_requests_running / vllm:num_requests_waiting. SGLang exports sglang:num_running_reqs / sglang:num_queue_reqs (verified against the SGLang metrics collector — there are no vllm:* names), so worker_active is always 0 and the worker half of the drain check is a silent no-op. This recipe is the one affected: with conc-list: [1, 4, 8, 16] the drain gate runs between points, and it will only wait on dynamo_frontend_active_requests — i.e., the pre-PR behavior, minus the worker-side guarantee this PR sets out to add. (Second-order effect: if any injected worker URL is unreachable from the node running agentic_srt.sh, every poll raises, idle_polls never accumulates, and the run hard-fails after AIPERF_DRAIN_TIMEOUT_SECONDS=1800s even when servers are idle.)

Fix: In agentic_srt.sh, also sum the SGLang gauge names:

worker_active += metric_sum(worker_metrics, "vllm:num_requests_running")
worker_active += metric_sum(worker_metrics, "vllm:num_requests_waiting")
worker_active += metric_sum(worker_metrics, "sglang:num_running_reqs")
worker_active += metric_sum(worker_metrics, "sglang:num_queue_reqs")

metric_sum returns 0 for absent metrics, so this stays backend-agnostic for the existing vLLM GB200 agentic recipes.

Fix this →

@claude claude Bot 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.

LGTM. The AIPerf metrics wiring (aiperf_server_metrics: true across all six recipes), the new cluster:gb300-nv hardware entry, and the perf-changelog addition are mechanical, consistent with existing patterns in this repo, and don't touch production-critical or security-sensitive code. The flagged nit (agentic_srt.sh / generate_aiperf_plots.py hardcoding vllm:-prefixed metric names, which won't match SGLang's sglang: prefix) has bounded, diagnostic-only impact — the frontend-side drain check still functions and the raw sglang:* series are still captured in server_metrics_export.json — so it doesn't need to block this PR.

Extended reasoning...

Overview

This PR wires up AIPerf Prometheus server-metrics collection (aiperf_server_metrics: true) for six GB300 DeepSeek-V4 AgentX SGLang recipes, layers a pinned cherry-pick commit from a contributor fork (cquil11/srt-slurm-nv) onto the NVIDIA/srt-slurm v1.0.10 checkout in runners/launch_gb300-nv.sh so the host-side orchestrator injects per-worker metrics URLs, adds a cluster:gb300-nv hardware entry to configs/runners.yaml, and appends a perf-changelog entry. All changes are confined to benchmark recipe YAML, a CI launcher script, and static config/changelog data.

Security risks

None of production consequence. The only notable supply-chain-adjacent element is the git fetch .../cquil11/srt-slurm-nv.git <full-commit-sha> && git cherry-pick --no-commit FETCH_HEAD addition in launch_gb300-nv.sh. It's pinned to a full commit SHA (content-addressed, can't be silently swapped) and mirrors an existing pattern already used a few branches down in the same script (the plain agentic path also clones cquil11/srt-slurm-nv and checks out a pinned commit), so this isn't a new risk pattern for this codebase.

Level of scrutiny

This is CI/benchmark-infra tooling, not a production code path — the blast radius of a mistake is a failed or misleading benchmark run, not a live-traffic incident. Low-to-moderate scrutiny is appropriate. The change is largely repetitive (same one-line flag added identically across six recipe files) plus a well-scoped, narrated launcher script edit.

Other factors

The one substantive finding (vllm:-only metric names not matching SGLang's sglang: prefix in two downstream consumers) is real but nit-level per its own bounded-impact analysis: the frontend-side drain-wait check still gates concurrency transitions, and the plots consumer is best-effort/diagnostic-only with the raw metrics still captured in the exported JSON. It's already surfaced as an inline comment, so it doesn't need to gate this approval. Validation described in the PR (matrix_logic tests, srt-slurm test suites, changelog validator, bash -n, local matrix generation) is reasonably thorough for this kind of change.


benchmark:
type: custom
aiperf_server_metrics: true

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.

🟡 Setting aiperf_server_metrics: true on these six SGLang recipes makes AIPERF_SERVER_METRICS_URLS non-empty for the SGLang path for the first time, but two downstream consumers still hardcode vLLM-only metric names instead of SGLang's sglang:-prefixed ones: wait_for_agentic_servers_idle() in benchmarks/multi_node/agentic_srt.sh (worker-level drain check silently reports 0 activity), and panel_kv_cache_usage()/panel_queue_depth() in utils/generate_aiperf_plots.py (KV-cache/queue-depth panels render empty). Fix by matching sglang:-prefixed names or selecting the metric family by backend in both files; this same recipe line is added identically across all six new recipes so the fix applies uniformly.

Extended reasoning...

Turning on benchmark.aiperf_server_metrics: true (added identically to all six GB300 DeepSeek-V4 SGLang AgentX recipes in this PR) causes the cherry-picked srt-slurm patch to populate AIPERF_SERVER_METRICS_URLS with one real Prometheus endpoint per logical SGLang worker leader. Per the PR description, that variable was never set on this SGLang path before (PR #2157 left it empty), so this is the first time these worker URLs are actually fetched rather than being an inert, empty list.

Two existing consumers of that variable hardcode vLLM-only Prometheus metric names and never branch on backend/framework to select the SGLang equivalents:

  1. wait_for_agentic_servers_idle() in benchmarks/multi_node/agentic_srt.sh (~lines 74-79) computes worker activity via metric_sum(worker_metrics, "vllm:num_requests_running") and "vllm:num_requests_waiting". metric_sum() matches on an exact metric-name prefix, so it can never match SGLang's sglang:num_requests_running / sglang:num_requests_waiting lines. worker_active is therefore always computed as 0.0, regardless of how many requests SGLang workers are actually still running or queuing. This function is invoked between every pair of concurrency points in the sweep loop to make sure the previous point has fully drained before the next one starts; with worker_active pinned to zero, the worker-level half of that guard is dead code for SGLang and the drain-wait falls back to relying solely on dynamo_frontend_active_requests.

  2. panel_kv_cache_usage() and panel_queue_depth() in utils/generate_aiperf_plots.py (~lines 208-212, 246-249) look up vllm:kv_cache_usage_perc, vllm:cpu_kv_cache_usage_perc, vllm:num_requests_running, and vllm:num_requests_waiting in the scraped server metrics. None of these keys exist in an SGLang /metrics payload, so both panels in the generated metrics_plots.png render empty for all six of this PR's new recipes — silently defeating part of the stated point of the PR (capturing per-worker metrics for visualization).

SGLang's distinct metric family is already established elsewhere in the repo: benchmarks/single_node/agentic/dsv4_fp4_b300_sglang.sh:207 greps ^(sglang:(...|num_requests_running|num_requests_waiting)), and utils/agentic/aggregation/backends/sglang.py keys every SGLang server metric off the sglang: prefix. Neither agentic_srt.sh nor generate_aiperf_plots.py has any equivalent branching logic.

Step-by-step proof (drain-wait): (1) Recipe sets aiperf_server_metrics: true. (2) srt-slurm's cherry-picked patch resolves the SGLang worker leaders' hostnames/ports and exports AIPERF_SERVER_METRICS_URLS="http://worker1:PORT/metrics,http://worker2:PORT/metrics,...". (3) agentic_srt.sh splits this into worker_urls and, between concurrency points, curls each URL's /metrics, which (from an SGLang engine) contains lines like sglang:num_requests_running{...} 3 and sglang:num_requests_waiting{...} 1. (4) metric_sum(worker_metrics, "vllm:num_requests_running") scans those same lines for an exact match on vllm:num_requests_running and finds none, returning 0; same for vllm:num_requests_waiting. (5) worker_active = 0 + 0 = 0 even though 3 requests are running and 1 is queued. (6) The idle-wait loop only needs dynamo_frontend_active_requests == 0 for 3 consecutive polls to declare "drained," so it can do so while those SGLang requests are still in flight from the previous concurrency point.

Impact is real but bounded, which is why this should land as a nit rather than a blocker: the drain-wait's frontend-side check (dynamo_frontend_active_requests) still functions and is a reasonably strong proxy since a request stays "active" at the frontend until its streamed response completes; additionally, agentic_srt.sh's per-concurrency-point cache-bust marker gives each point a disjoint KV keyspace independently of the drain-wait, further limiting cross-contamination risk. For the plots consumer, generate_aiperf_plots.py is invoked best-effort (wrapped in || true from benchmark_lib.sh) purely for diagnostic visualization — it doesn't gate run success or affect the benchmark result JSON, and the raw sglang:* series are still captured intact in server_metrics_export.json; only these two specific plot panels come out empty.

Fix direction: have agentic_srt.sh and generate_aiperf_plots.py also match sglang:-prefixed metric names, or branch on backend/framework to select the right prefix family, since both files are now shared by vLLM and SGLang multi-node recipes that set aiperf_server_metrics.

Derive logical worker Prometheus endpoints in the InferenceX custom benchmark from the Slurm allocation and recipe worker widths while keeping NVIDIA/srt-slurm v1.0.10 unmodified. Teach the drain gate SGLang queue metrics, add topology tests, and retain the GB300 hardware metadata needed by matrix generation.

中文:在 InferenceX 自定义基准测试中,根据 Slurm 资源分配和配方中的 worker 节点宽度推导各逻辑 worker 的 Prometheus 端点,保持 NVIDIA/srt-slurm v1.0.10 完全不变。为排空检查补充 SGLang 队列指标,增加拓扑测试,并保留矩阵生成所需的 GB300 硬件元数据。
@cquil11
cquil11 force-pushed the agent/capture-gb300-dsv4-worker-metrics branch from b4dbfa7 to a42cc4b Compare July 20, 2026 23:23
@cquil11

cquil11 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

Updated the implementation to use untouched NVIDIA/srt-slurm v1.0.10 with no custom fork or patch. Endpoint discovery now runs entirely in the InferenceX custom benchmark, and the SGLang drain metrics noted in review are included. / 已将实现改为原样使用 NVIDIA/srt-slurm v1.0.10,不再使用自定义 fork 或补丁。端点发现现完全由 InferenceX 自定义基准测试完成,审阅中指出的 SGLang 排空指标也已补充。

Pin the GB300 DeepSeek-V4 AgentX path to NVIDIA/srt-slurm PR #276 through the upstream pull ref, verify its immutable head, and log whether srt-slurm supplied AIPerf worker metrics endpoints.

中文:将 GB300 DeepSeek-V4 AgentX 路径通过上游 Pull Request 引用固定到 NVIDIA/srt-slurm PR #276,校验不可变的 Head Commit,并在日志中明确标识 AIPerf Worker 指标端点是否由 srt-slurm 提供。
@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

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