Replay compact fixed state for hybrid decoding - #2454
Replay compact fixed state for hybrid decoding#2454Tianlei Wu (tianleiwu) wants to merge 7 commits into
Conversation
66006aa to
0c2cfb3
Compare
43b6b78 to
9bc0bbc
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates ONNX Runtime GenAI’s dynamic-batching Engine to support hybrid decoding with both paged KV cache and fixed recurrent state, replacing dense fixed-state checkpoints with compact per-token state-update capture + partial-prefix replay. It extends the decoder-state manifest schema (explicit bindings + fixed state groups + optional state_update metadata) and wires those resources through cache reservation, decoder IO binding, and device-specific replay (CPU/CUDA), with new synthetic fixtures and tests.
Changes:
- Extend decoder
state_groupsto include explicit bindings for paged KV and fixed state, plus optional compactstate_updatecapture/replay contract. - Add fixed-state pool support for dynamic batching, including double-buffered publication and compact prefix replay via
DeviceInterface::ReplayStateUpdates(CPU + CUDA implementations). - Add hybrid decoder IO path (
HybridDecoderIO) to bind fixed state (+ optional packed position_ids) alongside packed paged inputs, plus new synthetic composite fixtures and tests.
Reviewed changes
Copilot reviewed 36 out of 38 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/python/test_onnxruntime_genai_hybrid_engine.py | New Python integration test for deterministic packed paged+fixed Engine behavior. |
| test/python/create/create_synthetic_paged_model.py | Updates synthetic paged config to use legacy templates + explicit paged_kv bindings. |
| test/python/create/create_synthetic_hybrid_model.py | Updates synthetic hybrid fixture to use unified fixed state groups + compact state_update outputs. |
| test/python/create/create_synthetic_composite_model.py | New synthetic composite (paged+fixed) model + config used by integration tests. |
| test/python/builder/test_decoder_state_groups.py | Updates/extends builder tests for bindings and compact state_update metadata. |
| test/models/engine/synthetic-paged/genai_config.json | Updates checked-in synthetic paged config to include explicit paged_kv bindings. |
| test/models/engine/synthetic-hybrid/genai_config.json | Updates checked-in synthetic hybrid config for unified fixed groups + state_update metadata. |
| test/models/engine/synthetic-composite/genai_config.json | New checked-in composite config (paged+fixed + state_update). |
| test/cpp/engine/paged_key_value_cache_tests.cpp | Adjusts tests to reflect fixed groups now being parsed but rejected by paged-only manager/session. |
| test/cpp/engine/model_state_manifest_tests.cpp | Updates manifest tests for new bindings schema and dynamic-engine fixed support. |
| test/cpp/engine/fixed_state_pool_tests.cpp | Extends fixed-state pool tests for compact capture gating and partial-prefix replay (CPU/CUDA). |
| test/cpp/engine/dynamic_batching_config_tests.cpp | Updates config parsing tests for unified fixed kind + explicit bindings. |
| src/smartptrs.h | Adds ReplayStateUpdates ABI (version bump) and replay descriptor types. |
| src/python/py/models/builders/qwen.py | Adds Qwen-specific state_groups emission including compact state_update metadata. |
| src/python/py/models/builders/base.py | Updates base builder state_groups emission to use explicit bindings and paged_kv helper. |
| src/models/model_state_manifest.h | Adds helpers for querying manifest state-group kinds (fixed presence). |
| src/models/model_state_manifest.cpp | Reworks validation to be binding-driven; validates state_update session contract and shapes. |
| src/ep/cuda/model_kernels.cu | Adds CUDA kernel to replay compact state updates on device. |
| src/ep/cuda/kernels.h | Exposes LaunchReplayStateUpdates entrypoint. |
| src/ep/cuda/interface.cpp | Implements DeviceInterface::ReplayStateUpdates using H2D descriptor copy + kernel launch. |
| src/ep/cpu/interface.cpp | Implements DeviceInterface::ReplayStateUpdates for causal-conv and GDN replay on CPU. |
| src/engine/paged_key_value_cache.cpp | Resolves paged KV names from manifest bindings (with legacy fallback). |
| src/engine/fixed_state_pool.h | Extends pool API/bindings for state_update capture metadata and prefix-commit support. |
| src/engine/fixed_state_pool.cpp | Implements compact capture tensors, prefix commit bookkeeping, and replay via DeviceInterface. |
| src/engine/execution_context.h | Threads fixed-state reservation/bindings/staging bytes through execution context. |
| src/engine/engine.cpp | Ensures cache reservation PrepareCommit runs before crossing the transaction boundary. |
| src/engine/decoders/varlen_decoder_io.h | Adds packed position_ids preparation hook for varlen execution. |
| src/engine/decoders/varlen_decoder_io.cpp | Implements packed (rank-1) position_ids input construction for varlen batches. |
| src/engine/decoders/simple_decoder.h | Tracks whether the model has fixed state groups to select IO path. |
| src/engine/decoders/simple_decoder.cpp | Routes dynamic batching to HybridDecoderIO when fixed groups exist; adjusts CUDA-graph eligibility. |
| src/engine/decoders/hybrid_decoder_io.h | New DecoderIO wrapper combining varlen IO + fixed-state bindings. |
| src/engine/decoders/hybrid_decoder_io.cpp | Binds fixed state tensors (and optional state_update tensors) into the ORT run. |
| src/engine/cache_manager.h | Extends step reservation interface to carry fixed-state handles/bindings + prepare/validate stages. |
| src/engine/cache_manager.cpp | Adds composite reservation (paged + fixed), fixed-state pool ownership, and joint commit/release flow. |
| src/config.h | Extends decoder state-group schema: unified fixed kind, explicit bindings, and state_update metadata. |
| src/config.cpp | Parses new state_groups schema including bindings and state_update blocks (with validation). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
## Summary - export packed Qwen3.5/3.8 linear-attention layers with `VarlenCausalConvWithState` and `GatedDeltaNet` - replace dense recurrent checkpoints with compact convolution values and GDN transition capsules - export raw `A_log`/`dt_bias` for native Qwen gate arithmetic, without `arithmetic_mode` - keep committed paged recurrent state unwindowed, FP32, and V-major while preserving the dense `LinearAttention` default The existing `state_groups` schema is unchanged in this PR. Parsing compact update metadata and replaying these transitions is handled by the stacked runtime PR #2454. ## Dependencies - microsoft/onnxruntime#32282 - microsoft/onnxruntime#32290 - microsoft/onnxruntime#32307 ## Testing - `python3 -m pytest test/python/builder/test_decoder_state_groups.py test/python/builder/test_qwen_vl.py -q` (50 passed) - `python3 -m pytest test/python/builder -q` (493 passed, 3 skipped)
c8e0d4a to
0830990
Compare
2b8021f to
f9465b9
Compare
Replace dense recurrent checkpoints with packed convolution values and GDN capsules that replay accepted prefixes into fixed-state banks. Integrate fixed state with paged dynamic batching through explicit manifest bindings and a validated two-phase cache commit.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
6b2dd5a to
4631a59
Compare
- Drop HybridDecoderIO's stored ExecutionContext reference; the IO is moved into ScheduledRequests and can outlive the context Engine::Step holds on its stack. - Validate the declared element type of packed position_ids, not just its rank. - Make FixedStatePool::PlannedStagingBytes account for the compact capture buffers Reserve() allocates, so the planner stays exact once MTP requests captures. - Report state_update.enabled = false distinctly from missing state_update outputs. - Bound the CUDA replay descriptor count by the gridDim.y limit instead of INT_MAX. - Classify Qwen state-group layers the same way the base builder does, so sliding_attention and conv layers are no longer silently dropped.
4631a59 to
1fd351c
Compare
Summary
Replace dense recurrent checkpoint tensors with compact state-update replay for dynamically batched hybrid models. The engine now owns fixed convolution and GatedDeltaNet state beside paged KV cache, captures packed per-token updates, and replays only an accepted prefix into inactive state banks before atomically publishing both cache types.
Stack
valueandcapsuleoutputs.Key Changes
paged_kvandfixeddecoder state groups, including compact convolutionvalueand GDNcapsuleupdate bindings.HybridDecoderIO, including optional packedposition_ids.state_groups.Memory Impact
The runtime no longer requires dense per-token recurrent checkpoint outputs. Speculative rollback data is bounded by
state_update_capacityand represented as compact convolution values or packed GDN transition capsules.Testing
test/python/builder/test_decoder_state_groups.py: 24 passedengine_unit_tests: 256 passedengine_unit_testson H200: 261 passedChecklist