Skip to content

Commit c94d0a4

Browse files
committed
fix(amd): preserve legacy AgentX fabric semantics
1 parent 74c0c85 commit c94d0a4

6 files changed

Lines changed: 132 additions & 1 deletion

File tree

‎benchmarks/multi_node/agentic_srt.sh‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,60 @@ done
4242
resolve_trace_source
4343
install_agentic_deps
4444

45+
# Preserve the legacy DP-attention replay contract. The SGLang router uses this
46+
# header to keep every request in one AgentX correlation tree on a stable DP
47+
# route, which is important for both session continuity and prefix-cache reuse.
48+
if [[ "${PREFILL_DP_ATTN:-false}" == "true" ]]; then
49+
export AIPERF_HTTP_X_SMG_ROUTING_KEY_FROM_CORRELATION_ID=true
50+
fi
51+
52+
# Reset every advertised SGLang worker before each concurrency point, matching
53+
# the retired amd_utils trace replay. /flush_cache covers GPU radix + host
54+
# HiCache; the storage-backend endpoint is best-effort because L3 is optional.
55+
clear_agentic_worker_caches() {
56+
local timeout_seconds="${FLUSH_DRAIN_TIMEOUT:-120}"
57+
local metrics_csv="${AIPERF_SERVER_METRICS_URLS:-}"
58+
if [[ -z "$metrics_csv" ]]; then
59+
echo "[clear_caches] WARN: AIPERF_SERVER_METRICS_URLS unset; skipping cache flush" >&2
60+
return 0
61+
fi
62+
63+
local -a metrics_urls
64+
IFS=',' read -r -a metrics_urls <<< "$metrics_csv"
65+
local metrics_url base_url start response code flushed
66+
for metrics_url in "${metrics_urls[@]}"; do
67+
[[ -n "$metrics_url" ]] || continue
68+
base_url="${metrics_url%/metrics}"
69+
start=$(date +%s)
70+
flushed=0
71+
response=""
72+
while :; do
73+
response=$(curl -sf -m 10 -X POST "${base_url}/flush_cache" 2>/dev/null || true)
74+
if grep -qi "Cache flushed" <<< "$response"; then
75+
flushed=1
76+
break
77+
fi
78+
if (( $(date +%s) - start >= timeout_seconds )); then
79+
break
80+
fi
81+
sleep 3
82+
done
83+
if (( flushed )); then
84+
echo "[clear_caches] ${base_url}: L1+L2 flushed"
85+
else
86+
echo "[clear_caches] WARN ${base_url}: L1+L2 flush not confirmed after ${timeout_seconds}s" >&2
87+
fi
88+
89+
code=$(curl -s -m 60 -o /dev/null -w '%{http_code}' \
90+
-X POST "${base_url}/hicache/storage-backend/clear" 2>/dev/null || true)
91+
if [[ "$code" == "200" ]]; then
92+
echo "[clear_caches] ${base_url}: L3 store cleared"
93+
else
94+
echo "[clear_caches] ${base_url}: L3 clear http=${code:-000} (optional backend unavailable)"
95+
fi
96+
done
97+
}
98+
4599
wait_for_agentic_servers_idle() {
46100
local timeout_seconds="${AIPERF_DRAIN_TIMEOUT_SECONDS:-1800}"
47101
local poll_seconds="${AIPERF_DRAIN_POLL_SECONDS:-10}"
@@ -125,6 +179,9 @@ for index in "${!CONCURRENCIES[@]}"; do
125179
mkdir -p "$RESULT_DIR"
126180

127181
echo "Running agentic concurrency $concurrency of: ${CONCURRENCIES[*]}"
182+
if [[ "${CLEAR_CACHE_BETWEEN_CONC:-1}" == "1" ]]; then
183+
clear_agentic_worker_caches
184+
fi
128185
build_replay_cmd "$RESULT_DIR"
129186
run_agentic_replay_and_write_outputs "$RESULT_DIR"
130187

‎perf-changelog.yaml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6670,4 +6670,5 @@
66706670
- "Add small-model aggregate and 1P1D disaggregated correctness lanes for the shared MI355X srt-slurm launcher."
66716671
- "Use the native SGLang router for request routing and AMD MoRI for disaggregated KV transfer, without Dynamo, NIXL, or the deleted amd_utils control plane."
66726672
- "Remove the active and deprecated MI355X matrix entries that depended on amd_utils; configuration-specific child PRs reintroduce the active production lanes as native srt-slurm recipes."
6673+
- "Preserve the retired AgentX launch contract in the shared srt path: route DP-attention sessions by correlation ID, flush every advertised worker cache before each concurrency point, and run the MI355X RDMA device/QoS/DCQCN plus bare-process GPU drain preflights on every allocated host."
66736674
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/2542

‎runners/check_mi355x_rdma.sh‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Fast, per-node fabric preflight for MI355X srt-slurm allocations. This keeps
5+
# the meaningful QoS/DCQCN gate from the retired amd_utils launcher without its
6+
# Docker or job-control plumbing.
7+
8+
log() { printf '[%s] %s\n' "$(hostname -s)" "$*"; }
9+
fail() { log "RDMA preflight failed: $*" >&2; exit 1; }
10+
11+
expected_devices="${IBDEVICES:-rdma0,rdma1,rdma2,rdma3,rdma4,rdma5,rdma6,rdma7}"
12+
IFS=',' read -r -a devices <<< "$expected_devices"
13+
for device in "${devices[@]}"; do
14+
[[ -d "/sys/class/infiniband/${device}" ]] || fail "missing device ${device}"
15+
done
16+
log "found all ${#devices[@]} expected RDMA devices: ${expected_devices}"
17+
18+
if ! command -v nicctl >/dev/null 2>&1; then
19+
log "nicctl is unavailable; device presence passed, QoS/DCQCN checks skipped"
20+
exit 0
21+
fi
22+
23+
probe=$(sudo -n nicctl show version firmware 2>&1 || true)
24+
if grep -qiE 'No AMD NICs|Invalid card handle|Failed to get NIC' <<< "$probe"; then
25+
fail "nicctl cannot access the AMD NICs"
26+
fi
27+
28+
qos=$(sudo -n nicctl show qos 2>/dev/null) || fail "nicctl show qos failed"
29+
classification=$(awk '/Classification type/ {print $NF; exit}' <<< "$qos")
30+
[[ "$classification" == "DSCP" ]] || fail "classification is ${classification:-unset}, expected DSCP"
31+
32+
priorities=$(awk '/PFC no-drop priorities/ {print $NF; exit}' <<< "$qos")
33+
bitmap=$(awk '/PFC priority bitmap/ {print $NF; exit}' <<< "$qos")
34+
[[ -n "$priorities" ]] || fail "PFC no-drop priorities are missing"
35+
[[ -n "$bitmap" && "$bitmap" != "0x0" ]] || fail "PFC is disabled"
36+
IFS=',' read -r -a priority_values <<< "$priorities"
37+
for priority in "${priority_values[@]}"; do
38+
priority="${priority//[^0-9]/}"
39+
[[ -n "$priority" ]] || fail "invalid PFC priority list: ${priorities}"
40+
(( bitmap & (1 << priority) )) || fail "PFC bitmap ${bitmap} does not cover priority ${priority}"
41+
done
42+
43+
dcqcn=$(sudo -n nicctl show dcqcn 2>/dev/null) || fail "nicctl show dcqcn failed"
44+
device_count=$(grep -c 'ROCE device' <<< "$dcqcn" || true)
45+
(( device_count > 0 )) || fail "no RoCE devices reported by nicctl"
46+
if grep 'Status' <<< "$dcqcn" | grep -qv 'Enabled'; then
47+
fail "DCQCN is disabled on at least one RoCE device"
48+
fi
49+
cnp_count=$(awk '/DSCP value used for CNP/ {print $NF}' <<< "$dcqcn" | sort -u | grep -c . || true)
50+
(( cnp_count == 1 )) || fail "CNP DSCP is inconsistent across NICs"
51+
52+
log "RDMA QoS/DCQCN preflight passed"

‎runners/launch_mi355x-amds-srt.sh‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,14 @@ if (
249249
decode_environment.setdefault(
250250
"SGLANG_MORI_NUM_MAX_DISPATCH_TOKENS_PER_RANK", str(dispatch_tokens)
251251
)
252+
# The retired launcher also exposed its harness-level dispatch budget to
253+
# the server environment after scaling it by the MTP draft width. Keep that
254+
# auxiliary value distinct from the model-specific per-rank SGLang pin.
255+
if "MORI_MAX_DISPATCH_TOKENS_DECODE" in decode_environment:
256+
mtp_size = int(os.environ.get("DECODE_MTP_SIZE", "0"))
257+
decode_environment["MORI_MAX_DISPATCH_TOKENS_DECODE"] = str(
258+
dispatch_tokens * (mtp_size + 1)
259+
)
252260
decode_environment["SGLANG_MORI_DISPATCH_INTER_KERNEL_SWITCH_THRESHOLD"] = str(
253261
2 * dispatch_tokens
254262
)

‎runners/prepare_mi355x_srt_host.sh‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
33

4+
"$(dirname "${BASH_SOURCE[0]}")/check_mi355x_rdma.sh"
5+
6+
# Preserve the legacy bare-process GPU drain gate. Slurm owns the node, but a
7+
# process left outside the prior job's container can still retain VRAM and make
8+
# the next model load fail much later with a misleading OOM.
9+
(
10+
unset IS_AGENTIC SCENARIO_TYPE
11+
# shellcheck source=benchmarks/benchmark_lib.sh
12+
source "$(dirname "${BASH_SOURCE[0]}")/../benchmarks/benchmark_lib.sh"
13+
wait_for_amd_gpu_clean
14+
)
15+
416
# Some MI355X experiments reserve large 2 MiB HugeTLB pools and leave the
517
# reservation behind after their Slurm allocation exits. Those free hugepages
618
# remain unavailable to ordinary host allocations, which can make a later

‎utils/evals/test_batched_eval.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,5 @@ def test_amd_srt_launcher_preserves_mori_dispatch_pin() -> None:
272272
assert 'decode_environment.setdefault(' in launcher
273273
assert '"SGLANG_MORI_NUM_MAX_DISPATCH_TOKENS_PER_RANK", str(dispatch_tokens)' in launcher
274274
assert '"SGLANG_MORI_DISPATCH_INTER_KERNEL_SWITCH_THRESHOLD"' in launcher
275-
assert "mtp_size + 1" not in launcher
275+
assert 'if "MORI_MAX_DISPATCH_TOKENS_DECODE" in decode_environment:' in launcher
276+
assert "dispatch_tokens * (mtp_size + 1)" in launcher

0 commit comments

Comments
 (0)