Skip to content

feat(qwen35): support sampled concurrent speculation - #654

Draft
Graffioh wants to merge 11 commits into
Luce-Org:qwen38-dsparkfrom
Graffioh:codex/qwen38-sampled-spec
Draft

feat(qwen35): support sampled concurrent speculation#654
Graffioh wants to merge 11 commits into
Luce-Org:qwen38-dsparkfrom
Graffioh:codex/qwen38-sampled-spec

Conversation

@Graffioh

@Graffioh Graffioh commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Stack

This draft PR is built on top of #651 at f1c85e05. It therefore contains the exact current #642 history, #651's projection batching, and the separate replay-log rename.

#654 adds two commits:

  1. 0445b161feat(sampler): add distribution-preserving spec verification
  2. e0647848feat(qwen35): speculate sampled concurrent lanes

Both commits are patch-equivalent across the final restack.

Summary

  • Keep temperature, top-p, top-k, repetition penalty, frequency penalty, and presence penalty lanes in DFlash2 chain rounds.
  • Share one target forward across greedy speculative lanes, sampled speculative lanes, and autoregressive fallback lanes.
  • Apply distribution-preserving speculative accept/reject sampling.
  • Keep one transactional RNG state per slot and publish it only after prefix promotion succeeds.
  • Roll back at the first rejected draft token.
  • Commit only the accepted KV, target-feature, GDN, and convolution prefix.
  • Batch sampled target-logit transfers by depth, stop transfers after a lane rejects, and reuse sampler buffers.
  • Preserve the sparse ordinary AR path for lanes that cannot use the sampled protocol.

For a proposed token x, verification accepts with min(1, p(x) / q(x)). At the first rejection, it samples from normalized max(p - q, 0). If the chain fully accepts, it samples the bonus token from the target distribution on the final verifier row. Target and residual distributions use the same sampler policy as ordinary generation.

Three-lane reference benchmark

These measurements were taken on the previous stacked head 13590205, before the latest #625 refresh. They remain useful as a reference for the unchanged #654 patches, but they are not presented as final-head measurements. A clean rerun was deferred because another user continuously occupied the shared GPU host; contaminated numbers were excluded.

Setup:

  • Radeon R9700 (gfx1201)
  • Qwen3.8-27B Q4_K_M target
  • Q8_0 DFlash2 draft with W8 and SWA 2048
  • Concurrency 3, context 4,096, and a 12,288-token KV pool
  • 96 output tokens per lane with DFLASH_MIN_TOKENS=96
  • One warmup batch, followed by three measured batches per mode
  • Aggregate throughput is 288 completion tokens divided by batch wall time

Sampled lanes use temperature 0.8, top-p 0.9, top-k 40, frequency penalty 0.4, and presence penalty 0.2. The mixed batch is greedy, sampled, greedy.

Lanes DFlash2 One-token AR control Speedup
Greedy / greedy / greedy 222.33 tok/s 46.93 tok/s 4.74x
Sampled / sampled / sampled 149.69 tok/s 44.33 tok/s 3.38x
Greedy / sampled / greedy 187.46 tok/s 45.43 tok/s 4.13x

Every measured batch produced exactly 288 tokens. The speculative server reported W8, SWA layers: 5/5 (window=2048), and one packed three-lane draft backbone. The AR control used the same binary without a drafter.

Verification

@Graffioh
Graffioh force-pushed the codex/qwen38-sampled-spec branch from 5644008 to 0e7da88 Compare August 24, 2026 08:20
@Graffioh

Copy link
Copy Markdown
Contributor Author

Benchmark results after the commit-stack rewrite, at head 0e7da88.

Setup: Radeon gfx1201 32 GB; Qwen3.8-27B-Q4_K_M target; Q8_0 DFlash2 draft; concurrency 3; draft width 8; max context 4096. Each batch launched three concurrent requests and generated 96 tokens per lane with DFLASH_MIN_TOKENS=96. Results are aggregate completion tokens divided by batch wall time, after one warmup and across three measured batches. Every measured batch produced exactly 288 tokens.

Sampled lanes used temperature 0.8, top_p 0.9, top_k 40, frequency_penalty 0.4, and presence_penalty 0.2.

lanes DFlash2 on #654 one-token AR control speedup
greedy / greedy / greedy 219.92 tok/s 47.14 tok/s 4.67x
sampled / sampled / sampled 151.29 tok/s 44.62 tok/s 3.39x
greedy / sampled / greedy 188.55 tok/s 45.76 tok/s 4.12x

The control used the same #654 binary with no drafter loaded. It measures concurrent one-token AR and is not a source-level A/B against #651. Server logs confirmed packed DFlash2 batches with lanes=3 and q_len=8 for the speculative runs. The final gfx1201 build passed, as did the five focused CTests.

Restore the paged-attention C ABI through a separate tree entry point. Reject unsupported GDN variants, initialize root-only chain trees, and size draft metadata from graph capacity.
Keep GDN journals inside the result buffer, restore the 10-source tensor layout, validate every tree destination before mutation, and allow selector widths that use the CPU top-k fallback.
Add fixed-width DFlash2 concurrent decoding for Qwen3.8 and batch the shared dense draft projections across active lanes.

Keep convolution, cache updates, RoPE, masks, and attention lane-local. Preserve transactional state promotion and fixed-chain validation through C6.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant