wikillm

Paper · 2026-02-05 · cs.CL

DFlash: Block Diffusion for Flash Speculative Decoding

DFlash drafts a block of tokens in one parallel pass with a small block-diffusion model. Features from the target LLM are injected as keys and values into every draft layer, and the target verifies the block, so output stays lossless. Author-reported: 4.9x average greedy speedup over autoregressive decoding on Qwen3-4B across seven tasks, up to 6.1x on MATH-500.

Speculative decodingDiscrete diffusionLLM servinginferencedecodingdiffusion

arXivPDFCodeMarkdown20 min read

AI-compiled by claude-haiku-5-5 on 2026-10-18, not yet reviewed by a human. Every claim cites its source; check it when a detail matters.

In plain words

Language models usually write one word-piece at a time, and each step waits for the one before it. Speculative decoding speeds this up with a helper: a small model guesses several upcoming pieces, and the big model checks the whole guess in a single pass, keeping the part it agrees with.

DFlash changes the helper. Instead of guessing one piece after another, it fills in a block of blank slots all at once, the way diffusion models fill in masked text. Its main trick is that it gets to look at the big model's internal state while it guesses, not only the last word. Because the big model still checks every piece, the final text is the one it would have produced anyway, only faster.

The authors report that this is several times faster than plain decoding and clearly faster than a strong earlier helper method.

TL;DR

  • Speculative decoding with a non-autoregressive drafter: one parallel forward pass proposes a block of tokens §4.1.
  • The draft is a small block-diffusion transformer; target-model hidden features enter every draft layer as extra keys and values §4.1 app. A.3.
  • Reported on Qwen3, LLaMA-3.1 and others with the paper's own draft models; author-reported, Transformers and SGLang backends §5.
  • Official code is MIT-licensed, but it contains inference only: the training recipe cannot be checked against code model.py.

Problem

Autoregressive decoding is sequential and memory-bound, so latency and GPU utilisation suffer §1. Speculative decoding with a small drafter helps, but the strongest autoregressive drafter the paper cites (EAGLE-3) still drafts one token per step, which the authors say caps speedups at about 2–3× §1. Diffusion drafters avoid that serial cost, but previously proposed diffusion drafters used very large models (e.g. 7B parameters), and small autoregressive imitations of parallel drafting were limited by weak capacity §1. The question is whether a small, parallel drafter can still propose high-quality tokens §1.

Assumptions: the target model is a fixed autoregressive LLM whose hidden states are available; verification is done by that target §1 §3.1.

Method

Inference (§4.1)

  1. Context features. The target runs a normal prefill over the prompt and emits the first token. Hidden states are taken from a fixed set of layers spaced evenly from shallow to deep, concatenated, and projected once to one compact context feature. The paper calls this the target context feature §4.1. The projection is a linear map followed by RMS normalisation app. A.3.
  2. KV injection. The context feature is not added to the draft's input. In every draft layer it is projected into keys and values, alongside the draft tokens' keys and values. Queries come only from the draft tokens. Context entries skip the query projection, the output projection, attention updates and the feed-forward block, so they act as extra memory for the draft §4.1 app. A.3 fig. 2. Stored context entries are reused in later drafting rounds §4.1.
  3. Parallel block drafting. Each round starts from an anchor token, which is the target's last accepted or bonus token. The anchor is followed by block-size minus one mask tokens. The masked positions are embedded with the target's embedding table and decoded together in one draft forward pass §4.1 §4.2.
  4. Verification. The target runs one forward pass over the whole block. The accepted prefix and the target's own next token (the bonus token) are kept. The new anchor is the bonus token §3.1 §4.1.
  5. Lossless. Verification by the target keeps the output distribution of the target model, which the authors describe as lossless §1.

Drafting cost does not grow with the block size for moderate blocks, because the draft runs once per round rather than once per token §3.2 fig. 3. Deeper drafts give higher acceptance length but cost more per round §3.2 tab. 6.

Training (§4.2)

  1. Features from the clean sequence. The frozen target runs once over the full clean sequence, prompt plus response, to extract and fuse all features. The draft is trained on these features §4.2 fig. 4. Training responses are generated by the target model §5.
  2. Anchor-based blocks. Random response positions are chosen as anchors. Each anchor starts a block, and the remaining block positions are masked. The draft learns to predict the next block-size minus one tokens in parallel, matching inference §4.2. The paper states that standard block diffusion training divides the response uniformly and masks random positions inside each block; DFlash replaces this §4.2.
  3. Anchor count and resampling. A fixed number of anchors is drawn per sequence, and the anchor positions are resampled at every epoch. This bounds training cost on long sequences and augments the data §4.2 app. A.1.
  4. Packed blocks with a sparse mask. All blocks of a sequence are concatenated into one sequence. Tokens attend bidirectionally inside their own block and to the context features, and attention across blocks is disallowed. This lets many blocks train in one forward and backward pass with FlexAttention §4.2 fig. 4.
  5. Loss weighting. The cross-entropy for a token at position k of a block is multiplied by an exponentially decaying weight, so early positions count more, because an early error invalidates every later token in the draft §4.2 eq. 4.
  6. Frozen embeddings and head. The draft shares the target's token embedding and output head and keeps them frozen. Only the draft's transformer layers are trained §4.2.

Ablations: random anchor sampling beats standard uniform block construction on all three tasks tested tab. 13; KV injection beats input-only fusion in both autoregressive and block-diffusion drafting tab. 9; loss decay converges faster and to a higher acceptance length fig. 5 §4.2.

Key equations:

L = \frac{T_{\text{draft}} + T_{\text{verify}}}{\tau} eq. 1

w_k = \exp\!\left(-\frac{k-1}{\gamma}\right) eq. 4

Equation 1 gives per-token latency, where τ counts accepted tokens including the bonus token §3.1. Equations 2 and 3 give autoregressive and parallel drafting costs §3.2. The KV projection equations in the appendix are unnumbered app. A.3.

Pseudocode for one greedy decoding round, from the paper's inference description §4.1 §3.1:

Pseudocode
# One DFlash decoding loop, greedy case  [§4.1]
# Input:  target LLM, draft model, prompt token ids, max_new_tokens
# Output: generated token ids

def dflash_decode(target, draft, prompt, max_new_tokens):
    # Prefill: target gives the first token and its hidden states  [§4.1]
    first_token, hidden = target.prefill(prompt)
    # Fuse the chosen layers' features into one context feature  [app. A.3]
    context = draft.fuse(select_layers(hidden))    # (n_ctx, d)
    generated = [first_token]
    anchor = first_token
    while len(generated) < max_new_tokens:
        # Anchor plus B-1 mask tokens, embedded by the target  [§4.2]
        noise = target.embed([anchor] + [MASK] * (block_size - 1))
        # One parallel draft pass; keep only the mask positions  [§4.1]
        drafts = argmax(target.head(draft(noise, context)[1:]))
        # Target scores the whole block in one forward pass  [§3.1]
        posterior, verified = target.verify([anchor] + drafts)
        # Count drafts that match the target's greedy choice  [§3.1]
        accepted = count_leading_matches(drafts, posterior[:-1])
        # Keep the accepted drafts and the target's bonus token  [§3.1]
        bonus = posterior[accepted]
        generated += drafts[:accepted] + [bonus]
        # Add verified features to the context for the next round  [§4.1]
        context = concat(context, verified[:accepted + 1])
        anchor = bonus
    return generated[:max_new_tokens]

Pseudocode for one draft layer, with the context entering only as keys and values app. A.3:

Pseudocode
# One draft layer with target features as extra KV  [app. A.3]
# Input:  draft_states (B, d), context (n_ctx, d); B = block size
# Output: draft_states (B, d)

