Skip to content

Commit b582eb1

Browse files
authored
Merge branch 'main' into amd/agentx_dsv4_sgl_mtp_0717
2 parents 4c1ad1c + c0124ae commit b582eb1

13 files changed

Lines changed: 545 additions & 9 deletions

File tree

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
---
2+
name: debug-agentx-runs
3+
description: Debug long-running AgentX benchmark jobs from live cluster logs and metrics instead of waiting for buffered GitHub Actions output. Use for AgentX bring-up, performance tuning, apparent hangs, warmup or profiling failures, aggregated or disaggregated serving runs, deciding whether to short-circuit an unproductive run, estimating phase completion, and verifying that every frontend, prefill, decode, or aggregate engine is healthy.
4+
---
5+
6+
# Debug AgentX runs from the cluster
7+
8+
AgentX runs have long model-load, warmup, drain, and profiling phases. Treat GitHub Actions
9+
as the orchestration and final-status view; use the cluster as the primary source of live
10+
diagnostic signal. Compose with `$debug-runs` when it is available for the general
11+
full-sweep and reproduction workflow.
12+
13+
Cluster login addresses, users, jumpboxes, runner directories, and storage paths belong in
14+
the access-controlled InferenceX Clusters Slack canvas, not this repository. Ask the user
15+
for the canvas link or the intended SSH alias when access is not already configured; never
16+
guess or publish private infrastructure details. Read-only SSH inspection is allowed.
17+
Before editing cluster files, restarting or killing processes, draining nodes, cancelling
18+
Slurm jobs, or otherwise mutating shared infrastructure, stop and ask for approval unless
19+
the user explicitly authorized that exact action in the current task.
20+
21+
## 1. Resolve the exact job and serving topology
22+
23+
Start with the workflow run and list its AgentX matrix jobs:
24+
25+
```bash
26+
gh run view <RUN_ID> --repo SemiAnalysisAI/InferenceX --json jobs \
27+
--jq '.jobs[] | select(.name | test("agentic|AgentX"; "i")) |
28+
[.databaseId, .status, .conclusion, .name] | @tsv'
29+
```
30+
31+
Read the selected master-config entry, launcher, and checked-in recipe before interpreting
32+
logs. The recipe is the source of truth for what srt-slurm launches.
33+
34+
- **Aggregated:** look for `resources.agg_*`, `vllm_config.aggregated`, and usually a null
35+
connector. One logical deployment handles both prefill and decode.
36+
- **Disaggregated:** look for separate prefill and decode resources/configs plus a KV
37+
connector. Prefill and decode are separate services and must both be inspected.
38+
- **Attention DP inside an aggregate deployment is not disaggregation.** A TP4 × DP4 =
39+
EP16 deployment exposes four DP engine metrics sources, but every engine handles both
40+
prefill and decode.
41+
42+
Do not infer the topology from AIPerf source labels alone. Aggregate DP engines can appear
43+
as `srv decode 0`, `srv decode 1`, and so on even though they are not decode-only servers.
44+
Likewise, InferenceX may encode an aggregate worker in the master YAML as one prefill
45+
worker and zero decode workers for result labeling.
46+
47+
## 2. Find the live Slurm allocation and log directory
48+
49+
Use the access method from the InferenceX Clusters canvas or the operator's configured SSH
50+
alias. On the controller:
51+
52+
```bash
53+
squeue -u <RUNNER_USER> -o "%.8i %.8T %.10M %.20N %.100j"
54+
scontrol show job -o <SLURM_JOB_ID> | tr " " "\n" |
55+
grep -E "^(JobId|JobState|RunTime|TimeLimit|NodeList|WorkDir)="
56+
```
57+
58+
Derive paths from `WorkDir`; do not guess or hardcode a cluster path. For an srt-slurm
59+
job, logs normally live under:
60+
61+
```text
62+
<WorkDir>/outputs/<SLURM_JOB_ID>/logs/
63+
```
64+
65+
Inventory the directory before choosing files:
66+
67+
```bash
68+
find "<LOG_DIR>" -maxdepth 1 -type f -print | sort
69+
```
70+
71+
If the Slurm job ID is not obvious, correlate the GitHub run ID, runner suffix, config
72+
name, start time, and allocated nodes. Never attach to a similarly named job without
73+
verifying those fields.
74+
75+
## 3. Follow the live logs
76+
77+
Always stream the custom benchmark log from the beginning so phase transitions and the
78+
current metrics snapshot have context:
79+
80+
```bash
81+
ssh <CLUSTER_ALIAS> 'tail -f -n+1 "<LOG_DIR>/benchmark.out"'
82+
```
83+
84+
Select additional logs by topology:
85+
86+
- **Aggregated:** inspect every aggregate backend log, commonly `*_agg_w*.out`. Add the
87+
frontend/router log, commonly `*_frontend_*.out`, when requests are not registering,
88+
routing is imbalanced, metrics are missing, or the frontend reports active requests
89+
after engines are idle.
90+
- **Disaggregated:** inspect all prefill backend logs, all decode backend logs, and the
91+
frontend/router log. A healthy decode pool does not prove that prefill or KV transfer is
92+
healthy, and vice versa.
93+
- **Both:** inspect infrastructure logs when etcd/NATS registration, health checks, or
94+
worker discovery is suspect.
95+
96+
After discovering the real filenames, follow them together:
97+
98+
```bash
99+
tail -F -n+1 <BENCHMARK_LOG> <FRONTEND_LOG> <SERVER_LOGS...>
100+
```
101+
102+
Useful signatures:
103+
104+
```bash
105+
rg -n -i \
106+
"Phase |warmup|profiling|returned=|in_flight=|queue=|kv_usage=|prefix_cache_hit=|tput_|ERROR|Traceback|OOM|NCCL|RCCL|timeout|connection refused" \
107+
<LOGS...>
108+
```
109+
110+
GitHub job logs are often buffered or unavailable until a long-running job finishes.
111+
Do not wait for them when the compute-visible logs are updating.
112+
113+
## 4. Inspect every live metrics source
114+
115+
Confirm the AIPerf command contains the frontend and all applicable engine metrics URLs.
116+
117+
- Aggregated TP/TEP normally has one logical engine source.
118+
- Aggregated attention-DP has one source per DP engine.
119+
- Disaggregated serving needs every prefill source, every decode source, and the frontend.
120+
121+
Missing URLs create a falsely healthy partial view. Read the endpoint directly when the
122+
benchmark summary is ambiguous:
123+
124+
```bash
125+
curl -fsS "<METRICS_URL>" |
126+
rg -i "request|queue|cache|token|prefill|decode|error|fail"
127+
```
128+
129+
Prefer the metric names actually exposed by the running image instead of assuming a
130+
specific vLLM, SGLang, or Dynamo version. Track at least:
131+
132+
- active/running and waiting requests;
133+
- KV-cache usage and prefix-cache hit rate;
134+
- input and output token rates;
135+
- completed, cancelled, and errored requests;
136+
- frontend active requests and per-worker routing balance;
137+
- KV-transfer activity and failures for disaggregated runs.
138+
139+
Interpret trends, not one scrape:
140+
141+
- KV usage pinned near 100%, collapsing cache hits, and a growing queue indicate a
142+
capacity cliff.
143+
- Flat or falling throughput as concurrency rises, with sharply worse TTFT/TPOT, means
144+
the added concurrency is not productive.
145+
- One idle engine while peers have deep queues suggests routing, registration, or metrics
146+
coverage problems.
147+
- No new log timestamps and no changing counters suggest a hang.
148+
- Increasing completions with stable queues and zero errors is healthy even when a
149+
full-context AgentX phase is slow.
150+
151+
## 5. Determine phase progress and ETA from cluster timestamps
152+
153+
Use AgentX phase markers, not total Slurm runtime:
154+
155+
```bash
156+
grep -E \
157+
"Phase warmup progress|WARMUP cache pressure|Phase warmup complete|Phase profiling started|Phase profiling complete|replay_rc=" \
158+
"<LOG_DIR>/benchmark.out"
159+
date -u
160+
```
161+
162+
Model loading and warmup can dominate job age. For a duration-based profiling phase,
163+
calculate the nominal end from the `Phase profiling started` timestamp plus the configured
164+
duration. Then allow a few minutes for cutoff drain, aggregation, staging, and artifact
165+
upload. State separately:
166+
167+
1. phase elapsed and remaining time;
168+
2. whether logs are still updating;
169+
3. errors observed;
170+
4. expected benchmark completion;
171+
5. expected GitHub job completion.
172+
173+
For warmup drains, report returned, sent, in-flight, errors, elapsed time, and the
174+
configured grace limit. Compare the curve with a prior failed run at the same elapsed time
175+
when validating a timeout change.
176+
177+
## 6. Short-circuit clearly bad runs
178+
179+
Do not burn hours waiting for final JSON when direct signals already disqualify a config.
180+
Use server logs and metrics to make the decision early. Examples include:
181+
182+
- deterministic OOM, NCCL/RCCL failure, parser crash, or missing worker;
183+
- no forward progress across repeated samples;
184+
- persistent KV saturation and queue growth with unusable latency;
185+
- throughput that has plateaued while added concurrency only increases latency;
186+
- a disaggregated pool or metrics source that never registered.
187+
188+
Before cancellation, capture the relevant log lines, timestamps, topology, and metric
189+
trend and state the diagnosis. Unless the user explicitly authorized cancellation or
190+
short-circuiting in the current task, ask before terminating anything.
191+
192+
Prefer cancelling from GitHub so workflow cleanup executes:
193+
194+
```bash
195+
gh run cancel <RUN_ID> --repo SemiAnalysisAI/InferenceX
196+
```
197+
198+
Use `scancel` or direct process termination only with explicit approval and a concrete
199+
reason; doing so can bypass cleanup or strand shared-cluster state. Never kill only the
200+
backend and leave the workflow silently occupying a runner.
201+
202+
After a recipe/config fix, use a targeted e2e dispatch for fast feedback. Reserve another
203+
official full sweep for the candidate that has passed direct cluster inspection.
204+
205+
## 7. Report the live diagnosis
206+
207+
For each active point, report:
208+
209+
- GitHub job and Slurm job links/IDs;
210+
- aggregate versus disaggregated topology;
211+
- phase, elapsed time, remaining time, and last log update;
212+
- log files and metrics sources inspected;
213+
- request, queue, KV-cache, cache-hit, and token-rate trends;
214+
- errors and the likely root cause;
215+
- whether to continue, short-circuit, or rerun;
216+
- which points are fully green versus merely healthy in progress.
217+
218+
Do not call a run successful until GitHub has accepted its result artifacts and the
219+
required workflow concludes green.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
interface:
2+
display_name: "Debug AgentX Runs"
3+
short_description: "Debug long AgentX runs from live cluster signals"
4+
default_prompt: "Use $debug-agentx-runs to debug this AgentX benchmark from live cluster logs and metrics."

