Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions launchers/start-glm53-nvfp4-tp4.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ if [ -f "$PROFILE_ENV" ]; then
for _v in IMAGE MOE_BACKEND ENABLE_EP EAGER GRAPH_CAP MAX_SEQS MAX_BATCHED MAX_LEN \
GMU SPEC_K KV_DTYPE KV_BYTES DFLASH2 SPEC ASYNC_SCHED ATTN_BACKEND \
MODEL_HOST_PATH SERVED_NAME DRAFT_TP DRAFT_KV CUSTOM_OPS_AXIS COMPILE_CFG \
EXTRA_ENV LOAD_FORMAT DRAFT_SAMPLE REJECT_METHOD $_vllm_keys; do
EXTRA_ENV LOAD_FORMAT DRAFT_SAMPLE REJECT_METHOD PREFIX_CACHE $_vllm_keys; do
if [ -n "${!_v:-}" ]; then _caller="$_caller $_v=$(printf %q "${!_v}")"; fi
done
# shellcheck disable=SC1090
Expand Down Expand Up @@ -169,6 +169,21 @@ fi
# num_speculative_tokens MUST be 7 (drafter block 8 minus the verified token).
DFLASH2="${DFLASH2:-1}"
DRAFT_HOST_PATH=/home/choiceoh/models/GLM-5.3-Flash-DFlash2
# DFlash/DSpark synthesize their context KV from target hidden states. Tokens
# restored by automatic prefix caching do not run through the target, so this
# image leaves their draft KV slots unwritten while draft attention still
# reads them. That is upstream vLLM #47926: long shared-prefix workloads can
# collapse to position-0-only acceptance. Until that draft PR's four-file
# state/block-table repair lands, fail closed and make every prompt token flow
# through the target. PREFIX_CACHE=1 is an explicit throughput-first rollback;
# it may restore TTFT reuse at the cost of DFlash2 acceptance on cache hits.
PREFIX_CACHE="${PREFIX_CACHE:-0}"
case "$PREFIX_CACHE" in
0) PREFIX_CACHE_FLAG="--no-enable-prefix-caching" ;;
Comment on lines +180 to +182

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve prefix caching when DFlash2 is inactive

When the launcher is invoked with SPEC=0, its documented target-only mode cannot encounter the missing draft-KV problem, yet this unconditional default still emits --no-enable-prefix-caching; the same happens for the DFLASH2=0 MTP path. Before this change those modes inherited vLLM's enabled default, so shared-prefix target-only/MTP workloads now lose prefix reuse and its TTFT benefit unless callers discover and set the new override. Default the flag based on whether the DFlash2 path is actually active while still honoring an explicit PREFIX_CACHE value.

Useful? React with 👍 / 👎.