def draft_layer(draft_states, context, layer):
    # Queries come from the draft tokens only  [app. A.3]
    queries = layer.w_q(draft_states)
    # Context and draft tokens both give keys and values  [app. A.3]
    keys = concat(layer.w_k(context), layer.w_k(draft_states))
    values = concat(layer.w_v(context), layer.w_v(draft_states))
    # Attention over the context-plus-block sequence  [§4.1]
    mixed = attention(queries, keys, values)
    # Residual update of the draft tokens only  [app. A.3]
    hidden = draft_states + layer.w_o(mixed)
    return hidden + layer.feed_forward(hidden)

Pseudocode for the training loss, from the paper's description §4.2 eq. 4 app. A.1:

Pseudocode
# One training step of the draft model  [§4.2] [app. A.1]
# Input:  clean sequence = prompt + target-generated response
# Output: scalar loss

def training_loss(target, draft, sequence, response, block_size):
    # Frozen target forward over the clean sequence  [§4.2]
    hidden = target.hidden_states(sequence)
    context = draft.fuse(select_layers(hidden))
    # Random anchors in the response, a fixed count per sequence  [app. A.1]
    anchors = sample(response, num_anchors)
    # Each block: clean anchor, masked remainder  [§4.2]
    blocks = [make_block(sequence, a, block_size) for a in anchors]
    # Pack blocks into one sequence; attention stays inside each block [§4.2]
    preds = draft(pack(blocks), context, block_mask(blocks))
    # Decay the weight of later block positions  [eq. 4]
    weights = exp(-(block_positions - 1) / gamma)
    return weighted_cross_entropy(preds, targets, weights)

Hyperparameters

NameValueWhereNotes
Draft layers5 (Qwen3-4B, Qwen3-8B); 8 (Qwen3-Coder-30B-A3B-Instruct)§53, 5 and 8 layers compared in tab. 6
Block size B16 (Qwen3 models); 10 (LLaMA-3.1-8B)§5drafts B-1 tokens per round §4.2; B=8 in tab. 9
Target layers for context5 layers, uniform from the 2nd to the 3rd-to-last layer§5the paper gives no rounding rule; the code has one model.py
Shared embedding and LM headfrozen, shared with target§4.2
OptimizerAdamW, learning rate 6e-4app. A.1weight decay not stated
Gradient clipping1.0app. A.1
LR schedulecosine, warmup ratio 0.04app. A.1minimum LR not stated
Epochs6app. A.1
Maximum sequence length3072 (4096 for Qwen3-Coder)app. A.1
Anchors per sequence512, resampled every epochapp. A.1 §4.2
Loss decay γ7 (B=16); 5 (B=10); 4 (B=8)app. A.1 eq. 4index convention for k not stated
Training data, Qwen3around 800K samples from Nemotron Post-Training Dataset V2 and CodeAlpaca; responses generated by the target§5
Training data, LLaMA-3.1-8BUltraChat and ShareGPT, same as EAGLE-3§5.5.1
Ablation training set100K random samples from the mixture§5.5
Long-context fine-tune1.6K LongAlign-10K samples, 3 epochs, Qwen3.5-27B draft§5.4learning rate and batch size not stated
Max new tokens (evaluation)2048tab. 1
Sampling temperature0 and 1tab. 1top-p and top-k not stated
HardwareNVIDIA H200 (Transformers); single B200 with FA4 (SGLang)§5 §5.3
Concurrency sweep (SGLang)1, 4, 8, 16, 32tab. 3
Projection sizeW_c maps 5D to D, shared by all draft layersapp. A.3D = 2048 in the paper's memory example

Results

Author-reported. Setup: Transformers backend, thinking mode disabled, maximum 2048 generated tokens, NVIDIA H200 unless noted, speedup over the autoregressive baseline §5.1 tab. 1. Each cell is speedup / average acceptance length τ.

Table 1 tab. 1: Qwen3 models, thinking disabled