.github/workflows/benchmark-multinode-tmpl.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@ on:
154154
type: string
155155
required: false
156156
default: "3600"
157+
agentx-fast:
158+
description: "Use the AgentX 5-minute warmup and 20-minute profiling preset"
159+
type: boolean
160+
required: false
161+
default: false
157162
kv-offloading:
158163
description: "KV offload mode for agentic scenarios (none/dram)"
159164
required: false
@@ -214,6 +219,7 @@ env:
214219
IS_AGENTIC: ${{ inputs.scenario-type == 'agentic-coding' && '1' || '0' }}
215220
CONC: ${{ inputs.conc }}
216221
DURATION: ${{ inputs.duration }}
222+
AIPERF_EXPERIMENTAL_FAST: ${{ inputs.agentx-fast && '1' || '0' }}
217223
KV_OFFLOADING: ${{ inputs.kv-offloading }}
218224
KV_OFFLOAD_BACKEND: ${{ inputs.kv-offload-backend }}
219225
KV_OFFLOAD_BACKEND_METADATA: ${{ inputs.kv-offload-backend-metadata }}

.github/workflows/benchmark-tmpl.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ on:
129129
required: false
130130
type: string
131131
default: '3600'
132+
agentx-fast:
133+
description: "Use the AgentX 5-minute warmup and 20-minute profiling preset"
134+
required: false
135+
type: boolean
136+
default: false
132137
eval-limit:
133138
description: "Eval instance count: empty/full = whole split (default); N = first-N smoke slice"
134139
required: false
@@ -174,6 +179,7 @@ env:
174179
KV_P2P_TRANSFER: ${{ inputs.kv-p2p-transfer }}
175180
TOTAL_CPU_DRAM_GB: ${{ inputs.total-cpu-dram-gb }}
176181
DURATION: ${{ inputs.duration }}
182+
AIPERF_EXPERIMENTAL_FAST: ${{ inputs.agentx-fast && '1' || '0' }}
177183
EVAL_LIMIT: ${{ inputs.eval-limit }}
178184
SWEBENCH_GEN_MODE: ${{ inputs.swebench-gen-mode }}
179185
AIPERF_FAILED_REQUEST_THRESHOLD: '0.10'

