Make workspace input shapes optional-aware - #32312
Merged
Ti-Tai Wang (titaiwangms) merged 7 commits intoSep 4, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces optional-aware, positional workspace shape metadata for Level-2 estimation and updates CUDA MatMulNBits workspace handling.
Changes:
- Adds three-state
WorkspaceInputShaperesolution while preserving optional-input holes. - Handles zero-sized MatMulNBits outputs consistently across estimation and runtime.
- Expands framework/CUDA tests and updates design documentation.
No actionable issues identified.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
include/onnxruntime/core/framework/workspace_input_shape.h |
Defines presence-aware shape metadata. |
include/onnxruntime/core/framework/op_kernel.h |
Updates the Level-2 virtual contract. |
include/onnxruntime/ep/adapter/op_kernel.h |
Mirrors the contract for plugin builds. |
onnxruntime/core/framework/node_shape_resolver.h |
Preserves positional input metadata. |
onnxruntime/core/framework/session_state.cc |
Passes resolved entries to kernels. |
onnxruntime/contrib_ops/cuda/quantization/matmul_nbits.h |
Updates MatMulNBits declarations. |
onnxruntime/contrib_ops/cuda/quantization/matmul_nbits.cc |
Handles partial and empty shapes. |
onnxruntime/contrib_ops/cuda/quantization/matmul_nbits_workspace_estimate.h |
Exposes shared dimension-product logic. |
onnxruntime/contrib_ops/cuda/llm/fpA_intB_gemm/fpA_intB_gemm.h |
Returns zero workspace for empty outputs. |
onnxruntime/test/framework/max_shape_override_test.cc |
Tests all shape states and optional holes. |
onnxruntime/test/framework/session_state_test.cc |
Tests the default declaration behavior. |
onnxruntime/test/providers/cuda/test_cases/matmul_nbits_workspace_test.cc |
Tests formula edge cases. |
onnxruntime/test/providers/cuda/test_cases/matmul_nbits_e2e_workspace_test.cc |
Tests positional and runtime parity. |
docs/annotated_partitioning/future_directions_constrained_env.md |
Documents the revised contract and scope. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Ti-Tai Wang (titaiwangms)
force-pushed
the
titaiwangms/workspace-optional-input-shapes
branch
from
August 28, 2026 22:31
ac8b280 to
8f8ac3f
Compare
Contributor
Author
|
Chi Lo (@chilo-ms) Can you take a look and check if the PR understands #32071 correctly? We will need multi-slots support as Attention is much more complicated. |
Preserve positional optional-input holes and partial shapes for Level-2 workspace declarations. Keep MatMulNBits Level-1, Level-2, and runtime sizing aligned for empty outputs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c04148cc-7ace-4cf4-b981-0ddc92334e78
Document the current first-run tracing strategy, one-slot planner limit, and PackedAttention multi-slot requirement separately from future persistent preallocation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c04148cc-7ace-4cf4-b981-0ddc92334e78
Keep the positional optional-input layout while omitting unsupported bias in compact builds so MatMulNBits workspace parity continues to exercise the CUTLASS GEMM path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c04148cc-7ace-4cf4-b981-0ddc92334e78
Ti-Tai Wang (titaiwangms)
force-pushed
the
titaiwangms/workspace-optional-input-shapes
branch
from
August 31, 2026 19:37
8f8ac3f to
24f662c
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c04148cc-7ace-4cf4-b981-0ddc92334e78
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c04148cc-7ace-4cf4-b981-0ddc92334e78
Require planned offsets to honor declared alignment and distinguish the current PA and PMHA dynamic allocation counts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c04148cc-7ace-4cf4-b981-0ddc92334e78
Copilot started reviewing on behalf of
Ti-Tai Wang (titaiwangms)
September 2, 2026 19:41
View session
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: c04148cc-7ace-4cf4-b981-0ddc92334e78
Chi Lo (chilo-ms)
approved these changes
Sep 4, 2026
Ti-Tai Wang (titaiwangms)
deleted the
titaiwangms/workspace-optional-input-shapes
branch
September 4, 2026 03:07
Ti-Tai Wang (titaiwangms)
added a commit
that referenced
this pull request
Sep 4, 2026
## Summary Add MatMulNBits-equivalent operator-side workspace estimation for CUDA `PackedAttention` and `PackedMultiHeadAttention`: - Level 1 derives a conservative estimate from the node, resolved input shapes, CUDA device properties, and the EP's resolved attention options. - Level 2 declares the same estimate from positional `WorkspaceInputShape` metadata and constructed kernel state. - Existing graph-free runtime recipes remain the single source of truth for workspace bytes and layouts. - PackedAttention declares one 256-byte-aligned root in slot 0, with internal projection and attention regions. - PackedMultiHeadAttention declares one 256-byte-aligned attention root in slot 0. Level 1 is log-only, matching the current MatMulNBits pilot. This PR does not add #32071-specific planner APIs or change runtime `GetScratchBuffer()` behavior. ## Route aggregation Runtime routes are mutually exclusive, so the estimate uses: ```text PackedAttention: align_up(projection_bytes, 256) + max(feasible TRT, MEA, unfused recipes) PackedMultiHeadAttention: max(feasible Flash, TRT, MEA, unfused recipes) ``` Route reachability is evaluated conservatively for every runtime shape up to the supplied maximum geometry. This is necessary because Flash/MEA thresholds and attention-bias alignment gates are not monotonic when moving from a maximum shape to a smaller runtime shape. Unfused fallback is always retained, and a failure to size any included route makes the estimate unavailable rather than silently underestimating. ## Shape and zero semantics - Missing mandatory inputs, shapeless required inputs, unknown dimensions, malformed geometry, and checked-arithmetic overflow produce no estimate. - `WorkspaceInputShape` does not carry max-shape provenance, so zero-shaped framework hints are conservatively treated as unavailable. - Exact zero behavior remains supported by the graph-free runtime recipes. - At the current Level-2 boundary, both unavailable and zero are represented by an empty requirements list. ## Planner integration - Both operators fit #32071's current one-slot pilot. Generic framework multi-slot support remains unchanged. - A declaration alone is not planner opt-in. `SupportsPreallocatedWorkspace()`, slot-0 retrieval, and PA root slicing must land atomically in the planner integration. - Until then, PA retains its two dynamic allocations and PMHA retains its one dynamic allocation. ## Build boundaries The framework adapters and kernel overrides are excluded from: - CUDA minimal builds - `DISABLE_CONTRIB_OPS` builds - CUDA plugin EP builds The graph-free workspace recipes remain available to the shared BERT attention infrastructure where required. ## Validation - 18/18 PA/PMHA workspace estimator tests - includes direct production-kernel Level-2 declaration tests - route-threshold, max-not-sum, aligned-root padding/no-padding, optional-hole, zero, overflow, and malformed geometry coverage - 23/23 existing packed-attention workspace recipe tests - 20/20 existing hand-calculated runtime parity cases - 26/26 PackedAttention/PackedMultiHeadAttention runtime operator tests - CUDA provider-test build - 145 CUDA internal tests executed: 143 passed, 2 unrelated LeanAttention skips - `DISABLE_CONTRIB_OPS` and CUDA-minimal compile-guard probes - C++ formatting and diff checks ## Dependency This is a stacked follow-up to #32312. The base should change to `main` after #32312 merges. Tracking: #29775 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Copilot-Session: c04148cc-7ace-4cf4-b981-0ddc92334e78
This was referenced Sep 12, 2026
Open
Open
Chi Lo (chilo-ms)
pushed a commit
that referenced
this pull request
Sep 17, 2026
Add MatMulNBits-equivalent operator-side workspace estimation for CUDA `PackedAttention` and `PackedMultiHeadAttention`: - Level 1 derives a conservative estimate from the node, resolved input shapes, CUDA device properties, and the EP's resolved attention options. - Level 2 declares the same estimate from positional `WorkspaceInputShape` metadata and constructed kernel state. - Existing graph-free runtime recipes remain the single source of truth for workspace bytes and layouts. - PackedAttention declares one 256-byte-aligned root in slot 0, with internal projection and attention regions. - PackedMultiHeadAttention declares one 256-byte-aligned attention root in slot 0. Level 1 is log-only, matching the current MatMulNBits pilot. This PR does not add #32071-specific planner APIs or change runtime `GetScratchBuffer()` behavior. Runtime routes are mutually exclusive, so the estimate uses: ```text PackedAttention: align_up(projection_bytes, 256) + max(feasible TRT, MEA, unfused recipes) PackedMultiHeadAttention: max(feasible Flash, TRT, MEA, unfused recipes) ``` Route reachability is evaluated conservatively for every runtime shape up to the supplied maximum geometry. This is necessary because Flash/MEA thresholds and attention-bias alignment gates are not monotonic when moving from a maximum shape to a smaller runtime shape. Unfused fallback is always retained, and a failure to size any included route makes the estimate unavailable rather than silently underestimating. - Missing mandatory inputs, shapeless required inputs, unknown dimensions, malformed geometry, and checked-arithmetic overflow produce no estimate. - `WorkspaceInputShape` does not carry max-shape provenance, so zero-shaped framework hints are conservatively treated as unavailable. - Exact zero behavior remains supported by the graph-free runtime recipes. - At the current Level-2 boundary, both unavailable and zero are represented by an empty requirements list. - Both operators fit #32071's current one-slot pilot. Generic framework multi-slot support remains unchanged. - A declaration alone is not planner opt-in. `SupportsPreallocatedWorkspace()`, slot-0 retrieval, and PA root slicing must land atomically in the planner integration. - Until then, PA retains its two dynamic allocations and PMHA retains its one dynamic allocation. The framework adapters and kernel overrides are excluded from: - CUDA minimal builds - `DISABLE_CONTRIB_OPS` builds - CUDA plugin EP builds The graph-free workspace recipes remain available to the shared BERT attention infrastructure where required. - 18/18 PA/PMHA workspace estimator tests - includes direct production-kernel Level-2 declaration tests - route-threshold, max-not-sum, aligned-root padding/no-padding, optional-hole, zero, overflow, and malformed geometry coverage - 23/23 existing packed-attention workspace recipe tests - 20/20 existing hand-calculated runtime parity cases - 26/26 PackedAttention/PackedMultiHeadAttention runtime operator tests - CUDA provider-test build - 145 CUDA internal tests executed: 143 passed, 2 unrelated LeanAttention skips - `DISABLE_CONTRIB_OPS` and CUDA-minimal compile-guard probes - C++ formatting and diff checks This is a stacked follow-up to #32312. The base should change to `main` after Tracking: #29775 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Copilot-Session: c04148cc-7ace-4cf4-b981-0ddc92334e78
This was referenced Sep 18, 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.
Why
DeclareWorkspaceRequirements()currently receives a densespan<const TensorShape>. That loses positional correspondence when an optional input is omitted and prevents Level 2 workspace estimation for valid signatures with an internal hole, for example:biaswith latertoken_offset/cumulative_sequence_lengthseqlens_kwith latertotal_sequence_lengthg_idxwith laterbiasThe resolver also dropped partial shapes wholesale, conflating “input is missing”, “input is present but shape metadata is unavailable”, and “input is present with unknown dimensions”.
What changed
WorkspaceInputShapedescriptor with three explicit states:MissingPresentWithShapePresentWithoutShape-1per unknown dimension), and optional holes.MatMulNBits parity
The shared workspace formula now handles known-empty outputs before architecture-specific arithmetic:
[0, unknown, K]are recognized as empty#32071 integration constraints
#32071 uses Level-2 declarations as synthetic negative allocation IDs in the existing activation
MemoryPattern.The first run for a compatible feed-shape key traces workspace allocation/free while the kernel still uses
GetScratchBuffer(). Later compatible runs can return an offset in the normal per-run pattern backing buffer;an unavailable pattern or a request larger than the declared capacity falls back to
GetScratchBuffer().This is not persistent
Initialize()-time allocation and does not protect the first run from OOM.The current #32071 pilot preplans only kernels that explicitly opt in and declare exactly one slot.
The PA/PMHA follow-up uses that contract for both operators:
The declarations alone do not opt either kernel into planning. The future integration must atomically add
SupportsPreallocatedWorkspace(), retrieve slot 0, and split PA's root at its declared aligned Attention offset.Until then, PA retains its two dynamic allocations and PMHA retains its one dynamic allocation. Generic multi-slot
framework support remains available, but PA does not require a multi-slot planner extension.
Deferred Phase-B semantics
This PR intentionally does not add:
Those semantics belong to the planner/accounting integration, where runtime bound checks and fallback behavior can be defined coherently.
Compatibility with #32071
This PR should merge first. #32071 should then rebase and update its Level-2 caller to pass the same positional
WorkspaceInputShapespan while retaining its reservation verification and execution-plan registration.Validation
Mthen zero-Mruntime coveragegit diff --checkDesign tracking: #29775