ModelMethodGSM8KMATH-500AIME25HumanEvalMBPPLCBMT-BenchAvg.
Temperature = 0
Qwen3-4BEAGLE-3 (16)1.99× / 3.301.83× / 3.081.79× / 3.051.84× / 3.051.78× / 2.951.73× / 2.911.74× / 3.021.81× / 3.05
Qwen3-4BEAGLE-3 (60)2.27× / 3.772.10× / 3.522.13× / 3.512.12× / 3.472.02× / 3.381.90× / 3.222.04× / 3.492.08× / 3.48
Qwen3-4BDFlash (16)5.15× / 6.536.09× / 7.845.68× / 7.275.21× / 6.644.78× / 6.095.41× / 7.092.85× / 4.354.91× / 6.54
Qwen3-8BEAGLE-3 (16)1.94× / 3.231.81× / 3.021.79× / 3.001.89× / 3.171.69× / 2.821.57× / 2.651.63× / 2.831.76× / 2.96
Qwen3-8BEAGLE-3 (60)2.23× / 3.712.05× / 3.492.05× / 3.442.17× / 3.651.93× / 3.251.81× / 3.031.90× / 3.262.02× / 3.40
Qwen3-8BDFlash (16)5.15× / 6.546.08× / 7.875.62× / 7.085.14× / 6.504.65× / 5.955.51× / 7.272.75× / 4.244.86× / 6.49
Temperature = 1
Qwen3-4BEAGLE-3 (16)1.89× / 3.221.75× / 2.991.64× / 2.791.74× / 3.011.69× / 2.891.63× / 2.771.70× / 2.951.72× / 2.95
Qwen3-4BEAGLE-3 (60)2.12× / 3.681.97× / 3.441.83× / 3.201.94× / 3.391.92× / 3.331.82× / 3.141.91× / 3.361.93× / 3.36
Qwen3-4BDFlash (16)4.71× / 6.005.09× / 6.673.73× / 4.924.74× / 6.044.42× / 5.664.90× / 6.502.67× / 4.074.24× / 5.69
Qwen3-8BEAGLE-3 (16)1.87× / 3.121.73× / 2.911.63× / 2.741.75× / 3.051.64× / 2.741.56× / 2.571.58× / 2.701.68× / 2.83
Qwen3-8BEAGLE-3 (60)2.07× / 3.591.94× / 3.381.84× / 3.182.05× / 3.541.85× / 3.161.72× / 2.921.70× / 3.051.88× / 3.26
Qwen3-8BDFlash (16)4.67× / 5.984.84× / 6.403.57× / 4.734.32× / 5.524.04× / 5.214.93× / 6.692.47× / 3.804.03× / 5.48

Parenthesised numbers are the EAGLE-3 draft-tree size, or the DFlash block size tab. 1 caption. The EAGLE-3 checkpoints for Qwen3 are from AngelSlim, a third party, and the LLaMA comparison uses the official EAGLE-3 checkpoint §5.

Table 2 tab. 2: Qwen3 models, thinking enabled (DFlash only)

ModelTemp.GPQAMATH-500AIME25
Qwen3-4B04.23× / 5.234.59× / 5.744.39× / 5.54
Qwen3-4B13.67× / 4.553.93× / 4.893.64× / 4.68
Qwen3-8B04.17× / 5.174.64× / 5.824.51× / 5.74
Qwen3-8B13.75× / 4.654.03× / 5.063.70× / 4.69

Table 3 tab. 3: SGLang throughput (tok/s), FA4 backend, single B200. Each block gives baseline throughput, DFlash throughput, the speedup and average τ.

