Run a DFlash2 block drafter in the batch engine - #2496
Open
Tianlei Wu (tianleiwu) wants to merge 5 commits into
Open
Run a DFlash2 block drafter in the batch engine#2496Tianlei Wu (tianleiwu) wants to merge 5 commits into
Tianlei Wu (tianleiwu) wants to merge 5 commits into
Conversation
This was referenced Aug 28, 2026
Tianlei Wu (tianleiwu)
force-pushed
the
tlwu/20260828/runtime-dflash2
branch
from
August 29, 2026 00:02
7ed7354 to
65e263d
Compare
Tianlei Wu (tianleiwu)
force-pushed
the
tlwu/20260828/runtime-dflash2
branch
from
August 29, 2026 09:21
65e263d to
87fc812
Compare
Tianlei Wu (tianleiwu)
force-pushed
the
tlwu/20260828/runtime-dflash2
branch
from
August 29, 2026 17:03
87fc812 to
9605bea
Compare
Tianlei Wu (tianleiwu)
marked this pull request as ready for review
August 29, 2026 17:05
Contributor
There was a problem hiding this comment.
Pull request overview
This PR integrates a DFlash2 block drafter into the paged dynamic-batching Engine, including plumbing to surface a packed aux_hidden_states decoder output and a new Dflash2Drafter runtime that maintains its own windowed paged KV ring and proposes draft token blocks post-commit.
Changes:
- Add an optional packed
aux_hidden_statesoutput to the decoder IO chain (and forward it throughScheduledRequests) for downstream speculative drafters. - Introduce the
Dflash2Model/Dflash2Drafterruntime and wire it intoEngine::StepDynamic()(feed capture pre-commit, publish post-commit, per-request cache release on teardown). - Extend config parsing for
model.dflash2and add focused C++ unit coverage for config projection, geometry validation, and cache sizing.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/cpp/dflash2_config_test.cpp | Adds unit tests for DFlash2 config validation/projection and cache sizing helpers. |
| src/engine/scheduled_requests.h | Exposes AuxHiddenStates() accessor for scheduled request batches. |
| src/engine/scheduled_requests.cpp | Implements ScheduledRequests::AuxHiddenStates() forwarding to decoder state. |
| src/engine/engine.h | Adds DFlash2 drafter ownership + step hooks for feed capture and draft publication. |
| src/engine/engine.cpp | Creates/owns the drafter, captures feeds pre-commit, publishes drafts post-commit, releases per-request cache blocks. |
| src/engine/decoders/decoder.h | Extends DecoderIO interface with AuxHiddenStates(). |
| src/engine/decoders/hybrid_decoder_io.h | Forwards AuxHiddenStates() from varlen IO through hybrid IO. |
| src/engine/decoders/varlen_decoder_io.h | Stores optional aux_hidden_states_ output tensor and exposes it via AuxHiddenStates(). |
| src/engine/decoders/varlen_decoder_io.cpp | Binds optional aux_hidden_states output; rejects CUDA graph capture when present. |
| src/dflash2_drafter.h | Defines Dflash2Model, CreateDflash2Config, and the Dflash2Drafter runtime API. |
| src/dflash2_drafter.cpp | Implements config projection, drafter cache sizing/allocation, packed layout construction, and greedy lattice walk. |
| src/config.h | Adds decoder aux_hidden_states output name and introduces the model.dflash2 config section. |
| src/config.cpp | Parses decoder aux_hidden_states output and the new model.dflash2 JSON section (including tensor-name overrides). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Tianlei Wu (tianleiwu)
force-pushed
the
tlwu/20260828/runtime-dflash2
branch
from
August 29, 2026 22:44
9605bea to
56b8e4a
Compare
A drafter that reads the target's intermediate residual streams needs those rows out of the same step that produced them, in the same packed order as the logits rows. Bind the optional `aux_hidden_states` decoder output in `VarlenDecoderIO` when the model declares one, and expose it through `DecoderIO::AuxHiddenStates()` up to `ScheduledRequests`. `HybridDecoderIO` forwards to the varlen IO it wraps: a model with fixed state groups is served through the hybrid IO, so leaving the accessor unforwarded there returns null on exactly the models that need it. CUDA graph capture is rejected rather than silently producing stale rows, since the tensor is allocated per step from the step's token count.
Adds `model.dflash2` to the config and a `Dflash2Drafter` that the Engine owns alongside the existing MTP drafter. Each committed step feeds the drafter the step's auxiliary hidden states and it returns a whole block of drafts per request, which the Engine attaches through `Request::SetDraftTokens` for the next step to verify. Notable constraints encoded here: - The drafter is constructed *before* the main cache manager so that the paged pool's free-memory measurement already excludes it. Its own pool is a sliding-window ring sized from `max_batch_size`, not from the context length; ingesting unwindowed context instead costs ~10.6 GB at this geometry. - Feeds are captured *before* `Request::CommitStep`, which clears the accepted-draft counts the row trimming depends on, and published after. `first_position` comes from `ProcessedSequenceLength()`; deriving it from `sequence_length_before` is wrong for a prefill chunk. - Rows belonging to rejected drafts are dropped before ingest, otherwise the drafter conditions on tokens that were never committed. `Dflash2Model` throws from `CreateState`: it is a session container for the Engine, never a standalone generator.
Tianlei Wu (tianleiwu)
force-pushed
the
tlwu/20260828/runtime-dflash2
branch
from
August 30, 2026 06:41
36b5fe6 to
8db7e53
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds the DFlash2 block-drafter runtime to the paged batch engine on top of #2495. The target decoder exposes packed auxiliary hidden states, and the drafter ingests committed rows into its own bounded sliding-window KV cache before proposing a coherent token path through the exported candidate lattice.
This replaces #2460 while excluding builder changes already covered by #2487/#2489, diagnostics churn, unsafe mixed-checkpoint experiments, and ONNX Runtime dependency changes.
Summary of Changes
Packed target output
aux_hidden_statesdecoder output sized to the active token rows.DFlash2 drafter
model.dflash2session, geometry, tensor-name, and sliding-window configuration.Engine integration
Testing
build/Linux/Debug/unit_tests(238 passed, 22 skipped)build/Linux/Debug/engine_unit_tests(295/295 passed)cmake --build build/Linux/Debug(passed)Performance validation
Measured on one NVIDIA H200 with the CUDA Release build from stack head
dabb4103, ORT CUDA 1.30.0, compact-final native-GDN artifacts,K=7, 1,024 generated tokens, CUDA graphs off, 2 warmups, and 3 measured runs:DFlash2's geometric-mean decode speedup was 1.159x (+15.89%). Its evaluated-draft acceptance was 75.13%, 74.60%, and 72.86% respectively. All measured runs produced deterministic output hashes and speculative counters, with no dense-checkpoint compatibility warnings.
Dependencies
Checklist