Skip to content

Commit 71e7ad1

Browse files
committed
Add DSR1-0528 FP8 MI300X vLLM PD-disaggregation config
- .github/configs/amd-master.yaml: add dsr1-fp8-mi300x-vllm (2P2D TP8 MTP3) - benchmarks/multi_node/amd_utils/models_vllm.yaml: add DeepSeek-R1-0528 entry with M4 flags - benchmarks/multi_node/dsr1_fp8_mi300x_vllm-disagg.sh: new disagg recipe - runners/launch_mi300x-amds.sh: add IS_MULTINODE branch for MI300X disagg - benchmarks/multi_node/amd_utils/env.sh: Thor/bnxt explicit-match NCCL_IB_HCA + MORI_RDMA_DEVICES - benchmarks/multi_node/amd_utils/server_vllm.sh: 172.29.x RDMA IP, MoRIIO extra config, IS_MTP - benchmarks/multi_node/amd_utils/job.slurm: forward RDMA env vars, no host lib mounts for vllm - benchmarks/multi_node/amd_utils/bench.sh: --use-chat-template for vllm-disagg MTP - perf-changelog.yaml: document new config Image: vllm-mori-pd:milestone4-aiterwheel
1 parent 86e7761 commit 71e7ad1

10 files changed

Lines changed: 425 additions & 44 deletions

File tree

.github/configs/amd-master.yaml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,60 @@ dsr1-fp8-mi355x-sglang-mtp:
166166
search-space:
167167
- { tp: 8, ep: 1, conc-start: 4, conc-end: 64, spec-decoding: mtp }
168168

169+
dsr1-fp8-mi300x-vllm-disagg:
170+
image: vllm-mori-pd:milestone4-aiterwheel
171+
model: deepseek-ai/DeepSeek-R1-0528
172+
model-prefix: dsr1
173+
runner: mi300x-disagg
174+
precision: fp8
175+
framework: vllm-disagg
176+
multinode: true
177+
disagg: true
178+
scenarios:
179+
fixed-seq-len:
180+
- isl: 1024
181+
osl: 1024
182+
search-space:
183+
- spec-decoding: "mtp"
184+
conc-list: [ 8, 16, 32, 64, 128, 256, 512 ]
185+
prefill:
186+
num-worker: 2
187+
tp: 8
188+
ep: 1
189+
dp-attn: false
190+
additional-settings:
191+
- "PREFILL_NODES=2"
192+
- "VLLM_MORIIO_CONNECTOR_READ_MODE=1"
193+
decode:
194+
num-worker: 2
195+
tp: 8
196+
ep: 1
197+
dp-attn: false
198+
additional-settings:
199+
- "DECODE_NODES=2"
200+
- "DECODE_MTP_SIZE=3"
201+
- isl: 8192
202+
osl: 1024
203+
search-space:
204+
- spec-decoding: "mtp"
205+
conc-list: [ 8, 16, 32, 64, 128, 256, 512 ]
206+
prefill:
207+
num-worker: 2
208+
tp: 8
209+
ep: 1
210+
dp-attn: false
211+
additional-settings:
212+
- "PREFILL_NODES=2"
213+
- "VLLM_MORIIO_CONNECTOR_READ_MODE=1"
214+
decode:
215+
num-worker: 2
216+
tp: 8
217+
ep: 1
218+
dp-attn: false
219+
additional-settings:
220+
- "DECODE_NODES=2"
221+
- "DECODE_MTP_SIZE=3"
222+
169223
qwen3.5-bf16-mi355x-sglang:
170224
image: lmsysorg/sglang-rocm:v0.5.12-rocm720-mi35x-20260517
171225
model: Qwen/Qwen3.5-397B-A17B

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
**/__pycache__/**
22
**/.coverage
33
experimental/multiturn/vllm_benchmark/results/
4+
.venv/
5+
AMDSOW_CLUSTER_NOTES.md