ModelTaskRowc=1c=4c=8c=16c=32Avg. τ
Qwen3-4BMATH-500Baseline3161145220141007136–
Qwen3-4BMATH-500DFlash15314943906614477204178.01
Qwen3-4BMATH-500Speedup4.8×4.3×4.1×3.5×2.9×
Qwen3-4BHumanEvalBaseline3121162221741847143–
Qwen3-4BHumanEvalDFlash12474147699711234157036.63
Qwen3-4BHumanEvalSpeedup4.0×3.6×3.2×2.7×2.2×
Qwen3-8BMATH-500Baseline230861166631335694–
Qwen3-8BMATH-500DFlash11753884748512268160768.01
Qwen3-8BMATH-500Speedup5.1×4.5×4.5×3.9×2.8×
Qwen3-8BHumanEvalBaseline229868164932535462–
Qwen3-8BHumanEvalDFlash955309260109919131166.50
Qwen3-8BHumanEvalSpeedup4.2×3.6×3.6×3.0×2.4×
Qwen3-Coder-30B-A3BHumanEvalBaseline229686106816812713–
Qwen3-Coder-30B-A3BHumanEvalDFlash80220783442542983148.09
Qwen3-Coder-30B-A3BHumanEvalSpeedup3.5×3.0×3.2×3.2×3.1×
Qwen3-Coder-30B-A3BLCBBaseline220681111217332823–
Qwen3-Coder-30B-A3BLCBDFlash56916212554416064016.42
Qwen3-Coder-30B-A3BLCBSpeedup2.6×2.4×2.3×2.4×2.3×
Qwen3-Coder-30B-A3BMBPPBaseline228682105716972735–
Qwen3-Coder-30B-A3BMBPPDFlash72020523360552285387.23
Qwen3-Coder-30B-A3BMBPPSpeedup3.2×3.0×3.2×3.3×3.1×

Table 4 tab. 4: long-context acceptance length, Qwen3.5-27B base draft vs long-context fine-tune (τ; columns: base / long)

Contexthotpotqaqaspergov_report
1K4.91 / 4.995.27 / 5.384.53 / 4.53
2K4.97 / 5.065.50 / 5.674.35 / 4.38
4K4.91 / 5.415.17 / 5.803.93 / 4.25
8K4.46 / 5.764.17 / 5.623.32 / 4.04
16K3.61 / 6.053.57 / 6.002.67 / 3.81
32K––2.09 / 3.56

Table 5 tab. 5: LLaMA-3.1-8B-Instruct, SGLang with FlashInfer, single B200. Speedups per concurrency level; baseline row gives absolute tok/s.

TaskMethodc=1c=4c=8c=16c=32Avg. τ
GSM8KBaseline (tok/s)249923173932455349–
GSM8KEAGLE-3 (10)1.6×1.5×1.4×1.2×1.0×3.49
GSM8KEAGLE-3 (60)1.9×1.6×1.3×0.9×0.6×4.55
GSM8KDFlash (10)2.4×2.2×2.1×1.8×1.6×4.32
HumanEvalBaseline (tok/s)245922177833365854–
HumanEvalEAGLE-3 (10)2.0×1.9×1.8×1.5×1.2×3.62
HumanEvalEAGLE-3 (60)2.0×1.7×1.3×0.9×0.6×4.65
HumanEvalDFlash (10)2.8×2.6×2.5×2.1×1.8×4.91
AlpacaBaseline (tok/s)245906174532375434–
AlpacaEAGLE-3 (10)1.5×1.4×1.4×1.1×0.9×3.11
AlpacaEAGLE-3 (60)1.8×1.5×1.2×0.8×0.5×4.07
AlpacaDFlash (10)2.2×2.0×1.8×1.5×1.4×3.73

Table 6 tab. 6: number of draft layers (block 16, 5 hidden features; speedup / τ)

SettingMath500HumanEvalMT-Bench
3 layers4.69× / 5.643.90× / 4.612.38× / 3.18
5 layers4.71× / 5.993.96× / 4.942.35× / 3.37
8 layers4.64× / 6.333.96× / 5.292.23× / 3.50

Table 7 tab. 7: number of target hidden features (block 16, 3 draft layers; speedup / τ)

SettingMath500HumanEvalMT-Bench
3 features4.49× / 5.383.80× / 4.472.32× / 3.07
5 features4.69× / 5.643.90× / 4.612.38× / 3.18

Table 8 tab. 8: training versus inference block size (8 layers, 5 features; speedup / τ)

Train BTest BMath500HumanEvalMT-Bench
16164.64× / 6.333.96× / 5.292.23× / 3.50
1683.87× / 5.093.39× / 4.442.12× / 3.18
8163.78× / 5.023.24× / 4.282.09× / 3.09
883.97× / 5.213.53× / 4.612.22× / 3.29

Table 9 tab. 9: target-feature conditioning (Qwen3-4B, 5-layer drafts, block 8; τ / speedup)

