Fix CUDA illegal memory access crash in TopK when inputs contain NaN - #2195
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens the CUDA TopK selection-sort kernels against all-NaN logits to prevent out-of-bounds writes that can trigger illegal memory access and corrupt subsequent GPU work, improving runtime resilience for edge-case vision inputs.
Changes:
- Clamp invalid Top-1 / Top-K output indices to
0when no valid max element is found (e.g., all inputs are NaN). - Add bounds guards around in-place
scores_in[...]“blanking” writes to prevent OOB when the selected index remains at its sentinel value. - Apply the same NaN-safety pattern to both the single-block selection-sort path and the distributed selection-sort (Stage 1 + Stage 2) path.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/cuda/cuda_topk_select_sort.cuh | Adds NaN-safe index clamping and guards the in-place blanking write to prevent OOB in Top-1/Top-K kernels. |
| src/cuda/cuda_topk_distributed_select_sort.cuh | Adds NaN-safe clamping/guards in distributed TopK Stage 1 and Stage 2 to avoid OOB writes and downstream invalid indices. |
jiafatom
force-pushed
the
fix/topk-nan-guard
branch
from
June 8, 2026 02:50
58ff4ba to
98d94c4
Compare
When vision models produce NaN logits (e.g., due to corrupt/edge-case images), the TopK kernels crash with illegal memory access because: - TopK_Pair.p is initialized to INT_MAX for tie-breaking - NaN comparisons always return false, so no Insert succeeds - p stays at INT_MAX, causing scores_in[INT_MAX] = OOB write - This corrupts GPU state and kills all subsequent inferences Fix: Guard all scores_in writes with p < vocab_size check, and clamp output indices to 0 when no valid element is found. This ensures: 1. No OOB memory access (prevents crash) 2. No GPU state corruption (subsequent inferences still work) 3. Downstream embedding lookups use token 0 (valid, produces garbage text for that sample but doesn't crash) Repro: Qwen2.5-VL-3B with a 1500x1204 image where ort-extensions bicubic resize produces incorrect pixel values, causing NaN in the vision encoder that propagates to all-NaN logits. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a test that feeds all-NaN input scores to each TopK algorithm and verifies: 1. No CUDA illegal memory access (the original crash scenario) 2. All output indices are valid (within [0, vocab_size)) This guards the defensive bounds checks added in the TopK kernels against accidental removal in the future. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jiafatom
force-pushed
the
fix/topk-nan-guard
branch
from
June 8, 2026 23:54
0443b01 to
8beb105
Compare
kunal-vaishnavi
previously approved these changes
Jun 9, 2026
kunal-vaishnavi
enabled auto-merge (squash)
June 9, 2026 00:09
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
kunal-vaishnavi
approved these changes
Jun 9, 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.
Problem
When vision models produce all-NaN logits (e.g., due to corrupt or edge-case images triggering incorrect pixel values in the image preprocessing pipeline), the CUDA TopK kernels crash with an illegal memory access error that corrupts GPU state and kills all subsequent inferences.
Root Cause
TopK_Pair.pis initialized toINT_MAXfor tie-breaking (smaller index wins ties)NaN > x) always return false, so noInsertsucceedspstays atINT_MAX, causingscores_in[INT_MAX]→ out-of-bounds writeRepro
Fix
Guard all
scores_inwrites withp < vocab_sizecheck, and clamp output indices to 0 when no valid element is found:GetTop1Kernel: Clampindices_outto 0 ifp >= vocab_sizeGetTopKKernel: Clamp output index to 0, guardscores_inwrite with bounds checkGetTopKKernelDistributedSelectSortStage 1: Same pattern for distributed indicesGetTopKKernelDistributedSelectSortStage 2: Guard shared memory writes and output indicesBehavior After Fix
This is an ORT CUDA EP issue, not a genai bug per se. The genai TopK kernel is just the first thing that detects the corruption. The fix would need to be in ORT's attention kernel for large sequence lengths, or genai should cap/resize images that would produce too many patches.
Confirmed! The root cause is vision model fp16 numerical instability, NOT an ort-extensions bug.
Even with perfect, HF-identical pixel values, the vision.onnx model in fp16 produces NaN at output position [1316, 0] (patch 1316 onward). This is a model precision issue — certain image patterns trigger fp16 overflow in the vision transformer's attention/normalization layers.
Testing
Verified locally on A100-SXM4-80GB with the repro image:
CUDA error: an illegal memory access was encountered→ all subsequent GPU ops failFiles Changed
src/cuda/cuda_topk_select_sort.cuh— GetTop1Kernel + GetTopKKernelsrc/cuda/cuda_topk_distributed_select_sort.cuh— Distributed TopK Stage 1 + Stage 2