Repository navigation
[CUDA] Make GatherND capture-safe - #32120
Merged
Tianlei Wu (tianleiwu) merged 2 commits intoSep 16, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Makes CUDA GatherND safe for graph capture and replay by eliminating stale host-memory references.
Changes:
- Replaces host-vector staging with a by-value
TArray. - Removes the scratch allocation and asynchronous H2D copy.
- Updates launcher and kernel signatures accordingly.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
onnxruntime/core/providers/cuda/tensor/gather_nd.cc |
Builds and passes slice strides by value. |
onnxruntime/core/providers/cuda/tensor/gather_nd_impl.cu |
Accepts by-value strides in CUDA code. |
onnxruntime/core/providers/cuda/tensor/gather_nd_impl.h |
Updates the launcher declaration. |
π‘ Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
PrepareCompute staged the per-dimension slice strides through device memory with a cudaMemcpyAsync whose source was a std::vector local to the call. The copy outlives the vector, which is harmless for a normal launch but not under CUDA graph capture: the recorded memcpy node keeps the host address and reads it again on every replay, long after the vector is gone. The slice offsets then come out as garbage and the gather reads far outside its input. Pass the strides by value in a TArray instead, the way input_dims already is. The array is at most rank elements, which TArray::capacity already covers for input_dims, and the copy disappears along with the scratch buffer.
Tianlei Wu (tianleiwu)
force-pushed
the
tlwu/20260816/gather_nd_capture_safe
branch
from
September 15, 2026 00:56
b42fa22 to
a459f0b
Compare
Tianlei Wu (tianleiwu)
requested review from
Akshay Sonawane (apsonawane),
kunal-vaishnavi and
Ti-Tai Wang (titaiwangms)
September 15, 2026 23:46
Ti-Tai Wang (titaiwangms)
approved these changes
Sep 15, 2026
Tianlei Wu (tianleiwu)
deleted the
tlwu/20260816/gather_nd_capture_safe
branch
September 16, 2026 04:05
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
GatherND'sPrepareComputestaged the per-dimension slice strides through device memory with acudaMemcpyAsyncwhose source was astd::vectorlocal to the call. The copy outlives the vector. That is harmless for a normal launch, but not under CUDA graph capture: the recorded memcpy node keeps the host address and re-reads it on every replay, long after the vector is gone.The slice offsets then come out as garbage and the gather reads far outside its input.
Summary of Changes
onnxruntime/core/providers/cuda/tensor/gather_nd.ccTArrayinstead of astd::vector+ device staging buffer; drop the scratch allocation and the async copy.onnxruntime/core/providers/cuda/tensor/gather_nd_impl.cuonnxruntime/core/providers/cuda/tensor/gather_nd_impl.hThe array holds at most
rankelements, whichTArray::capacityalready covers forinput_dimson the same code path, so no new capacity assumption is introduced.Testing
GatherNDCPU/CUDA parity tests pass.Motivation and Context
This is a correctness fix for CUDA graph capture, not a performance change, though it does remove one allocation and one H2D copy per
Run. It is one of a small set of EP-level issues that must be fixed before a graph-captured decode loop is safe; the companion issue inCudaAsyncBufferis addressed separately.Checklist