VariantInjectionGSM8KHumanEvalMT-Bench
EAGLE-3 (5 layers), autoregressiveInput4.2 / 2.1×4.3 / 2.2×3.1 / 1.4×
DFlash-AR, autoregressiveKV4.8 / 2.4×4.6 / 2.3×3.4 / 1.5×
DFlash, block diffusionInput3.5 / 2.9×3.5 / 2.9×2.6 / 2.0×
DFlash, block diffusionKV4.2 / 3.3×4.0 / 3.2×3.0 / 2.2×

Table 10 tab. 10: draft without target features (appendix; speedup / τ; no context features, 5 layers)

Temp.GSM8KMath500AIME24AIME25
02.83× / 3.383.73× / 4.613.43× / 4.123.35× / 4.07
12.76× / 3.293.31× / 4.122.66× / 3.232.65× / 3.24

Table 11 tab. 11: more target models, SGLang, concurrency 8 (τ / speedup; MTP is the native multi-token prediction the paper compares against app. A.4)

ModelMethodMath500HumanEvalMT-Bench
Qwen3.5-4BMTP6.5 / 1.5×6.3 / 1.6×5.3 / 1.3×
Qwen3.5-4BDFlash7.1 / 3.0×7.3 / 2.9×5.6 / 2.3×
Qwen3.5-9BMTP6.7 / 1.7×6.6 / 1.7×5.3 / 1.3×
Qwen3.5-9BDFlash7.3 / 3.5×7.9 / 3.4×5.5 / 2.5×
Qwen3.5-35B-A3BMTP6.9 / 1.7×7.1 / 1.6×5.2 / 1.2×
Qwen3.5-35B-A3BDFlash7.2 / 2.4×7.9 / 2.3×5.4 / 1.7×
Qwen3.5-27BDFlash7.7 / 3.8×9.1 / 3.9×5.5 / 2.5×
Qwen3-Coder-NextDFlash6.0 / 1.9×7.2 / 1.9×3.9 / 1.2×
GPT-OSS-20BDFlash5.1 / 2.2×4.3 / 2.2×4.2 / 2.0×
GPT-OSS-120BDFlash5.4 / 1.6×4.4 / 1.7×3.7 / 1.3×

Table 12 tab. 12: vLLM, Qwen3.5-9B (DFlash tok/s, speedup in parentheses)

ConcurrencyMath500HumanEvalMT-Bench
1849 (4.0×)969 (4.6×)627 (3.0×)
85096 (3.2×)5434 (3.4×)3536 (2.2×)
167669 (2.5×)8131 (2.7×)5297 (1.7×)
329836 (1.9×)10258 (2.1×)6787 (1.3×)

Table 13 tab. 13: anchor sampling vs standard blocks (3 layers, 5 features, block 16; speedup / τ)

SettingMath500HumanEvalMT-Bench
Standard4.13× / 4.943.29× / 3.862.13× / 2.80
Random anchors4.69× / 5.643.90× / 4.612.38× / 3.18

Figures, described only fig. 1 fig. 2 fig. 3 fig. 4 fig. 5: fig. 1 plots speedup against autoregressive decoding for DFlash and EAGLE-3 on Qwen3-8B with the Transformers backend. fig. 2 shows the inference design, with context features injected into each draft layer's key-value cache. fig. 3 compares draft latency of 1, 3 and 5-layer DFlash with a 1-layer EAGLE-3. fig. 4 is the training attention pattern: clean prompt and response, anchors, mask tokens, and the blocked cross-block attention. fig. 5 shows acceptance length per epoch with and without loss decay.

Paper vs code