1) PREFIX_CACHE_FLAG="--enable-prefix-caching" ;;
*) echo "ABORT: PREFIX_CACHE must be 0 or 1 (got $PREFIX_CACHE)" >&2; exit 2 ;;
esac
[ "$PREFIX_CACHE" = 1 ] || echo "prefix-cache: disabled for DFlash2 draft-KV safety"
# The former AUDIT overlay replaced V1 files, but this image runs V2 Model
# Runner. Refuse the old switch instead of claiming an audit that cannot run.
[ "${AUDIT:-0}" = 0 ] || {
Expand Down Expand Up @@ -465,6 +480,7 @@ SERVE_ARGS="$MODEL_PATH \
${ATTN_BACKEND:+--attention-backend $ATTN_BACKEND }\
--max-model-len $MAX_LEN \
--max-num-seqs $MAX_SEQS --max-num-batched-tokens $MAX_BATCHED --block-size 2304 --moe-backend $MOE_BACKEND \
$PREFIX_CACHE_FLAG \
--load-format $LOAD_FORMAT \
${EP_FLAG:+$EP_FLAG }\
$SPECCFG_VAL \
Expand All @@ -483,7 +499,7 @@ $EAGER_FLAG --enable-flashinfer-autotune \
if [ "${DRY_RUN:-0}" = 1 ]; then
echo "profile : ${PROFILE_ENV:-<none>}"
for _k in IMAGE MOE_BACKEND ENABLE_EP VLLM_B12X_EP_COMPACT VLLM_B12X_EP_NO_DUMMY KV_DTYPE EAGER GRAPH_CAP GMU MAX_SEQS \
MAX_BATCHED MAX_LEN DFLASH2 SPEC SPEC_K ASYNC_SCHED \
MAX_BATCHED MAX_LEN DFLASH2 SPEC SPEC_K ASYNC_SCHED PREFIX_CACHE \
DRAFT_SAMPLE REJECT_METHOD; do
printf ' %-12s %s\n' "$_k" "${!_k:-<unset>}"
done
Expand Down
7 changes: 7 additions & 0 deletions profiles/glm53.env
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ VLLM_TARGET_LM_HEAD_FP8=1
# Verdict: both deltas within +/-2 pct => precision retired; the gap then
# lives in the drafter itself or bench content (dsv4's 78.5% came from its
# own bench mix) -- DRAFT_TP and content-matched benches are the next axes.
# DFlash2 context KV is built only for tokens that pass through the target.
# vLLM enables automatic prefix caching by default, but cache-hit tokens skip
# that forward and this image still lets the drafter attend to their unwritten
# KV slots (upstream draft PR #47926). Prefer acceptance correctness over TTFT
# reuse until that multi-file runtime fix lands. Set 1 only as an explicit
# throughput-first rollback for a workload known not to reuse prefixes.
Comment on lines +172 to +174
PREFIX_CACHE=0
# The drafter's block is 8; 7 is that minus the verified token. The launcher's
# default of 4 contradicts its own comment.
SPEC_K=7
Expand Down
32 changes: 32 additions & 0 deletions tests/test_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5217,6 +5217,37 @@ def test_launcher_reject_method_gate() -> None:
print(" launcher reject-method gate ... OK")


def test_dflash2_prefix_cache_fail_closed() -> None:
"""Cache-restored target tokens have no guaranteed DFlash context KV."""
launcher = open(
"launchers/start-glm53-nvfp4-tp4.sh", encoding="utf-8"
).read()
profile = open("profiles/glm53.env", encoding="utf-8").read()

check("PREFIX_CACHE=0" in profile,
"the DFlash2 profile must prefer valid draft KV over prefix TTFT reuse")
check('PREFIX_CACHE="${PREFIX_CACHE:-0}"' in launcher,
"a profile-less DFlash2 launch must also fail closed")
check("ABORT: PREFIX_CACHE must be 0 or 1" in launcher,
"an invalid cache-safety value must not reach vLLM")
check('0) PREFIX_CACHE_FLAG="--no-enable-prefix-caching"' in launcher
and '1) PREFIX_CACHE_FLAG="--enable-prefix-caching"' in launcher,
"both explicit vLLM BooleanOptionalAction flags must be wired")
serve = launcher[launcher.index('SERVE_ARGS="'):]
check("$PREFIX_CACHE_FLAG" in serve,
"the validated prefix-cache decision must reach the serve command")
names = _launcher_caller_passthrough(launcher)
check("PREFIX_CACHE" in names,
"a caller must be able to make the documented throughput rollback")
dry_run = launcher[launcher.index('if [ "${DRY_RUN:-0}" = 1 ]'):]
check("PREFIX_CACHE" in dry_run,
"dry-run must expose whether draft-KV safety or prefix reuse won")
check(launcher.index('PREFIX_CACHE="${PREFIX_CACHE:-0}"')
< launcher.index('SERVE_ARGS="'),
"prefix-cache validation must happen before serve args are frozen")
print(" dflash2 prefix-cache fail-closed OK")


def test_accept_profile_conditional_arithmetic() -> None:
"""pos[i] is a MARGINAL count; the conditional is pos[i] / pos[i-1].

Expand Down Expand Up @@ -5282,6 +5313,7 @@ def test_accept_profile_conditional_arithmetic() -> None:
test_hotpath_env_latches()
test_launcher_load_format_gate()
test_launcher_reject_method_gate()
test_dflash2_prefix_cache_fail_closed()
test_accept_profile_conditional_arithmetic()
test_launcher_nofile_limit()
test_prefill_ladder_probe()
Expand Down