Verify Level-2 workspace reservations - #32189
Chi Lo (chilo-ms) wants to merge 29 commits into
Conversation
Move workspace reporting out of GetCapabilityForEP and into the completed GraphPartitioner::Partition boundary. Track workspace estimates as pending during capability probing and commit them only for nodes that ORT actually assigns. Replace the generic safety-margin workspace with the MatMulNBits Level-1 estimate before CUDA's budget decision. Preserve workspace estimates across the layout-transformation deferred-commit path, and report non-workspace, workspace, and total estimated memory once per resource-accounted EP. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cdd38fe6-fcf3-45c2-acea-b8e6206a7839
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cdd38fe6-fcf3-45c2-acea-b8e6206a7839
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cdd38fe6-fcf3-45c2-acea-b8e6206a7839
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cdd38fe6-fcf3-45c2-acea-b8e6206a7839
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cdd38fe6-fcf3-45c2-acea-b8e6206a7839
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cdd38fe6-fcf3-45c2-acea-b8e6206a7839
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cdd38fe6-fcf3-45c2-acea-b8e6206a7839
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cdd38fe6-fcf3-45c2-acea-b8e6206a7839
Separate runtime workspace, persistent prepack buffers, and temporary prepack scratch in Level-1 estimates, and conservatively charge each component during CUDA partitioning. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep nodes missing from a supplied stats file at zero cost so profile-based sessions do not fall through to ad-hoc initializer and workspace bookkeeping. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add estimator-aware NHWC and CUDA budget coverage, make resource arithmetic checked, clarify per-graph Level-2 reporting, and document deferred plugin estimator parity. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1faf9517-5062-4655-a967-3834143334d0
Extract Level-1 runtime workspace into explicitly initialized scalar state so GCC 14 reduced builds do not diagnose nested optional storage as maybe uninitialized. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1faf9517-5062-4655-a967-3834143334d0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1faf9517-5062-4655-a967-3834143334d0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1faf9517-5062-4655-a967-3834143334d0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1faf9517-5062-4655-a967-3834143334d0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1faf9517-5062-4655-a967-3834143334d0
Document that Level-1 prepack estimates include only allocations additional to already-accounted initializers, and distinguish sequential MatMulNBits tactic profiling from PrePack scratch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cdd38fe6-fcf3-45c2-acea-b8e6206a7839
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1faf9517-5062-4655-a967-3834143334d0
Persist accepted per-node workspace reservations through partitioning and compare them with kernel declarations during session finalization. Add an opt-in strict mode for constrained deployments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: cdd38fe6-fcf3-45c2-acea-b8e6206a7839
Resolve workspace-estimation conflicts against current main while preserving Level-2 reservation verification. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 991be248-6618-43aa-8d4b-5305e52bcd40
There was a problem hiding this comment.
🟡 Changes recommended
Fused-node reservations can be omitted or mismatched, and the strict verification paths lack direct tests.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds post-partition verification of Level-2 kernel workspace declarations against accepted reservations, with optional strict validation.
Changes:
- Preserve reservations by graph and node.
- Compare declarations and report discrepancies during session finalization.
- Add strict verification configuration and reservation tests.
File summaries
| File | Description |
|---|---|
include/onnxruntime/core/framework/resource_accountant.h |
Defines reservation maps and retrieval APIs. |
include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h |
Adds the strict verification option. |
onnxruntime/core/framework/graph_partitioner.cc |
Collects committed reservations after partitioning. |
onnxruntime/core/framework/graph_partitioner.h |
Exposes reservation collection from partitioning. |
onnxruntime/core/framework/resource_accountant.cc |
Records reservations by graph and node. |
onnxruntime/core/framework/session_state.cc |
Performs Level-2 comparison, logging, and strict failure. |
onnxruntime/core/framework/session_state.h |
Stores session workspace reservations. |
onnxruntime/core/session/inference_session.cc |
Transfers partition reservations into session state. |
onnxruntime/test/framework/resource_accountant_test.cc |
Tests reservation retention. |
Review details
Suppressed comments (3)
onnxruntime/core/framework/session_state.cc:1874
- Reservations for fused capabilities are keyed to the constituent node indexes, but
AccountForAllNodes()commits those indexes beforeFinalizeFuseSubGraph()removes them. Because this loop visits only surviving nodes, those reservations are never counted as missing declarations, and a declaring fused kernel cannot be compared with them. Remap/aggregate reservations when creating the fused node, or track consumed reservations here and report all unmatched entries after the loop.
for (const auto& node : graph_viewer_->Nodes()) {
onnxruntime/core/framework/session_state.cc:1958
- This error is also returned when a declaration has no matching reservation (line 1921), so the current text incorrectly tells users that an excess was found. Include both failure conditions in the diagnostic.
ORT_RETURN_IF(strict_verification_failed,
"Level-2 workspace verification failed: one or more declarations exceed "
"the workspace reserved during graph partitioning.");
onnxruntime/core/framework/session_state.cc:1915
- This changes the per-node declaration message from VERBOSE to INFO. Models with many workspace-declaring kernels will emit one normal-priority record per node during initialization even though the graph summary already reports the totals; retain VERBOSE here and reserve WARNING for actual excesses.
LOGS(logger_, INFO) << "Level-2 workspace: node '" << node.Name()
- Files reviewed: 9/9 changed files
- Comments generated: 2
- Review effort level: Balanced (auto)
Note
Copilot is running an experiment and ran this review at Balanced.
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Keep missing reservations diagnostic-only so strict mode matches its documented contract, and cover missing, equal, conservative, and exceeded reservations during session finalization. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 991be248-6618-43aa-8d4b-5305e52bcd40
Consolidate constituent workspace reservations onto the surviving fused node, keep per-node declaration details verbose, and cover default overrun behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 991be248-6618-43aa-8d4b-5305e52bcd40
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 991be248-6618-43aa-8d4b-5305e52bcd40
|
Follow-up fixes for the Copilot review are in 7d18338: fused capabilities now consolidate constituent workspace reservations onto the surviving fused node, per-node declaration totals are VERBOSE rather than INFO, and default warning-mode overrun behavior has direct session-level coverage. The focused Release suite passed 35/35 tests before merging the latest unrelated main commits. |
There was a problem hiding this comment.
🟡 Changes recommended
Post-partition node replacements can invalidate index-keyed reservations and bypass strict overrun detection.
Get a fresh assessment by requesting another Copilot review.
Review details
- Files reviewed: 11/11 changed files
- Comments generated: 1
- Review effort level: Balanced (auto)
Note
Copilot is running an experiment and ran this review at Balanced.
|
Full review-team verdict: changes requested. Major findings
Review notesThe new partition-fusion consolidation is sound for the paths it covers: constituent byte fields are added with checked arithmetic, initialization scratch uses peak/max semantics, and graph identity correctly disambiguates subgraph node indices. The default warning behavior and static matched-node tests also look good. Not checked: runtime execution or performance; the review was static against head |
Transfer workspace reservations through selector-action replacements and graph fusions, reject unresolved ownership in strict mode, and document that strict verification is unsupported for ORT-format loads. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 991be248-6618-43aa-8d4b-5305e52bcd40
|
Addressed the latest review in 393dee7. Post-partition selector-action replacements and graph fusions now transfer/aggregate reservation ownership onto the surviving node; strict mode rejects any remaining declaration-plus-orphan mismatch rather than silently bypassing verification. ORT-format loads now explicitly reject |
There was a problem hiding this comment.
🟢 Approval recommended
The reservation lifecycle, strict-mode behavior, graph mutation handling, and targeted regression coverage are coherent with no unresolved correctness issues found.
Review details
- Files reviewed: 16/16 changed files
- Comments generated: 0 new
- Review effort level: Balanced (auto)
Note
Copilot is running an experiment and ran this review at Balanced.
|
Updated full-team review of Major findings
MinorThe public option comment still says “Missing reservations remain diagnostic only,” but the new orphan+missing condition now fails strict initialization. Please update the documented contract to match the implemented behavior. Verified improvements: reservation consolidation uses checked arithmetic and deduplicates source indices; the root/subgraph callback routing and Not checked: runtime performance or the full test matrix; this was a static review of head |
Transfer reservations through shared and GQA-specific fusion paths, preserve existing destination reservations, and make orphaned reservations independently fail strict verification. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 991be248-6618-43aa-8d4b-5305e52bcd40
|
Addressed in
Added production-path tests for both |
Minimal builds load pre-optimized ORT models and do not run graph partitioning, so they cannot produce partition-time workspace reservations. Compile the reservation storage and verification path only in full builds to avoid increasing baseline binary size. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 991be248-6618-43aa-8d4b-5305e52bcd40
|
CI triage and fix:
Validated the fix with a full Release build, all 44 focused workspace/accounting tests, and a no-ops MinSizeRel minimal shared-library build with exceptions disabled. |
|
Updated review of current head 1. Other normal Level-2 replacements still orphan reservationsReservation transfer remains opt-in at individual transformer call sites. Because strict mode now fails on any orphaned reservation, a valid MatMul+Scale optimization can fail session initialization even when no Level-2 workspace declaration exceeds its reservation. The same structural risk remains in other direct Please either instrument all post-partition replacement paths or move reservation tracking into a graph-mutation mechanism where a transformer cannot accidentally omit it. A focused strict-mode test using 2. Intentional deletion has no reservation disposition
This is especially broad because the resource accountant records a reservation selection for every committed accepted node, including zero-byte workspace selections. Strictly failing on every orphan means even removal of a node with no workspace can block initialization. Please add an explicit intentional-removal disposition, such as Verified improvements
Verdict: changes requested. Static review of current head |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 991be248-6618-43aa-8d4b-5305e52bcd40
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 991be248-6618-43aa-8d4b-5305e52bcd40
|
Addressed the latest review and completed a broader final mutation audit in
Added production-path reservation tests for these ownership shapes. The final Windows Release suite passed 123 tests with 4 expected hardware skips; the training-enabled suite passed all 10 focused tests; extended-minimal and ordinary minimal builds also passed. |
Summary
session.strict_workspace_verification=1.Behavior and scope
Verification runs after kernels are created and constant tensors are prepacked, when final Level-2 requirements are available. Strict mode fails session initialization when a declaration exceeds its reservation or when an untracked mutation leaves a nonzero orphaned reservation. Missing partition reservations and zero-byte orphans remain diagnostic-only.
Reservation ownership now follows fused capabilities, selector actions, shared and manual fusions, bottom-up removals, intentional eliminations, and training recomputation clones. This includes MatMulScale and QDQ cleanup, Attention and EmbedLayerNorm cleanup paths, Level-4 initializer fusion, GroupQueryAttention, BitmaskDropout, BiasSoftmaxDropout, SCE loss gradient, Triton, and MemoryOptimizer transformations.
Strict verification is rejected for ORT-format loads because partition-time reservations are not serialized. Reservation storage and verification remain excluded from ordinary minimal builds; extended-minimal ORT-format loads reject strict mode explicitly.
This PR does not repartition the graph or change runtime workspace allocation. #31962 introduced Level-1 workspace estimation and reporting; activation-aware CUDA workspace preallocation remains follow-up work in #32071.
Validation
onnxruntime_test_allbuild: 123 focused tests passed, 4 hardware-dependent tests skipped.lintrunnerandgit diff --checkpassed.