benchmarks/multi_node/amd_utils/bench.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ for max_concurrency in "${chosen_concurrencies[@]}"; do
7878
extra_flags=""
7979
if [[ "$ENGINE" == "vllm-disagg" ]]; then
8080
extra_flags="--trust-remote-code --tokenizer $MODEL_PATH"
81+
if [ "$IS_MTP" = "true" ]; then
82+
extra_flags="$extra_flags --use-chat-template"
83+
fi
8184
else
8285
if [ "$IS_MTP" = "true" ]; then
8386
extra_flags="--use-chat-template"

benchmarks/multi_node/amd_utils/env.sh

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,18 @@ fi
4343

4444
set +x
4545

46-
export NCCL_IB_HCA=${NCCL_IB_HCA:-$IBDEVICES}
46+
# Pin RCCL/NCCL to the data-plane RDMA devices in explicit-match form.
47+
# Our NCCL 2.27 / RCCL 7.2 stack silently ignores the exclude/non-explicit form,
48+
# so every HCA name must carry its own leading '=' (e.g. '=rocep28s0,=rocep62s0,...').
49+
# This matches scripts/pd/lib_shared.sh in the AMDSOW delivery.
50+
_nccl_ib_hca=""
51+
IFS=',' read -ra _ib_arr <<< "$IBDEVICES"
52+
for _dev in "${_ib_arr[@]}"; do
53+
[[ -n "$_dev" ]] && _nccl_ib_hca+="=${_dev},"
54+
done
55+
_nccl_ib_hca="${_nccl_ib_hca%,}"
56+
export NCCL_IB_HCA=${NCCL_IB_HCA:-$_nccl_ib_hca}
57+
export MORI_RDMA_DEVICES=${MORI_RDMA_DEVICES:-$IBDEVICES}
4758

