Skip to content

Commit 5a68bc9

Browse files
Merge remote-tracking branch 'origin/main' into pr-1762-reuse-27706
2 parents 38be6be + 83d1a36 commit 5a68bc9

9 files changed

Lines changed: 1899 additions & 0 deletions

File tree

.github/workflows/speedbench-al.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,17 @@ jobs:
209209
path: speedbench_results/server_*.log
210210
if-no-files-found: ignore
211211

212+
# Per-request benchmark detail (vllm bench serve --save-detailed): includes
213+
# the model's response text per request, so the AL of each cell can be
214+
# audited for output correctness (sensible text + correct thinking mode).
215+
- name: Upload detailed benchmark results
216+
if: always()
217+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
218+
with:
219+
name: speedbench_detailed_results-${{ inputs.model-prefix }}
220+
path: speedbench_results/speedbench_*
221+
if-no-files-found: ignore
222+
212223
- name: Resource cleanup (post-run)
213224
if: always()
214225
run: *resource-cleanup
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
#!/usr/bin/env bash
2+
3+
# DeepSeek-R1 B300 vLLM SPEED-Bench AL matrix collector.
4+
#
5+
# Produces the golden acceptance-length (AL) reference matrix consumed by the
6+
# synthetic-acceptance framework: for each MTP level (num_speculative_tokens),
7+
# measure the REAL AL on a single SPEED-Bench category (default: coding) and emit
8+
# a YAML matrix identical in shape to benchmarks/speedbench-reference-al.yaml.
9+
# This measures real MTP acceptance; the synthetic value is injected downstream
10+
# by the throughput recipe, not here.
11+
#
12+
# Adapted from speedbench/dsv4_fp4_b300_vllm.sh. DeepSeek-R1 is DeepSeek-V3
13+
# architecture (MLA dense attention), NOT V4 (DSA / Lightning Indexer), so vs the
14+
# DSV4 collector:
15+
# - NO --tokenizer-mode deepseek_v4 / --reasoning-parser deepseek_v4 /
16+
# --tool-call-parser deepseek_v4 (all V4-specific; the official vLLM R1
17+
# serve command is bare). reasoning-parser is irrelevant here anyway: AL is
18+
# read from /metrics, not from parsed output.
19+
# - NO --attention_config.use_fp4_indexer_cache (that knob is dsv32/MLA-indexer
20+
# only; R1 is plain MLA and never reads it).
21+
# - NO --block-size / --compilation-config (the official R1 recipe omits them;
22+
# defaults apply). --kv-cache-dtype fp8 IS kept, to match the dsv4/qwen/glm
23+
# collectors so all golden AL values share one kv-cache numeric regime.
24+
# - FP4 on Blackwell needs FlashInfer MoE: export VLLM_USE_FLASHINFER_MOE_FP4=1.
25+
# - THINKING: R1 is a pure reasoning model and always emits <think> (its chat
26+
# template has no enable_thinking toggle). There is no thinking-off mode, so
27+
# this collector measures thinking_on only and needs no --chat-template-kwargs
28+
# shim (the default client-side template render already enables thinking).
29+
#
30+
# Checkpoint (B300 / Blackwell): NVFP4 build nvidia/DeepSeek-R1-0528-NVFP4-v2,
31+
# basename dsr1-fp4 on the runner (resolved by launch_b300-nv.sh).
32+
#
33+
# Usage (inside the vLLM container, on a B300 node):
34+
# export MODEL=/data/models/dsr1-fp4
35+
# bash benchmarks/single_node/speedbench/dsr1_fp4_b300_vllm.sh
36+
#
37+
# Tunables (env):
38+
# MTP_LIST space-separated MTP levels (default "1 2 3 4 5 6 7 8")
39+
# THINKING_MODES space-separated: on (default "on"; R1 has no off)
40+
# CATEGORY SPEED-Bench category (default coding)
41+
# SPEEDBENCH_OUTPUT_LEN per-request output len (default 4096)
42+
# OUT_YAML output matrix path (default $RESULTS_DIR/speedbench-reference-al.yaml)
43+
44+
set -uo pipefail
45+
source "$(dirname "$0")/../../benchmark_lib.sh"
46+
47+
MODEL="${MODEL:?MODEL env var required (e.g. /data/models/dsr1-fp4)}"
48+
SERVE_MODEL="${MODEL_PATH:-$MODEL}"
49+
TP="${TP:-8}"
50+
DP_ATTENTION="${DP_ATTENTION:-false}"
51+
PORT="${PORT:-8888}"
52+
53+
MTP_LIST="${MTP_LIST:-1 2 3 4 5 6 7 8}"
54+
THINKING_MODES="${THINKING_MODES:-on}"
55+
CATEGORY="${CATEGORY:-coding}"
56+
MODEL_KEY="${MODEL_KEY:-$(basename "$SERVE_MODEL" | tr '[:upper:]' '[:lower:]')}"
57+
SPEEDBENCH_OUTPUT_LEN="${SPEEDBENCH_OUTPUT_LEN:-4096}"
58+
CONCURRENCY="${CONCURRENCY:-1}"
59+
# Provider-recommended sampling from the DeepSeek-R1 checkpoint generation_config
60+
# (temperature 0.6, top_p 0.95; no top_k). vLLM's own default top_p is 1.0, so it
61+
# MUST be passed explicitly or the measured AL is taken at the wrong settings.
62+
TEMPERATURE="${TEMPERATURE:-0.6}"
63+
TOP_P="${TOP_P:-0.95}"
64+
65+
SPEEDBENCH_DIR="${SPEEDBENCH_DIR:-/workspace/speed_bench_data}"
66+
# Flat results dir to match the speedbench-al.yml artifact glob
67+
# (speedbench_results/server_*.log) and its pre-run `rm -rf speedbench_results`.
68+
RESULTS_DIR="${RESULTS_DIR:-/workspace/speedbench_results}"
69+
OUT_YAML="${OUT_YAML:-$RESULTS_DIR/speedbench-reference-al.yaml}"
70+
71+
# Blackwell FP4 MoE path (DeepSeek-R1 FP4 on B-series): required per vLLM R1 docs.
72+
export VLLM_USE_FLASHINFER_MOE_FP4="${VLLM_USE_FLASHINFER_MOE_FP4:-1}"
73+
export VLLM_ENGINE_READY_TIMEOUT_S=3600
74+
75+
mkdir -p "$RESULTS_DIR"
76+
nvidia-smi
77+
if [[ "$SERVE_MODEL" != /* ]]; then hf download "$SERVE_MODEL"; fi
78+
79+
# ---- Download SPEED-Bench dataset ----
80+
echo "=== Downloading SPEED-Bench dataset ==="
81+
pip install -q datasets tiktoken
82+
curl -LsSf https://raw.githubusercontent.com/NVIDIA-NeMo/Skills/refs/heads/main/nemo_skills/dataset/speed-bench/prepare.py \
83+
| python3 - --config qualitative --output_dir "$SPEEDBENCH_DIR"
84+
85+
if [[ ! -f "$SPEEDBENCH_DIR/qualitative.jsonl" ]]; then
86+
echo "CRITICAL: SPEED-Bench download failed — $SPEEDBENCH_DIR/qualitative.jsonl not found"
87+
exit 1
88+
fi
89+
90+
PARALLEL_ARGS=(--tensor-parallel-size "$TP" --data-parallel-size 1)
91+
if [ "${DP_ATTENTION}" = "true" ]; then
92+
PARALLEL_ARGS=(--tensor-parallel-size 1 --data-parallel-size "$TP")
93+
fi
94+
95+
fetch_metric() {
96+
local port="$1" name="$2"
97+
curl -s "http://localhost:${port}/metrics" \
98+
| grep -oP "${name}\\{[^}]*\\} \\K[0-9.]+" || echo "0"
99+
}
100+
101+
SERVER_PID=""
102+
_descendants() {
103+
local pid="$1" child
104+
for child in $(pgrep -P "$pid" 2>/dev/null || true); do
105+
echo "$child"
106+
_descendants "$child"
107+
done
108+
}
109+
cleanup_server() {
110+
if [[ -n "$SERVER_PID" ]]; then
111+
local descendants
112+
descendants=$(_descendants "$SERVER_PID")
113+
kill "$SERVER_PID" 2>/dev/null || true
114+
wait "$SERVER_PID" 2>/dev/null || true
115+
local pid
116+
for pid in $descendants; do
117+
kill -9 "$pid" 2>/dev/null || true
118+
done
119+
local waited=0
120+
while [[ $waited -lt 120 ]]; do
121+
local used
122+
used=$(nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits 2>/dev/null | sort -rn | head -1)
123+
if [[ -z "$used" || "$used" -lt 2000 ]]; then break; fi
124+
sleep 3; waited=$((waited + 3))
125+
done
126+
SERVER_PID=""
127+
fi
128+
}
129+
trap 'cleanup_server' EXIT
130+
131+
start_gpu_monitor
132+
133+
declare -A AL_RESULT
134+
135+
run_cell() {
136+
local mode="$1" mtp="$2"
137+
138+
echo ""
139+
echo "=========================================="
140+
echo " Cell: thinking=$mode MTP=$mtp category=$CATEGORY"
141+
echo "=========================================="
142+
143+
local serve_args=(
144+
--host 0.0.0.0 --port "$PORT"
145+
"${PARALLEL_ARGS[@]}"
146+
--pipeline-parallel-size 1
147+
--trust-remote-code
148+
--enable-expert-parallel
149+
--kv-cache-dtype fp8
150+
--no-enable-prefix-caching
151+
--max-model-len 16384
152+
--speculative-config "{\"method\": \"mtp\", \"num_speculative_tokens\": $mtp}"
153+
)
154+
155+
local server_log="$RESULTS_DIR/server_${mode}_mtp${mtp}.log"
156+
vllm serve "$SERVE_MODEL" "${serve_args[@]}" > "$server_log" 2>&1 &
157+
SERVER_PID=$!
158+
159+
if ! wait_for_server_ready --port "$PORT" --server-log "$server_log" --server-pid "$SERVER_PID"; then
160+
echo " -> server failed to start (thinking=$mode mtp=$mtp), recording N/A"
161+
AL_RESULT["${mode}_${mtp}"]="N/A"
162+
cleanup_server
163+
return
164+
fi
165+
166+
local acc_before drf_before acc_after drf_after
167+
acc_before=$(fetch_metric "$PORT" "vllm:spec_decode_num_accepted_tokens_total")
168+
drf_before=$(fetch_metric "$PORT" "vllm:spec_decode_num_drafts_total")
169+
170+
vllm bench serve \
171+
--model "$SERVE_MODEL" \
172+
--port "$PORT" \
173+
--dataset-name speed_bench \
174+
--dataset-path "$SPEEDBENCH_DIR" \
175+
--speed-bench-category "$CATEGORY" \
176+
--speed-bench-output-len "$SPEEDBENCH_OUTPUT_LEN" \
177+
--num-prompts -1 \
178+
--max-concurrency "$CONCURRENCY" \
179+
--save-result \
180+
--save-detailed \
181+
--result-dir "$RESULTS_DIR" \
182+
--result-filename "speedbench_${mode}_mtp${mtp}" \
183+
--trust-remote-code \
184+
--temperature "$TEMPERATURE" \
185+
--top-p "$TOP_P"
186+
187+
acc_after=$(fetch_metric "$PORT" "vllm:spec_decode_num_accepted_tokens_total")
188+
drf_after=$(fetch_metric "$PORT" "vllm:spec_decode_num_drafts_total")
189+
190+
local delta_acc delta_drf al
191+
delta_acc=$(awk "BEGIN {printf \"%d\", $acc_after - $acc_before}")
192+
delta_drf=$(awk "BEGIN {printf \"%d\", $drf_after - $drf_before}")
193+
if [[ "$delta_drf" -gt 0 ]]; then
194+
al=$(awk "BEGIN {printf \"%.2f\", 1 + ($delta_acc / $delta_drf)}")
195+
else
196+
al="N/A"
197+
fi
198+
echo " -> thinking=$mode MTP=$mtp AL=$al (accepted=$delta_acc drafts=$delta_drf)"
199+
AL_RESULT["${mode}_${mtp}"]="$al"
200+
201+
cleanup_server
202+
}
203+
204+
for mode in $THINKING_MODES; do
205+
for mtp in $MTP_LIST; do
206+
run_cell "$mode" "$mtp"
207+
done
208+
done
209+
210+
stop_gpu_monitor
211+
212+
# ---- Emit the YAML matrix ----
213+
emit_mode_block() {
214+
local mode="$1"
215+
for mtp in $MTP_LIST; do
216+
echo " $mtp: ${AL_RESULT[${mode}_${mtp}]:-N/A}"
217+
done
218+
}
219+
220+
{
221+
echo "# Acceptance Length (AL) reference values measured with SPEED-Bench."
222+
echo "# dataset: $CATEGORY | temperature: $TEMPERATURE | top_p: $TOP_P | output_len: $SPEEDBENCH_OUTPUT_LEN"
223+
echo "# DeepSeek-R1 always reasons (no thinking-off mode), so only thinking_on is emitted."
224+
echo "# Measured on $MODEL_KEY (B300, vLLM MTP), per num_speculative_tokens."
225+
echo "# Auto-generated by benchmarks/single_node/speedbench/dsr1_fp4_b300_vllm.sh (speedbench-al.yml)."
226+
echo "#"
227+
echo "# key = num_speculative_tokens (MTP level); value = golden AL"
228+
echo "${MODEL_KEY}:"
229+
if [[ " $THINKING_MODES " == *" on "* ]]; then
230+
echo " thinking_on:"
231+
emit_mode_block on
232+
fi
233+
if [[ " $THINKING_MODES " == *" off "* ]]; then
234+
echo " thinking_off:"
235+
emit_mode_block off
236+
fi
237+
} > "$OUT_YAML"
238+
239+
echo ""
240+
echo "=========================================="
241+
echo " SPEED-Bench AL matrix written to: $OUT_YAML"
242+
echo "=========================================="
243+
cat "$OUT_YAML"

benchmarks/single_node/speedbench/dsv4_fp4_b300_vllm.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ run_cell() {
275275
--num-prompts -1 \
276276
--max-concurrency "$CONCURRENCY" \
277277
--save-result \
278+
--save-detailed \
278279
--result-dir "$RESULTS_DIR" \
279280
--result-filename "speedbench_${mode}_mtp${mtp}" \
280281
--trust-remote-code \

0 commit comments

Comments
 (0)