.github/workflows/e2e-tests.yml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ on:
2121
required: false
2222
type: string
2323
default: ""
24+
agentx-fast:
25+
description: "AgentX fast feedback: 5-minute cache warmup and 20-minute profile."
26+
required: false
27+
type: boolean
28+
default: false
2429
eval-limit:
2530
description: "Eval instance count: empty/full = whole split (default); N = first-N smoke slice"
2631
required: false
@@ -50,6 +55,11 @@ on:
5055
required: false
5156
type: string
5257
default: ""
58+
agentx-fast:
59+
description: "AgentX fast feedback: 5-minute cache warmup and 20-minute profile."
60+
required: false
61+
type: boolean
62+
default: false
5363
eval-limit:
5464
description: "Eval instance count: empty/full = whole split (default); N = first-N smoke slice"
5565
required: false
@@ -264,7 +274,8 @@ jobs:
264274
kv-offload-backend: ${{ matrix.config['kv-offload-backend'].name }}
265275
kv-offload-backend-metadata: ${{ matrix.config['kv-offload-backend'] && toJson(matrix.config['kv-offload-backend']) || '' }}
266276
total-cpu-dram-gb: ${{ matrix.config.total-cpu-dram-gb }}
267-
duration: ${{ inputs.duration-override != '' && inputs.duration-override || matrix.config.duration }}
277+
duration: ${{ inputs.agentx-fast && '1200' || (inputs.duration-override != '' && inputs.duration-override || matrix.config.duration) }}
278+
agentx-fast: ${{ inputs.agentx-fast }}
268279
isl: '0'
269280
osl: '0'
270281
max-model-len: '0'
@@ -301,7 +312,8 @@ jobs:
301312
kv-offloading: ${{ matrix.config.kv-offloading }}
302313
kv-offload-backend: ${{ matrix.config.kv-offload-backend }}
303314
total-cpu-dram-gb: ${{ matrix.config.total-cpu-dram-gb }}
304-
duration: ${{ inputs.duration-override != '' && inputs.duration-override || matrix.config.duration }}
315+
duration: ${{ inputs.agentx-fast && '1200' || (inputs.duration-override != '' && inputs.duration-override || matrix.config.duration) }}
316+
agentx-fast: ${{ inputs.agentx-fast }}
305317
isl: '0'
306318
osl: '0'
307319
max-model-len: '0'
@@ -364,7 +376,8 @@ jobs:
364376
kv-offloading: ${{ matrix.config.kv-offloading }}
365377
kv-offload-backend: ${{ matrix.config['kv-offload-backend'].name }}
366378
kv-offload-backend-metadata: ${{ matrix.config['kv-offload-backend'] && toJson(matrix.config['kv-offload-backend']) || '' }}
367-
duration: ${{ inputs.duration-override != '' && inputs.duration-override || matrix.config.duration }}
379+
duration: ${{ inputs.agentx-fast && '1200' || (inputs.duration-override != '' && inputs.duration-override || matrix.config.duration) }}
380+
agentx-fast: ${{ inputs.agentx-fast }}
368381
run-eval: false
369382
scenario-type: agentic-coding
370383
ref: ${{ inputs.ref }}