Code: https://github.com/z-lab/dflash at code_commit 07ebd93, MIT licence; the paper links this repository [abstract]. Files read: dflash/model.py and README.md in full, dflash/cli.py for defaults, and dflash/benchmark.py by search only.

  • No training code. The repository contains inference, the CLI, benchmarks and an MLX port. It has no loss, anchor sampler, optimiser or data pipeline. A search for loss, anchor, AdamW, learning-rate and decay terms in dflash/*.py found none. The training recipe (anchor sampling, eq. 4 and the settings in app. A.1) therefore cannot be checked against code. model.py covers inference only.
  • Context layers match the text. Paper: five layers between the second and the third-to-last layer §5. Code: start index 1, end index L-3, spaced evenly model.py. extract_context_feature adds one because hidden state 0 is the embedding output model.py. If a checkpoint config sets target_layer_ids, that list overrides the formula model.py.
  • KV injection matches, with extras. Code projects target features and draft states with the same key and value weights and concatenates them model.py. It also applies per-head RMS normalisation to queries and keys model.py and rotary embeddings to context keys at their absolute positions model.py. The paper's appendix equations include neither app. A.3.
  • Context fusion matches. A linear map to the hidden size, then RMS normalisation model.py matches app. A.3.
  • Embedding and head. The code uses the target's input embeddings multiplied by input_embedding_scale model.py, and its output head multiplied by output_multiplier with optional tanh soft-capping model.py. The defaults are 1.0 and no capping model.py. The paper mentions neither mechanism §4.2.
  • Drafted tokens match. The anchor's output is dropped and the B-1 mask positions are decoded, greedily at temperature 0 model.py. This matches §4.2.
  • Attention pattern. Full-attention draft layers are non-causal, so the block attends bidirectionally to itself and the context model.py §4.1. The code also supports per-layer sliding-window attention from layer_types model.py. The paper does not describe it.
  • Acceptance length counts the bonus token. produced = accepted + 1 is what the benchmark averages model.py, matching the definition in §3.1.
  • Sampling rule. At temperature 0, a draft is accepted while it equals the target's argmax; the bonus token is the target's argmax after the accepted prefix model.py. At temperature above 0, speculative rejection sampling with residual resampling is used model.py. Top-p and top-k apply to both draft and target distributions model.py. The paper's text does not spell out this rule.
  • Maximum length. The CLI defaults to 2048 new tokens and greedy decoding cli.py, matching the setting in tab. 1.
  • DFlash 2 is a different model. DFlash2DraftModel adds grouped dynamic causal convolutions and a candidate selector model.py. Neither appears in this paper. Do not implement them as DFlash.

Pitfalls

  • Headline numbers are best cases. "Over 6x" in the abstract and "6.1x" in the introduction are single-task peaks on MATH-500 §1 tab. 1. Seven-task greedy averages are 4.9x for both Qwen3 models, and temperature-1 averages are 4.2x and 4.0x tab. 1. Chat (MT-Bench) speedups are much lower, 2.85x and 2.75x at greedy tab. 1.
  • The EAGLE-3 ratio is attributed to the wrong tree size. The text gives 2.4x for greedy decoding "over EAGLE-3 (16)" and 2.2x at temperature 1, without a tree size §5.1. The numbers match the tree-size-60 averages in tab. 1: 4.91/2.08 and 4.86/2.02 for greedy, and 4.24/1.93 and 4.03/1.88 at temperature 1. Against tree size 16 the ratios are about 2.7x and 2.8x (greedy) and 2.5x and 2.4x (temperature 1).
  • Reasoning averages. §5.2 says "roughly 4.5x and 3.9x" §5.2. The three-task averages in tab. 2 are about 4.4x (greedy) and about 3.8x (temperature 1). The paper does not say which temperature the rounded figures refer to.
  • Naive-draft range. §4.1 says draft models without context features give speedups "typically around 2–3x" §4.1. tab. 10 shows 2.65x to 3.73x.
  • Identical τ in Table 3. Qwen3-4B and Qwen3-8B on MATH-500 both list τ = 8.01 tab. 3. This may be a copy error; the paper gives no way to check it.
  • Serving tables are not comparable with Table 1. tab. 1 uses Transformers on H200; tab. 3 uses SGLang with FA4 on B200 §5 §5.3. Do not compare speedups across these tables.
  • Speedups fall with concurrency. Qwen3-4B on MATH-500 drops from 4.8x at one request to 2.9x at 32 tab. 3. The paper says large blocks cost more to verify when compute-bound §5.5.4.
  • Block size transfers in one direction only. A model trained at 16 works at 8 but a model trained at 8 does not work well at 16 §5.5.4 tab. 8. The paper leaves adaptive block-size scheduling for future work.
  • Token count per round. §3.2 says a 5-layer draft "generating 16 tokens" §3.2. §4.2 and the code draft B-1 = 15 tokens per round, plus the anchor §4.2 model.py. Use γ = B-1 in eq. 1–3 unless the paper says otherwise.
  • Index k in eq. 4 is ambiguous. The paper does not say whether k = 1 is the anchor or the first masked position §4.2 eq. 4. With no training code in the repository, choose one and record it.
  • Loss normalisation not stated. The paper does not say whether the weighted cross-entropy is summed or averaged over positions, blocks or the batch §4.2.
  • Block packing not fully specified. The paper says attention across blocks is disallowed §4.2 fig. 4 but not whether blocks may overlap in response positions, or how many blocks fit a sequence beyond the fixed anchor count app. A.1.
  • Context KV cache grows with length. The appendix quantifies the projection and per-round activations only app. A.3. The context entries are stored in each draft layer's KV cache for the whole sequence §4.1 model.py, and that memory is not quantified. The 42 MB figure is for Qwen3.5-35B-A3B, not the Qwen3 models app. A.3.
  • Feature indexing. Hidden states from Hugging Face-style outputs include the embedding output at index 0. Index target layers with the offset in model.py, not directly.
  • Positional encoding of context features. The paper does not say how context entries are positioned. The code gives them the absolute positions of their tokens model.py.
  • Baseline checkpoints. EAGLE-3 checkpoints for Qwen3 come from AngelSlim, a third party §5. The LLaMA comparison uses the official EAGLE-3 checkpoint, and the paper trains DFlash on the same data for that comparison §5.5.1.
  • Long-context fine-tune. The learning rate and batch size are not stated §5.4. The base draft degrades beyond 4K tokens tab. 4.
  • Models beyond Qwen3 and LLaMA. Qwen3.5, Qwen3-Coder-Next and GPT-OSS results appear only in the serving and vLLM tables app. A.4 tab. 11 tab. 12. Their training recipes are not described beyond the general settings above.
  • Lossless claim. The paper calls the output lossless §1. Greedy decoding gives exactly the target's greedy output, and sampling uses rejection sampling in the code model.py. The paper's sections read here do not give that argument in full.

Lineage

  • Builds on: Speculative decoding (Leviathan et al.), which introduced the draft-and-verify framework §1.
  • Builds on: EAGLE-3, arXiv:2503.01840, the strongest autoregressive drafter the paper compares against. DFlash keeps the idea of using target features but injects them as keys and values in every draft layer rather than fusing them into the input §1 §4.1.
  • Builds on: block diffusion LMs, arXiv:2503.09573. DFlash modifies their training by sampling anchors as block starts rather than masking uniformly §4.2.
  • Builds on: Samragh et al., arXiv:2507.11851, which the paper cites for the observation that target hidden states encode information about future tokens §1 §4.1.
  • Related, not compared: PARD, arXiv:2504.18583, small autoregressive models trained to imitate parallel drafting §1. Diffusion-based drafters such as DiffuSpec (arXiv:2510.02358) and SpecDiff-2 (arXiv:2511.00606) are not compared because no open-source implementation was available §1 §5.
  • Compared against: EAGLE-3 (tree sizes 16 and 60) and autoregressive decoding §5.

Source and license

Adapted from “DFlash: Block Diffusion for Flash Speculative Decoding” by Jian Chen, Yesheng Liang, Zhijian Liu (arXiv:2602.06036), used under CC BY 4.0. Changes: condensed and restructured for implementation, with tables, equations and algorithms taken from the paper and its code, each cited to its source. Not affiliated with or endorsed by the authors. Code citations refer to https://github.com/z-lab/dflash at commit 07ebd93db9f4 (MIT). Any quoted code is shown under that license.