You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Introduce DFlash (block-diffusion) speculative decoding on the NPU/ATB
backend. The draft proposes a full block of candidate tokens in a single
non-causal forward from the target's captured intermediate-layer hidden
states, and the target verifies the block via the shared rejection sampler.
Supported targets:
- Qwen3 dense (e.g. Qwen3-8B) and Qwen3-MoE (e.g. Qwen3-Coder-30B-A3B) as
the verify target. Both are standard-attention, head_dim=128, 4D dense KV
cache; aux-hidden capture is enabled on qwen3.h and qwen3_moe.h.
- The draft is always a small dense Qwen3 (model_type=DFlashDraftModel),
regardless of whether the target is dense or MoE; it never runs experts.
- Hybrid / linear-attention targets (e.g. Qwen3.5/Next) are NOT supported in
this PR (deferred: they need a TORCH-backend draft and target-side capture).
Core pieces:
- DFlashWorkerImpl (runtime): prepare draft query / run draft / validate /
materialize context K/V / write accepted context, decoupled from MTP.
- DFlashContextKV helper: backend-independent fc -> RMSNorm -> fused per-layer
K/V linear -> per-layer k_norm + RoPE -> scatter, parameterized by
DFlashContextKVConfig (head_dim, rotary_dim from partial_rotary_factor,
rope_theta, k_norm) so it can be reused across draft bodies.
- DFlashQwen3 draft model + registration.
- DFlash always runs eager (both target validate and draft query). ACL graph
was measured net-negative for DFlash (validate flattens to DECODE, so its
captured-shape count grows with concurrency: -2% at C=1, -38% at C=16), so
the target and draft engines force enable_graph off; the shared graph engine
and the MTP/Eagle3 spec-verify graph path are untouched.
- Guard: DFlash and EAGLE-3 reject context parallelism (cp_size > 1), which
would feed the draft the wrong (lm_head-gathered) hidden states.
Correctness fixes folded in:
- chunked-prefill graph mask reset stale tail columns [kv_len, max_seq_len)
across replays; a heterogeneous-kv_len batch otherwise let a shorter
sequence attend to another sequence's KV (graph accept rate 1.11% ->
34.10%, matching eager).
- qwen3-moe forward asserts capture_idx == layers_to_capture_set_.size()
before returning aux hidden, mirroring qwen3.h, so a misconfigured
target_layer_id fails fast instead of feeding uninitialized memory.
- dflash validate reconstructs dense draft probs by default (honoring
enable_opt_validate_probs like MTP) so the shared rejection sampler and its
fused kernel always receive dim==3 probs; output-distribution-equivalent to
selected-only. scatter_selected_to_dense() is shared with
build_validate_tensors.
Validated (gsm8k, greedy, num_spec=15, eager):
- Qwen3-8B: accept rate 34.67% / accept length 6.20, matching the transformers
reference (34.87% / 6.23).
- Qwen3-Coder-30B-A3B (MoE, pure TP=2): accept rate 25.0% / 4.75 end-to-end.
0 commit comments