Repository navigation
fix(attention): avoid overflow in triton kv cache offsets - #854
Merged
jason-fxz merged 2 commits intoNov 4, 2026
Merged
Conversation
Collaborator
|
Thanks for the fix. The uint32 tier is not needed. Please just use int32 when the max offset is below def _kv_offset_dtype(k_cache: torch.Tensor, v_cache: torch.Tensor):
- # Bound physical offsets, not request lengths. Nonnegative offsets can use
- # all 32 bits before falling back to int64, even when slot IDs fit in int32.
+ # Bound physical offsets, not request lengths.
max_offset = max(
sum((size - 1) * stride for size, stride in zip(cache.shape, cache.stride()))
for cache in (k_cache, v_cache)
)
- if max_offset < 1 << 31:
- return tl.int32
- return tl.uint32 if max_offset < 1 << 32 else tl.int64
+ return tl.int32 if max_offset < 1 << 31 else tl.int64Please also update the description to match. |
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.
Background
Triton attention can overflow int32
slot * stridebefore pointer addition, producing wrong reads or illegal accesses at element offsets >=2**31(4 GiB into an FP16/BF16 K or V buffer). This depends on the physical cache address, not context length.On H100 80GB,
Qwen/Qwen3.5-0.8Bwith its default pool (5.70 GiB per K/V buffer) crashes on three short requests when Graph padding reads the pool-tail dummy slot. The fix completes the same requests with the same pool, matching the bounded-pool reference's tokens and recorded top-5 IDs/logits.Fix
2**31, int64 otherwise. Small pools retain int32 arithmetic.Validation
Against main
9cacd0896c9b, all five GPUs below show 8 numerical failures before -> 8 passes after, plus 32 layout checks each. The int32/int64 implementation passes the related suites: 76 passed/4 optional-dependency skips on each AMD GPU; 78 passed/2 skips on each NVIDIA GPU.Kernel latency change versus main, positive = slower. BF16, Q=128 (decode Q=1), KV=8192; pools select int64, while low-slot accesses keep main correct. Eight interleaved Graph timing rounds after warmup:
At Q=1, H100 paged attention is +13.61%. Small-pool deltas range from -1.25% to +1.94%; small differences may be noise.
H100 end-to-end, same Qwen checkpoint and 5,976,310-slot pool, identical output tokens. Output tokens/s; main Graph crashes, so only the fixed Graph throughput is reported:
Eager throughput is 2.16% and 1.85% lower on these workloads. AMD end-to-end impact remains unmeasured; these are focused checks, not full CI certification.
Minimal reproduction and environment
Copy this PR's test file into the baseline checkout for the before run; use the PR checkout for the after run. Each needs an installed FreeToken environment and approximately 9 GiB of available GPU memory.
Expected: eight numerical failures on main, eight passes with the fix.
Tested with Torch 2.14.0 / Triton 3.8.0; CUDA 13.0 on NVIDIA; ROCm 10.1.0 Torch build / HIP 7.16.26385 on AMD.
Model A/B used greedy sampling with
ignore_eos=True, cache flush per repetition, one excluded warmup, synchronized timing, and four repetitions in each of two processes per configuration.