[CUDA] Add GatedLatentPool and SparseRowSelect contrib operators - #32124
Open
Tianlei Wu (tianleiwu) wants to merge 4 commits into
Open
[CUDA] Add GatedLatentPool and SparseRowSelect contrib operators#32124Tianlei Wu (tianleiwu) wants to merge 4 commits into
Tianlei Wu (tianleiwu) wants to merge 4 commits into
Conversation
GatedLatentPool gates and pools `ratio` consecutive tokens into one latent KV row -- the compression branch of a sparse-attention stack. SparseRowSelect scores a query against those compressed rows with a lightweight multi-head scorer and keeps the best `topk`, so attention work stays bounded as context grows. The two share the simulated-quantisation helpers in quant_sim_common.cuh, which reproduce the low-precision grids such a checkpoint was trained against.
This was referenced Aug 17, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Adds CUDA contrib operators for sparse-attention compression and row selection.
Changes:
- Implements fused gated pooling, cache updates, scoring, and top-k selection.
- Adds shared FP8/FP4 quantization simulation.
- Registers, documents, and tests both operators.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
onnxruntime/test/python/transformers/test_sparse_row_select.py |
Adds numeric parity tests. |
onnxruntime/test/python/transformers/test_gated_latent_pool.py |
Adds pooling parity tests. |
onnxruntime/core/graph/contrib_ops/ms_opset.h |
Registers schemas. |
onnxruntime/core/graph/contrib_ops/contrib_defs.cc |
Defines schemas and shape inference. |
onnxruntime/contrib_ops/cuda/math/sparse_row_select.h |
Declares the selection kernel. |
onnxruntime/contrib_ops/cuda/math/sparse_row_select.cc |
Validates and dispatches selection. |
onnxruntime/contrib_ops/cuda/math/sparse_row_select_impl.h |
Defines selection parameters. |
onnxruntime/contrib_ops/cuda/math/sparse_row_select_impl.cu |
Implements CUDA scoring and selection. |
onnxruntime/contrib_ops/cuda/math/quant_sim_common.cuh |
Adds shared quantization helpers. |
onnxruntime/contrib_ops/cuda/math/gated_latent_pool.h |
Declares the pooling kernel. |
onnxruntime/contrib_ops/cuda/math/gated_latent_pool.cc |
Validates and dispatches pooling. |
onnxruntime/contrib_ops/cuda/math/gated_latent_pool_impl.h |
Defines pooling parameters. |
onnxruntime/contrib_ops/cuda/math/gated_latent_pool_impl.cu |
Implements fused CUDA pooling. |
onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc |
Registers CUDA kernels. |
docs/OperatorKernels.md |
Lists kernel support. |
docs/ContribOperators.md |
Documents both operators. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Validated: CUDA plugin GatedLatentPool and SparseRowSelect objects compile.
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
Adds two CUDA contrib operators that together form the compression and selection front end of a sparse-attention stack:
GatedLatentPoolpoolsratioconsecutive tokens into one latent cache row, andSparseRowSelectscores those rows against the current query and emits thetopkrow ids attention should gather. DeepSeek-V4 uses this pair (its KV compressor and its Lightning Indexer), but the schemas are written against the general pattern — gated pooling into a strided latent cache, then a lightweight multi-head scorer over that cache.As ONNX primitives each of these is a long chain of gather/softmax/reduce/rotate nodes whose intermediates are far larger than their inputs; fusing them removes both the launches and the materialization.
Summary of Changes
GatedLatentPoolonnxruntime/contrib_ops/cuda/math/gated_latent_pool.{h,cc}OpKernel— attributes, validation, output shapesonnxruntime/contrib_ops/cuda/math/gated_latent_pool_impl.{h,cu}Gated pooling of
ratioconsecutive tokens into one latent row:Design points worth a reviewer's attention:
window_multiplier * ratioprojections that preceded this step, so a row whose window straddles a step boundary can still be pooled without the caller re-feeding history.scoreis optional: when omitted,kvis twice as wide and carries the value in the low half of each row and the gate in the high half, which is what a single fused projection GEMM produces.rowsis sized(seq_len - 1) / ratio + 2— one row per slot the step can touch plus a spare — so the output shape never depends onpast_lens, which keeps the op CUDA-graph-capturable.first_slot/last_slot/row_countsay which of those rows are live.simulate_fp8andsimulate_rotated_fp4apply a simulated FP8-E4M3 / Hadamard-rotated FP4-E2M1 round trip, matching what a quantized attention cache will store.SparseRowSelectonnxruntime/contrib_ops/cuda/math/sparse_row_select.{h,cc}OpKernel— attributes, validation, output shapesonnxruntime/contrib_ops/cuda/math/sparse_row_select_impl.{h,cu}GatedLatentPoolthis step are written atfirst_slot + j; slots below keeppast_cache. Slots abovelast_slotare deliberately left unspecified — no step has ever written them and no query can reach them. On a long-context export they are almost the whole cache, so producing them would dominate the operator.past_lens[b] + smay only see the first(past_lens[b] + s + 1) / ratiorows.selectionis emitted asrow_id_offset + cso it can be concatenated straight into a paged cache's index list, padded with-1when fewer thantopkrows are visible.Shared
onnxruntime/contrib_ops/cuda/math/quant_sim_common.cuhQuantSimConv, block scale, E4M3 rounding, FP4 rotation) used by both operatorsonnxruntime/core/graph/contrib_ops/contrib_defs.cconnxruntime/core/graph/contrib_ops/ms_opset.honnxruntime/contrib_ops/cuda/cuda_contrib_kernels.ccdocs/ContribOperators.md,docs/OperatorKernels.mdTesting
onnxruntime/test/python/transformers/test_gated_latent_pool.pyonnxruntime/test/python/transformers/test_sparse_row_select.pyBoth compare against PyTorch references built from the primitive formulas, across float32/float16/bfloat16, with and without the optional
scoreinput, with and without each quantization-simulation mode, and across window multipliers, ratios, and prefill/decode step shapes.Additive only — no existing operator, schema or kernel is modified.
Checklist