11#! /usr/bin/env bash
2- set -euo pipefail
2+ set -eo pipefail
33set -x
44
55# Agentic trace replay benchmark for DeepSeek-V4-Pro FP4 on B300 using vLLM.
6- # Mirrors the fixed-seq-len parallelism options (pure TP and DEP) so the
7- # agentic sweep can probe both interactivity and throughput regimes:
8- # pure TP (DP_ATTENTION=false, EP_SIZE=1): attention TP-sharded across
9- # all $TP GPUs in a single engine. Lower TPOT, lower batch.
10- # TP+EP (DP_ATTENTION=false, EP_SIZE>1): attention TP-sharded, MoE
11- # experts EP-sharded within the TP group.
12- # DEP (DP_ATTENTION=true, EP_SIZE>1): per-DP-rank attention with
13- # experts EP-sharded across DP ranks (per the vLLM blog recipe).
14- # Highest aggregate throughput at large CONC.
6+ # v4pro-b300.yaml TP4, DEP4, and DEP8 recipe. SimpleCPUOffload / MooncakeStore
157#
16- # Image is vllm/vllm-openai:v0.20.0-cu130. block_size=256, kv- cache-dtype=fp8 ,
17- # FP4 indexer cache enabled, FULL_AND_PIECEWISE cudagraph capture with
18- # custom_ops=all (per the vLLM blog recipe at https://vllm.ai/blog/deepseek-v4) .
8+ # Image is configured in nvidia-master.yaml. The recipe uses FP8 KV cache,
9+ # sparse DeepSeek-V4 FlashInfer attention with an FP4 indexer cache, mega-MoE,
10+ # and FULL_DECODE_ONLY CUDA graphs with every batch size captured explicitly .
1911#
2012# Required env vars:
2113# MODEL, TP, CONC, KV_OFFLOADING, TOTAL_CPU_DRAM_GB, RESULT_DIR
2214#
23- # KV_OFFLOADING=dram requires KV_OFFLOAD_BACKEND=mooncake.
15+ # TP4, TP8, and DEP8 (TP8 + DP-attention) are GPU-resident (KV_OFFLOADING=none).
16+ # DEP4 uses KV_OFFLOADING=dram with KV_OFFLOAD_BACKEND=vllm-simple or mooncake.
2417
2518source " $( dirname " $0 " ) /../../benchmark_lib.sh"
2619
2720check_env_vars MODEL TP CONC KV_OFFLOADING TOTAL_CPU_DRAM_GB RESULT_DIR DURATION EP_SIZE DP_ATTENTION
2821
29- DCP_SIZE=" ${DCP_SIZE:- 1} "
30- PCP_SIZE=" ${PCP_SIZE:- 1} "
31- VLLM_CP_ARGS=()
32- if [ " $DCP_SIZE " -gt 1 ]; then
33- VLLM_CP_ARGS+=(--decode-context-parallel-size " $DCP_SIZE " )
34- fi
35- if [ " $PCP_SIZE " -gt 1 ]; then
36- VLLM_CP_ARGS+=(--prefill-context-parallel-size " $PCP_SIZE " )
37- fi
38-
39- GPU_COUNT=" ${GPU_COUNT:- $((TP * PCP_SIZE))} "
22+ GPU_COUNT=$TP
4023if [[ ! " $GPU_COUNT " =~ ^[1-9][0-9]* $ ]]; then
4124 echo " Error: GPU_COUNT must be a positive integer, got '$GPU_COUNT '" >&2
4225 exit 1
4326fi
4427export GPU_COUNT
4528
46- if declare -p SLURM_JOB_ID > /dev/null 2>&1 && [ -n " $SLURM_JOB_ID " ]; then
47- SLURM_NODE=unknown
48- if declare -p SLURMD_NODENAME > /dev/null 2>&1 && [ -n " $SLURMD_NODENAME " ]; then
49- SLURM_NODE=" $SLURMD_NODENAME "
50- fi
51- echo " JOB $SLURM_JOB_ID running on $SLURM_NODE "
29+ # Under DP-attention the DP world size equals TP, and the DEP recipe sizes
30+ # per-rank batch as MAX_NUM_SEQS = 2*CONC/TP, which must be an integer.
31+ if [ " $DP_ATTENTION " = " true" ] && [ $(( 2 * CONC % TP)) -ne 0 ]; then
32+ echo " Error: DEP requires 2*CONC divisible by TP, got CONC='$CONC ' and TP='$TP '" >&2
33+ exit 1
34+ fi
35+
36+ # DEP8 (TP8 + DP-attention) is a GPU-resident, high-concurrency arm that is
37+ # tuned separately from the smaller DEP4 arm (larger prefill token budget,
38+ # long-prefill chunking, and a lower GPU-memory-utilization headroom).
39+ IS_DEP8=false
40+ if [ " $DP_ATTENTION " = " true" ] && [ " $TP " -eq 8 ]; then
41+ IS_DEP8=true
42+ fi
43+
44+ if [[ -n " $SLURM_JOB_ID " ]]; then
45+ echo " JOB $SLURM_JOB_ID running on $SLURMD_NODENAME "
5246fi
5347
5448# `hf download` creates the target dir if missing and is itself idempotent.
55- # When MODEL_PATH is unset (stand-alone runs), fall back to the HF_HUB_CACHE
49+ # When MODEL_PATH is unset (stand-alone runs), fall back to the HF_HUB_CACHE.
5650# Either way, MODEL_PATH is what the server is launched with.
57- if declare -p MODEL_PATH > /dev/null 2>&1 && [ -n " $MODEL_PATH " ]; then
51+ if [[ -n " $MODEL_PATH " ] ]; then
5852 if [[ ! -d " $MODEL_PATH " || -z " $( ls -A " $MODEL_PATH " 2> /dev/null) " ]]; then
5953 hf download " $MODEL " --local-dir " $MODEL_PATH "
6054 fi
@@ -68,17 +62,9 @@ nvidia-smi
6862resolve_trace_source
6963install_agentic_deps
7064
71- # vLLM v0.22.1 can ship CUTLASS DSL 4.5.2 with stale native MLIR bindings,
72- # which fails DSV4 indexer compilation with mlir_global_dtors(..., data).
73- # Reinstall the matching native wheel until NVIDIA/cutlass#3259 is resolved.
74- agentic_pip_install --quiet --force-reinstall --no-deps \
75- ' nvidia-cutlass-dsl-libs-cu13==4.5.2'
76-
7765# vllm-project/router expands the one HTTP backend into one logical worker per
78- # DP rank and sends X-data-parallel-rank on forwarded requests. aiperf's
79- # X-Correlation-ID is stable for every turn of a conversation; alias it to the
80- # router's preferred X-Session-ID header. This also keeps affinity correct when
81- # testing older wheels that prioritize per-request X-Request-ID.
66+ # DP rank. Bind every turn of a conversation to the same rank by mapping
67+ # AIPerf's stable correlation ID to the router's X-Session-ID header.
8268USE_VLLM_ROUTER=false
8369VLLM_BACKEND_PORT=" $PORT "
8470if [ " $DP_ATTENTION " = " true" ]; then
@@ -91,13 +77,13 @@ if [ "$DP_ATTENTION" = "true" ]; then
9177 agentic_pip_install --quiet " vllm-router==$VLLM_ROUTER_VERSION "
9278fi
9379
94- # DeepSeek-V4-Pro weights are large; engine startup can exceed default 600s.
80+ # Match the environment used by v4pro-b300.yaml.
81+ export VLLM_USE_V2_MODEL_RUNNER=1
9582export VLLM_ENGINE_READY_TIMEOUT_S=3600
96-
97- # vllm-project/vllm#43447 keeps local SWA prefix-cache tails sparsely, while
98- # vllm-project/vllm#44774 applies the same reachability policy to Mooncake's
99- # store mask. 32k matches the trace-replay tuning validated for this workload.
10083export VLLM_PREFIX_CACHE_RETENTION_INTERVAL=32768
84+ export VLLM_DSV4_MEGA_FP8_COMBINE=1
85+ export NCCL_NVLS_ENABLE=1
86+ export VLLM_USE_RUST_FRONTEND=1
10187
10288# ---- Server config ----------------------------------------------------------
10389SERVER_LOG=" $RESULT_DIR /server.log"
@@ -109,13 +95,47 @@ SERVER_PID=""
10995ROUTER_PID=" "
11096MOONCAKE_MASTER_PID=" "
11197
98+ # The generated TOTAL_CPU_DRAM_GB budget is proportional to allocated GPUs.
99+ # On cluster:b300-nv, dram-utilization=0.80 and DEP4 resolve to roughly the
100+ # source recipe's 280 GiB per DP rank. TP4 remains GPU-resident.
112101OFFLOAD_ARGS=()
113- if require_agentic_kv_offload_backend mooncake; then
114- # Mooncake embedded mode contributes one global segment per GPU rank to
115- # a shared distributed store. Pre-divide the aggregate host budget
116- # across those rank-contributed segments.
102+ case " $KV_OFFLOAD_BACKEND " in
103+ " " )
104+ require_agentic_kv_offload_none
105+ ;;
106+ vllm-simple)
107+ require_agentic_kv_offload_backend vllm-simple
108+ CPU_BYTES_PER_RANK=$(( TOTAL_CPU_DRAM_GB * 1000 * 1000 * 1000 / GPU_COUNT ))
109+ # Identical prefixes must hash to identical block keys across DP ranks.
110+ export PYTHONHASHSEED=42
111+ # The plain-TP (non-DP-attention) offload ladder uses lazy offload;
112+ # DEP keeps eager offload for cross-rank block-hash stability.
113+ SIMPLE_LAZY_OFFLOAD=false
114+ if [ " $DP_ATTENTION " != " true" ]; then
115+ SIMPLE_LAZY_OFFLOAD=true
116+ fi
117+ OFFLOAD_CONFIG=$( cat << EOF
118+ {
119+ "kv_connector": "SimpleCPUOffloadConnector",
120+ "kv_role": "kv_both",
121+ "kv_connector_extra_config": {
122+ "cpu_bytes_to_use": ${CPU_BYTES_PER_RANK} ,
123+ "enable_cross_layers_blocks": "true",
124+ "lazy_offload": ${SIMPLE_LAZY_OFFLOAD}
125+ }
126+ }
127+ EOF
128+ )
129+ OFFLOAD_ARGS=(
130+ --kv-transfer-config
131+ " $OFFLOAD_CONFIG "
132+ )
133+ ;;
134+ mooncake)
135+ require_agentic_kv_offload_backend mooncake
136+ # Embedded mode contributes one global segment per DP rank to the
137+ # shared store, so divide the aggregate host budget across ranks.
117138 PER_RANK_GB=$(( TOTAL_CPU_DRAM_GB / GPU_COUNT))
118-
119139 MOONCAKE_VERSION=0.3.11.post1
120140 agentic_pip_install --quiet --no-cache-dir --no-deps \
121141 --force-reinstall " mooncake-transfer-engine-cuda13==$MOONCAKE_VERSION "
139159 export MC_ENABLE_DEST_DEVICE_AFFINITY=1
140160 # Identical prefixes must hash to identical store keys across DP ranks.
141161 export PYTHONHASHSEED=0
142- # Large agentic KV writes can exceed Mooncake Store's fixed 60-second
143- # transfer deadline at the default 64 KiB RDMA slice size. Reduce
144- # per-transfer bookkeeping and give the shared RNIC more workers.
162+ export WITH_NVIDIA_PEERMEM=0
145163 export MC_SLICE_SIZE=1048576
146164 export MC_WORKERS_PER_CTX=4
147165
@@ -165,54 +183,106 @@ EOF
165183 fi
166184
167185 unset VLLM_USE_SIMPLE_KV_OFFLOAD
168- OFFLOAD_ARGS=(
169- --kv-transfer-config
170- ' {"kv_connector":"MooncakeStoreConnector","kv_role":"kv_both","kv_connector_extra_config":{"load_async":true}}'
171- )
172- fi
186+ OFFLOAD_CONFIG=' {"kv_connector":"MooncakeStoreConnector","kv_role":"kv_both","kv_connector_extra_config":{"load_async":true}}'
187+ OFFLOAD_ARGS=(--kv-transfer-config " $OFFLOAD_CONFIG " )
188+ ;;
189+ * )
190+ echo " Error: unsupported B300 KV_OFFLOAD_BACKEND='$KV_OFFLOAD_BACKEND '" >&2
191+ exit 1
192+ ;;
193+ esac
173194
174195PARALLEL_ARGS=(--tensor-parallel-size " $TP " --data-parallel-size 1)
175196if [ " $DP_ATTENTION " = " true" ]; then
176197 PARALLEL_ARGS=(--tensor-parallel-size 1 --data-parallel-size " $TP " )
177198fi
178199
179- EP_ARGS=()
200+ TP_ARGS=()
201+ if [ " $DP_ATTENTION " = " true" ]; then
202+ export PYTORCH_ALLOC_CONF=expandable_segments:True
203+ else
204+ export VLLM_ALLREDUCE_USE_FLASHINFER=1
205+ export VLLM_FLASHINFER_ALLREDUCE_BACKEND=auto
206+ TP_ARGS+=(--disable-custom-all-reduce)
207+ fi
208+
209+ MODE_ARGS=()
180210if [ " $EP_SIZE " -gt 1 ]; then
181- EP_ARGS=(--enable-expert-parallel)
211+ MODE_ARGS+=(
212+ --enable-expert-parallel
213+ --enable-ep-weight-filter
214+ --moe-backend deep_gemm_amxf4_mega_moe
215+ )
216+ fi
217+ if [ " $DP_ATTENTION " = " true" ]; then
218+ MODE_ARGS+=(--prefill-schedule-interval 8)
219+ if [ " $IS_DEP8 " = " true" ]; then
220+ # GPU-resident DEP8 gets a larger prefill token budget and chunks long
221+ # prefills so decode latency stays bounded at high concurrency.
222+ MODE_ARGS+=(
223+ --max-num-batched-tokens 16384
224+ --long-prefill-token-threshold 4096
225+ )
226+ else
227+ MODE_ARGS+=(--max-num-batched-tokens 8192)
228+ fi
182229fi
183230
184- # AgentX concurrency counts live session trees, not individual requests.
185- # Subagent fan-out can push instantaneous request concurrency above CONC, so
186- # leave 2x headroom rather than clipping those bursts at the scheduler.
187- MAX_NUM_SEQS= $(( 2 * CONC ))
188- if [ " $MAX_NUM_SEQS " -eq 128 ] ; then
189- MAX_NUM_SEQS=136
231+ if [ " $DP_ATTENTION " = " true " ] ; then
232+ # The DEP source recipe enforces 2* CONC = DP_WORLD_SIZE*MAX_NUM_SEQS.
233+ MAX_NUM_SEQS= $(( 2 * CONC / TP ))
234+ else
235+ # Preserve the previous TP4 scheduler headroom for agentic fan-out.
236+ MAX_NUM_SEQS=$(( 2 * CONC ))
190237fi
238+ CUDA_GRAPH_CAPTURE_SIZES=" "
239+ for (( capture_size = 1 ; capture_size <= MAX_NUM_SEQS; capture_size++ )) ; do
240+ if [ -n " $CUDA_GRAPH_CAPTURE_SIZES " ]; then
241+ CUDA_GRAPH_CAPTURE_SIZES+=" ,"
242+ fi
243+ CUDA_GRAPH_CAPTURE_SIZES+=" $capture_size "
244+ done
245+ COMPILATION_CONFIG=" {\" cudagraph_mode\" :\" FULL_DECODE_ONLY\" ,\" cudagraph_capture_sizes\" :[${CUDA_GRAPH_CAPTURE_SIZES} ],\" mode\" :0}"
191246
192247echo " Starting vllm server..."
193248export TORCH_CUDA_ARCH_LIST=" 10.0"
194249export PYTHONNOUSERSITE=1
195250export VLLM_FLOAT32_MATMUL_PRECISION=high
196251
197- vllm serve " $MODEL_PATH " --served-model-name " $MODEL " \
198- --host 0.0.0.0 \
199- --port " $VLLM_BACKEND_PORT " \
200- --trust-remote-code \
201- --kv-cache-dtype fp8 \
202- --block-size 256 \
203- " ${PARALLEL_ARGS[@]} " \
204- " ${VLLM_CP_ARGS[@]} " \
205- " ${EP_ARGS[@]} " \
206- --compilation-config ' {"cudagraph_mode":"FULL_AND_PIECEWISE","custom_ops":["all"]}' \
207- --attention_config.use_fp4_indexer_cache=True \
208- --tokenizer-mode deepseek_v4 \
209- --tool-call-parser deepseek_v4 \
210- --enable-auto-tool-choice \
211- --reasoning-parser deepseek_v4 \
212- --enable-prefix-caching \
213- --no-disable-hybrid-kv-cache-manager \
214- --max-num-seqs " $MAX_NUM_SEQS " \
215- " ${OFFLOAD_ARGS[@]} " > " $SERVER_LOG " 2>&1 &
252+ # DEP8 leaves more headroom for its larger prefill token budget.
253+ GPU_MEM_UTIL=0.96
254+ if [ " $IS_DEP8 " = " true" ]; then
255+ GPU_MEM_UTIL=0.92
256+ fi
257+
258+ { set +x; } 2> /dev/null
259+ VLLM_CMD=(
260+ vllm serve " $MODEL_PATH " --served-model-name " $MODEL "
261+ --host 0.0.0.0
262+ --port " $VLLM_BACKEND_PORT "
263+ --gpu-memory-utilization " $GPU_MEM_UTIL "
264+ --trust-remote-code
265+ --no-enable-flashinfer-autotune
266+ --no-disable-hybrid-kv-cache-manager
267+ --max-num-seqs " $MAX_NUM_SEQS "
268+ --kv-cache-dtype fp8
269+ --block-size 256
270+ --max-model-len 1048576
271+ --attention-config ' {"use_fp4_indexer_cache":true,"backend":"FLASHINFER_MLA_SPARSE_DSV4","use_prefill_query_quantization":true}'
272+ --disable-uvicorn-access-log
273+ --tokenizer-mode deepseek_v4
274+ --tool-call-parser deepseek_v4
275+ --enable-auto-tool-choice
276+ --reasoning-parser deepseek_v4
277+ --compilation-config " $COMPILATION_CONFIG "
278+ " ${PARALLEL_ARGS[@]} "
279+ " ${TP_ARGS[@]} "
280+ " ${MODE_ARGS[@]} "
281+ " ${OFFLOAD_ARGS[@]} "
282+ )
283+ printf ' %q ' " ${VLLM_CMD[@]} " | tee " $RESULT_DIR /vllm_command.txt"
284+ printf ' \n' | tee -a " $RESULT_DIR /vllm_command.txt"
285+ " ${VLLM_CMD[@]} " > " $SERVER_LOG " 2>&1 &
216286SERVER_PID=$!
217287echo " Server PID: $SERVER_PID "
218288
0 commit comments