Enable CUDA graph capture for CUDA EP to improve decode throughput - #2070
Merged
Conversation
Copilot started reviewing on behalf of
Akshay Sonawane (apsonawane)
April 7, 2026 01:23
View session
Contributor
There was a problem hiding this comment.
Pull request overview
Enables CUDA graph capture for the CUDA Execution Provider to reduce per-token kernel launch overhead during decoding, while adding safeguards for non-decoder sessions and ensuring recurrent-state updates keep stable device pointers needed by captured graphs.
Changes:
- Remove the hard failure blocking
enable_cuda_graph=1for the CUDA provider and treat it as an enabled graph-capture configuration. - Make CUDA EP registration honor
disable_graph_captureby overridingenable_cuda_graphto"0"for non-decoder sessions. - Update
RecurrentState::Update()to avoid pointer swapping under graph capture by copying present→past in-place to preserve stable addresses.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/config.cpp | Allows CUDA graph capture to be enabled via enable_cuda_graph=1 (no longer throws). |
| src/cuda/session_options.cpp | Applies disable_graph_capture by overriding CUDA provider options for non-decoder sessions. |
| src/models/recurrent_state.cpp | Ensures recurrent-state buffers remain pointer-stable under graph capture by copying instead of swapping. |
…ests - Clarify disable_graph_capture comment in cuda/session_options.cpp - Make recurrent_state.cpp comments EP-agnostic (graph capture, not CUDA-specific) - Add GreedySearchGptCudaGraphCapture test for correctness under graph capture - Add ContinuousDecodingGptCudaGraphCapture test for RewindTo with graph capture
…da_graph for vision and embedding
Baiju Meswani (baijumeswani)
previously approved these changes
May 5, 2026
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
kunal-vaishnavi
approved these changes
May 6, 2026
kunal-vaishnavi
enabled auto-merge (squash)
May 6, 2026 14:43
Baiju Meswani (baijumeswani)
approved these changes
May 8, 2026
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.
Enable CUDA graph capture for CUDA EP to improve decode throughput
Summary
Enable CUDA graph capture for the CUDA execution provider, which was previously blocked with a hard exception. This eliminates per-token kernel launch overhead during the decode phase, improving throughput by 20-45% across Qwen3.5 model sizes (0.8B through 9B).
Changes
1.
src/config.cppRemove the exception that blocked
enable_cuda_graph=1for CUDA EP. Instead of throwing, returntrueto enable graph capture — matching the behavior already implemented for DML and NvTensorRtRtx providers.2.
src/cuda/session_options.cppMake CUDA's
AppendExecutionProviderrespect thedisable_graph_captureparameter (previously ignored). Whendisable_graph_capture=true(used for vision and embedding sessions), forceenable_cuda_graphto"0"in the provider options. This ensures CUDA graph is only enabled on the decoder session, preventing crashes from dynamic-shape vision/embedding models.3.
src/models/recurrent_state.cppFix
RecurrentState::Update()for CUDA graph compatibility. The original code usedstd::swapto alternate past/present buffers each decode step, which changes memory addresses and invalidates the captured CUDA graph. When graph capture is enabled, copy present→past in-place instead, preserving the stable pointers that the CUDA graph expects.Performance Results (A100, Qwen3.5 INT4, 256 tokens, greedy)
Testing