AGENTS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ gh api -X POST \
119119

120120
Inputs: top-level `ref` (required) is the workflow ref to dispatch from, almost always `main`. `inputs[ref]` is the repo ref under test (defaults to the dispatch ref's `github.sha`). `inputs[generate-cli-command]` (required) is passed verbatim to `generate_sweep_configs.py` - test locally first. `inputs[test-name]` is the display name in the Actions UI. `inputs[duration-override]` overrides per-config duration (seconds); empty = use matrix value.
121121

122+
For an AgentX preflight, add `-F 'inputs[agentx-fast]=true'` to the dispatch command. This selects a 5-minute cache warmup and 20-minute profile for every AgentX job in that e2e dispatch and takes precedence over `duration-override`. Use it to get faster signal while debugging, then run the official sweep without `agentx-fast`; canonical AgentX timing remains a 10-minute cache warmup and 1-hour profile.
123+
122124
The POST returns no body and no run ID - find the run with `gh run list` below.
123125

124126
### Monitoring jobs

benchmarks/benchmark_lib.sh

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,15 @@ build_replay_cmd() {
17441744
# utils/aiperf/docs/tutorials/agentx-mvp.md.
17451745
local result_dir="$1"
17461746
local duration="$DURATION"
1747+
local cache_warmup_duration="${AIPERF_AGENTIC_CACHE_WARMUP_DURATION:-600}"
1748+
1749+
# Fast mode is an e2e-only feedback preset used before canonical one-hour
1750+
# sweeps. AIPerf already exposes both controls, so no AIPerf patch is
1751+
# required.
1752+
if [[ "${AIPERF_EXPERIMENTAL_FAST:-0}" == "1" ]]; then
1753+
duration=1200
1754+
cache_warmup_duration=300
1755+
fi
17471756

17481757
export AIPERF_DATASET_WEKA_LIVE_ASSISTANT_RESPONSES="${AIPERF_DATASET_WEKA_LIVE_ASSISTANT_RESPONSES:-0}"
17491758
# Dataset configuration (load + reconstruct + inputs.json + mmap)
@@ -1776,9 +1785,9 @@ build_replay_cmd() {
17761785
REPLAY_CMD+=" --trajectory-start-min-ratio 0.25"
17771786
REPLAY_CMD+=" --trajectory-start-max-ratio 0.75"
17781787
# After the normal t* snapshot warmup, continue those exact trajectories
1779-
# with one-token outputs and no idle delays for 10 minutes. Profiling begins
1780-
# only after those requests drain and resumes from the resulting live state.
1781-
REPLAY_CMD+=" --agentic-cache-warmup-duration 600"
1788+
# with one-token outputs and no idle delays. Profiling begins only after
1789+
# those requests drain and resumes from the resulting live state.
1790+
REPLAY_CMD+=" --agentic-cache-warmup-duration $cache_warmup_duration"
17821791
# Give long-context warmup requests up to 30 minutes to drain before
17831792
# declaring warmup failed. Recipes whose saturation arms carry a larger
17841793
# in-flight working set may override via AGENTIC_WARMUP_GRACE_PERIOD

0 commit comments

Comments
 (0)