4859
# =============================================================================
4960
# Engine-specific environment
@@ -110,6 +121,11 @@ $1 == "DSCP" && $2 == ":" && $NF == p {
110121
elif [[ $NODENAME == mia1* ]]; then
111122
export UCX_IB_TRAFFIC_CLASS=104
112123
echo "[INFO] Auto-detected UCX_IB_TRAFFIC_CLASS=$UCX_IB_TRAFFIC_CLASS from hostname $NODENAME"
124+
elif [[ -n "${MORI_RDMA_TC:-}" ]]; then
125+
# AMDSOW MI300X Thor fallback: align UCX RoCEv2 TC with MORI_RDMA_TC
126+
# when the hostname does not match a known InfX pattern.
127+
export UCX_IB_TRAFFIC_CLASS=$MORI_RDMA_TC
128+
echo "[INFO] Falling back to UCX_IB_TRAFFIC_CLASS=$UCX_IB_TRAFFIC_CLASS from MORI_RDMA_TC"
113129
else
114130
echo "[INFO] No nicctl and unable to detect from hostname. Skipping QoS configuration."
115131
fi

benchmarks/multi_node/amd_utils/job.slurm

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,10 @@ if [[ "$ENGINE" == "vllm-disagg" ]]; then
392392
DOCKER_ENV_ENGINE=(
393393
-e VLLM_WS_PATH=${WS_PATH}
394394
-e MODEL_PATH=$DOCKER_MODEL_PATH
395+
-e IBDEVICES=${IBDEVICES}
396+
-e MORI_RDMA_DEVICES=${MORI_RDMA_DEVICES:-$IBDEVICES}
397+
-e MORI_RDMA_TC=${MORI_RDMA_TC:-104}
398+
-e MORI_KV_EXTRA_CONFIG_JSON=${MORI_KV_EXTRA_CONFIG_JSON:-}
395399
-e UCX_TLS=tcp,self,shm,rocm_ipc,rocm_copy,cma
396400
-e UCX_SOCKADDR_TLS_PRIORITY=tcp
397401
-e UCX_MEMTYPE_CACHE=y
@@ -441,7 +445,9 @@ echo \"Rank \$SLURM_PROCID on \$(hostname)\"
441445
eval \"\$DOCKER_CMD_DETECT\"
442446
echo \"[docker-detect] rank \$SLURM_PROCID: DOCKER_CMD=\$DOCKER_CMD\"
443447
444-
# Enable out-of-tree RDMA library mounts for atom-disagg (mooncake requires host RDMA stack)
448+
# Enable out-of-tree RDMA library mounts for atom-disagg (mooncake requires host RDMA stack).
449+
# Our vllm-mori-pd image is self-contained with bnxt_re ABI-8 libs; do NOT mount host RDMA
450+
# libraries for vllm-disagg to avoid ABI/version mismatch.
445451
RDMA_MOUNTS=()
446452
if [[ "$ENGINE" == "atom-disagg" ]]; then
447453

benchmarks/multi_node/amd_utils/models_vllm.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,10 @@ gpt-oss-120b:
4242
prefill_flags: "--tensor-parallel-size 8"
4343
decode_flags: "--tensor-parallel-size 8"
4444
env: "VLLM_USE_V1=1 VLLM_ROCM_USE_AITER=1 VLLM_ROCM_USE_AITER_TRITON_BF16_GEMM=0 VLLM_USE_AITER_UNIFIED_ATTENTION=1 VLLM_ROCM_USE_AITER_MHA=0 ROCM_TRITON_MOE_PRESHUFFLE_SCALES=0"
45+
46+
DeepSeek-R1-0528:
47+
# DSR1-0528 FP8 MI300X vLLM PD-disaggregation (AMDSOW Milestone4).
48+
# Tensor-parallel size is appended by server_vllm.sh from PREFILL_TP_SIZE / DECODE_TP_SIZE.
49+
prefill_flags: "--dtype auto --trust-remote-code --distributed-executor-backend mp --kv-cache-dtype fp8_e4m3 --block-size 64 --performance-mode throughput --no-enable-chunked-prefill --compilation-config '{\"cudagraph_mode\":\"FULL_AND_PIECEWISE\",\"pass_config\":{\"fuse_rope_kvcache\":true,\"fuse_rope_kvcache_cat_mla\":true,\"enable_sp\":true,\"fuse_gemm_comms\":true,\"fuse_act_padding\":true}}' --no-enable-prefix-caching --max-model-len 32768 --max-num-batched-tokens 32768 --gpu-memory-utilization 0.80"
50+
decode_flags: "--dtype auto --trust-remote-code --distributed-executor-backend mp --kv-cache-dtype fp8_e4m3 --block-size 64 --performance-mode throughput --no-enable-chunked-prefill --compilation-config '{\"cudagraph_mode\":\"FULL_AND_PIECEWISE\",\"pass_config\":{\"fuse_rope_kvcache\":true,\"fuse_rope_kvcache_cat_mla\":true,\"enable_sp\":true,\"fuse_gemm_comms\":true,\"fuse_act_padding\":true}}' --no-enable-prefix-caching --max-model-len 32768 --max-num-batched-tokens 32768 --gpu-memory-utilization 0.80 --speculative-config '{\"method\":\"deepseek_mtp\",\"num_speculative_tokens\":3}'"
51+
env: "VLLM_USE_V1=1 VLLM_ROCM_USE_AITER=1 VLLM_ROCM_USE_AITER_LINEAR=True VLLM_ROCM_USE_AITER_MLA=True VLLM_ROCM_USE_AITER_MOE=True VLLM_ROCM_USE_AITER_FUSION_SHARED_EXPERTS=1 VLLM_ROCM_QUICK_REDUCE_QUANTIZATION=INT4 VLLM_ROCM_QUICK_REDUCE_CAST_BF16_TO_FP16=1 VLLM_ROCM_QUICK_REDUCE_MAX_SIZE_BYTES_MB=2048 VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS=3600 VLLM_MORIIO_CONNECTOR_READ_MODE=true VLLM_MOE_DP_CHUNK_SIZE=1024 AITER_ENABLE_VSKIP=0 AITER_ONLINE_TUNE=0 AITER_BYPASS_TUNE_CONFIG=1 MORI_EP_LAUNCH_CONFIG_MODE=AUTO MORI_SHMEM_HEAP_SIZE=24G MORI_SHMEM_MODE=ISOLATION MORI_APP_LOG_LEVEL=INFO MORI_IO_QP_MAX_SEND_WR=8192 MORI_IO_QP_MAX_CQE=16384 MORI_IO_QP_MAX_SGE=4 MORI_RDMA_TC=104 MORI_IB_PATH_MTU=1024 NCCL_IB_DISABLE=0 MORI_ALLOW_FULL_CUDAGRAPH=1"

benchmarks/multi_node/amd_utils/server_vllm.sh

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ MODEL_PATH="${MODEL_PATH:-${MODEL_DIR}/${MODEL_NAME}}"
5252
source $WS_PATH/env.sh
5353

5454
host_ip=$(ip route get 1.1.1.1 2>/dev/null | awk '/src/ {print $7}')
55-
# RDMA IP for Nixl KV transfer (prefer 192.168.x.x subnet if available)
56-
rdma_ip=$(hostname -I | tr ' ' '\n' | grep '^192\.168\.' | head -1)
55+
# RDMA IP for Nixl KV transfer: prefer Thor data-plane subnet 172.29.x.x, then 192.168.x.x,
56+
# then fall back to the default-gateway interface IP.
57+
rdma_ip=$(hostname -I | tr ' ' '\n' | grep '^172\.29\.' | head -1)
58+
rdma_ip="${rdma_ip:-$(hostname -I | tr ' ' '\n' | grep '^192\.168\.' | head -1)}"
5759
rdma_ip="${rdma_ip:-$host_ip}"
5860
host_name=$(hostname)
5961

@@ -217,6 +219,33 @@ echo "Decode node IPs: ${DECODE_ARGS}"
217219
# MoRI-IO proxy ZMQ registration port (must match vllm-router --vllm-discovery-address)
218220
PROXY_PING_PORT="${PROXY_PING_PORT:-36367}"
219221

222+
# MoRIIO connector extra config: optional caller overrides merged with the
223+
# standard proxy endpoints. Prefer only proven keys; unknown keys are silently
224+
# ignored by the connector.
225+
MORI_KV_EXTRA_CONFIG_JSON="${MORI_KV_EXTRA_CONFIG_JSON:-{\"read_mode\":true,\"allow_full_cudagraph\":true}}"
226+
227+
KV_TRANSFER_CONFIG_BASE=$(python3 -c "
228+
import json, os
229+
extra = json.loads(os.environ.get('MORI_KV_EXTRA_CONFIG_JSON', '{}'))
230+
print(json.dumps(extra, separators=(',', ':')))
231+
")
232+
233+
# Prefill nodes are kv_producer; decode nodes are kv_consumer. The proxy IP,
234+
# ping port, and HTTP port are always nested inside kv_connector_extra_config.
235+
build_kv_config() {
236+
local role="$1"
237+
python3 -c "
238+
import json
239+
extra = json.loads('''${KV_TRANSFER_CONFIG_BASE}''')
240+
extra.update({'proxy_ip': '${NODE0_ADDR}', 'proxy_ping_port': '${PROXY_PING_PORT}', 'http_port': '${SERVER_PORT}'})
241+
cfg = {'kv_connector': 'MoRIIOConnector', 'kv_role': '${role}', 'kv_connector_extra_config': extra}
242+
print(json.dumps(cfg, separators=(',', ':')))
243+
"
244+
}
245+
246+
KV_TRANSFER_CONFIG_PRODUCER=$(build_kv_config kv_producer)
247+
KV_TRANSFER_CONFIG_CONSUMER=$(build_kv_config kv_consumer)
248+
220249
# vLLM runtime environment (static vars moved to env.sh; these depend on per-node state)
221250
setup_vllm_env() {
222251
export VLLM_NIXL_SIDE_CHANNEL_HOST=${rdma_ip}
@@ -256,7 +285,7 @@ if [ "$NODE_RANK" -eq 0 ]; then
256285
--served-model-name ${SERVED_MODEL} \
257286
--port $SERVER_PORT \
258287
--trust-remote-code \
259-
--kv-transfer-config '{\"kv_connector\": \"MoRIIOConnector\", \"kv_role\": \"kv_producer\", \"kv_connector_extra_config\": {\"proxy_ip\": \"${NODE0_ADDR}\", \"proxy_ping_port\": \"${PROXY_PING_PORT}\", \"http_port\": \"${SERVER_PORT}\"}}' \
288+
--kv-transfer-config "${KV_TRANSFER_CONFIG_PRODUCER}" \
260289
${PREFILL_SERVER_CONFIG}"
261290

262291
if [[ "$DRY_RUN" -eq 1 ]]; then
@@ -301,6 +330,12 @@ if [ "$NODE_RANK" -eq 0 ]; then
301330
echo "Benchmarking on ${host_name}:${host_ip}"
302331
cd $WS_PATH
303332

333+
if [[ "${DECODE_MTP_SIZE:-0}" -gt 0 ]]; then
334+
export IS_MTP=true
335+
else
336+
export IS_MTP=false
337+
fi
338+
304339
export ROUTER_PORT=$ROUTER_PORT
305340
BENCH_CMD="bash $WS_PATH/bench.sh ${xP} ${yD} $((GPUS_PER_NODE*xP)) $((GPUS_PER_NODE*yD)) \
306341
$MODEL_DIR $MODEL_NAME /run_logs/slurm_job-${SLURM_JOB_ID} ${BENCH_INPUT_LEN} \
@@ -410,7 +445,6 @@ if [ "$NODE_RANK" -eq 0 ]; then
410445
echo "ERROR: eval failed; exiting node-0 with rc=1"
411446
exit 1
412447
fi
413-
414448
elif [ "$NODE_RANK" -gt 0 ] && [ "$NODE_RANK" -lt "$xP" ]; then
415449
echo "${host_name}:${host_ip} is Additional Prefill Node (Model: ${MODEL_NAME})"
416450
echo "Using prefill config: $PREFILL_SERVER_CONFIG"
@@ -422,7 +456,7 @@ elif [ "$NODE_RANK" -gt 0 ] && [ "$NODE_RANK" -lt "$xP" ]; then
422456
--served-model-name ${SERVED_MODEL} \
423457
--port $SERVER_PORT \
424458
--trust-remote-code \
425-
--kv-transfer-config '{\"kv_connector\": \"MoRIIOConnector\", \"kv_role\": \"kv_producer\", \"kv_connector_extra_config\": {\"proxy_ip\": \"${NODE0_ADDR}\", \"proxy_ping_port\": \"${PROXY_PING_PORT}\", \"http_port\": \"${SERVER_PORT}\"}}' \
459+
--kv-transfer-config "${KV_TRANSFER_CONFIG_PRODUCER}" \
426460
${PREFILL_SERVER_CONFIG}"
427461

428462
if [[ "$DRY_RUN" -eq 1 ]]; then
@@ -478,7 +512,7 @@ else
478512
--served-model-name ${SERVED_MODEL} \
479513
--port $SERVER_PORT \
480514
--trust-remote-code \
481-
--kv-transfer-config '{\"kv_connector\": \"MoRIIOConnector\", \"kv_role\": \"kv_consumer\", \"kv_connector_extra_config\": {\"proxy_ip\": \"${NODE0_ADDR}\", \"proxy_ping_port\": \"${PROXY_PING_PORT}\", \"http_port\": \"${SERVER_PORT}\"}}' \
515+
--kv-transfer-config "${KV_TRANSFER_CONFIG_CONSUMER}" \
482516
${DECODE_SERVER_CONFIG}"
483517

484518
if [[ "$DRY_RUN" -eq 1 ]]; then
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/usr/bin/env bash
2+
# DSR1-0528 FP8 MI300X vLLM PD-disaggregation recipe.
3+
# Mirrors kimik2.5_fp4_mi355x_vllm-disagg.sh; model-specific flags live in
4+
# amd_utils/models_vllm.yaml under the DeepSeek-R1-0528 entry.
5+
6+
source "$(dirname "$0")/../benchmark_lib.sh"
7+
8+
check_env_vars \
9+
CONC_LIST \
10+
ISL \
11+
OSL \
12+
IMAGE \
13+
SPEC_DECODING \
14+
MODEL_PATH \
15+
PREFILL_NUM_WORKERS \
16+
PREFILL_TP \
17+
PREFILL_EP \
18+
PREFILL_DP_ATTN \
19+
DECODE_NUM_WORKERS \
20+
DECODE_TP \
21+
DECODE_EP \
22+
DECODE_DP_ATTN \
23+
PREFILL_NODES \
24+
DECODE_NODES \
25+
RANDOM_RANGE_RATIO \
26+
FRAMEWORK
27+
28+
if [[ -n "$SLURM_JOB_ID" ]]; then
29+
echo "JOB $SLURM_JOB_ID running on $SLURMD_NODENAME"
30+
fi
31+
32+
set -x
33+
34+
cd "$GITHUB_WORKSPACE/benchmarks/multi_node/amd_utils" || exit 1
35+
36+
export TIME_LIMIT="08:00:00"
37+
export MODEL_PATH=$MODEL_PATH
38+
export MODEL_NAME=$MODEL_NAME
39+
export CONTAINER_IMAGE=$IMAGE
40+
41+
# Same EP/DP booleans as other disagg recipes → amd_utils/submit.sh
42+
if [[ "${PREFILL_EP:-1}" -eq 1 ]]; then
43+
export PREFILL_ENABLE_EP=false
44+
else
45+
export PREFILL_ENABLE_EP=true
46+
fi
47+
48+
if [[ "$PREFILL_DP_ATTN" == "true" ]]; then
49+
export PREFILL_ENABLE_DP=true
50+
else
51+
export PREFILL_ENABLE_DP=false
52+
fi
53+
54+
if [[ "${DECODE_EP:-1}" -eq 1 ]]; then
55+
export DECODE_ENABLE_EP=false
56+
else
57+
export DECODE_ENABLE_EP=true
58+
fi
59+
60+
if [[ "$DECODE_DP_ATTN" == "true" ]]; then
61+
export DECODE_ENABLE_DP=true
62+
else
63+
export DECODE_ENABLE_DP=false
64+
fi
65+
66+
# Parameter order matches SGLang disagg submit.sh; arg 16 is optional NODELIST.
67+
JOB_ID=$(bash ./submit.sh $PREFILL_NODES \
68+
$PREFILL_NUM_WORKERS \
69+
$DECODE_NODES \
70+
$DECODE_NUM_WORKERS \
71+
$ISL $OSL "${CONC_LIST// /x}" inf \
72+
${PREFILL_ENABLE_EP} ${PREFILL_ENABLE_DP} \
73+
${DECODE_ENABLE_EP} ${DECODE_ENABLE_DP} \
74+
${PREFILL_TP} ${DECODE_TP} \
75+
${RANDOM_RANGE_RATIO} \
76+
"${NODELIST:-}")
77+
78+
if [[ $? -ne 0 ]]; then
79+
echo "Failed to submit job" >&2
80+
exit 1
81+
fi
82+
83+
echo "$JOB_ID"

perf-changelog.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4153,3 +4153,11 @@
41534153
- "Run the PR #1891 MiniMax-M3 MXFP8 B300 Dynamo-vLLM recipe set on top of current main."
41544154
- "Uses the vllm/vllm-openai:minimax-m3-0618-x86_64-cu130 image and the TEP4/TEP8 8k1k topologies not covered by PR #1890."
41554155
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/1891
4156+
- config-keys:
4157+
- dsr1-fp8-mi300x-vllm-disagg
4158+
description:
4159+
- "Add DSR1-0528 FP8 MI300X vLLM PD-disaggregation configuration"
4160+
- "Image: vllm-mori-pd:milestone4-aiterwheel"
4161+
- "Topology: 2P2D TP8 with MTP3 speculative decoding"
4162+
- "Runner: mi300x-disagg; framework: vllm-disagg"
4163+
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/XXX

0 commit comments

Comments
 (0)