Skip to content

[WebGPU] Implement SparseAttentionIndexer operator - #32528

Merged
kunal-vaishnavi merged 68 commits into
mainfrom
copilot/implement-sparse-attention-indexer-again
Oct 3, 2026
Merged

kunal-vaishnavi merged 68 commits into
mainfrom
copilot/implement-sparse-attention-indexer-again

Conversation

Copilot AI commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Description

Adds WebGPU support for com.microsoft.SparseAttentionIndexer, covering Qwen4-Exp QSA and DeepSeek V4 CSA policies using the existing provider-neutral schema.

  • GPU execution
    • Implements WGSL programs for state updates, QSA grouping/scoring, CSA overlap compression, rotary embedding, and deterministic TopK selection.
    • Keeps persistent state and selected indices device-resident without host readback.
    • Uses FP32 accumulation for pooling, softmax, RMSNorm, and scoring.
  • Supported configurations
    • Supports policy_mode="qsa" and "csa".
    • Registers FP32 and FP16 batched execution.
    • Preserves explicit QSA key and CSA compressed-window state.
  • Integration
    • Registers the kernel with the WebGPU execution provider.
    • Adds reference-based QSA and CSA coverage, including empty compressed state.
    • Documents the supported subset and optimization follow-ups.

Motivation and Context

Sparse attention models need policy-specific candidate selection before downstream attention execution. This change enables QSA and CSA index generation on WebGPU while preserving the shared operator ABI, deterministic selection semantics, and graph-visible state.

Copilot AI and others added 4 commits September 10, 2026 02:32
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
…on-indexer' into copilot/implement-sparse-attention-indexer-again

Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
@kunal-vaishnavi
kunal-vaishnavi changed the base branch from main to copilot/implement-sparse-attention-indexer September 10, 2026 07:19
@kunal-vaishnavi
kunal-vaishnavi marked this pull request as ready for review September 10, 2026 07:19
…on-indexer' into copilot/implement-sparse-attention-indexer-again

# Conflicts:
#	onnxruntime/test/contrib_ops/sparse_attention_indexer_op_test.cc

Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟑 Changes recommended

WebGPU mishandles explicit zero scales and 64-bit positions, an opt-out test is ineffective, and the PR bundles major undocumented features.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Implements WebGPU SparseAttentionIndexer, while also bundling substantial CUDA, filesystem, and device-discovery changes.

Changes:

  • Adds WebGPU QSA/CSA kernels, registration, tests, and documentation.
  • Adds packed INT4 PagedAttention/XQA support.
  • Adds CUDA device mapping and cross-platform random-access files.
File summaries
File Description
onnxruntime/test/python/transformers/test_paged_attention.py Extends XQA scale and dispatch tests.
onnxruntime/test/providers/cuda/plugin/cuda_plugin_arena_test.cc Tests runtime CUDA device discovery.
onnxruntime/test/providers/cuda/plugin/cuda_device_mapping_test.cc Tests CUDA identity mapping.
onnxruntime/test/platform/env_test.cc Tests random-access files.
onnxruntime/test/contrib_ops/sparse_attention_indexer_op_test.cc Adds WebGPU QSA/CSA coverage.
onnxruntime/core/providers/cuda/plugin/cuda_ep_factory.h Stores runtime-discovered devices.
onnxruntime/core/providers/cuda/plugin/cuda_ep_factory.cc Maps and creates CUDA devices.
onnxruntime/core/providers/cuda/plugin/cuda_device_mapping.h Adds device-mapping helpers.
onnxruntime/core/platform/windows/env.h Declares Windows random-access support.
onnxruntime/core/platform/windows/env.cc Implements Windows positional reads.
onnxruntime/core/platform/posix/env.cc Implements POSIX positional reads.
onnxruntime/core/platform/env.h Defines the random-access file API.
onnxruntime/core/graph/contrib_ops/bert_defs.cc Extends PagedAttention for packed INT4.
onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc Registers SparseAttentionIndexer.
onnxruntime/contrib_ops/webgpu/bert/sparse_attention_indexer.h Declares WebGPU programs and kernel.
onnxruntime/contrib_ops/webgpu/bert/sparse_attention_indexer.cc Implements QSA/CSA WGSL execution.
onnxruntime/contrib_ops/cuda/cuda_contrib_kernels.cc Registers INT4 PagedAttention kernels.
onnxruntime/contrib_ops/cuda/bert/xqa/xqa_paged_spec_dec_fp16_int4_256.cu Instantiates speculative INT4 XQA.
onnxruntime/contrib_ops/cuda/bert/xqa/xqa_paged_loader.h Documents INT4 XQA contracts.
onnxruntime/contrib_ops/cuda/bert/xqa/xqa_paged_loader.cu Dispatches INT4 XQA kernels.
onnxruntime/contrib_ops/cuda/bert/xqa/xqa_paged_fp16_int4_256.cu Instantiates decode INT4 XQA.
onnxruntime/contrib_ops/cuda/bert/xqa/xqa_loader.h Adds the INT4 quantization type.
onnxruntime/contrib_ops/cuda/bert/xqa/mhaUtils.cuh Unpacks INT4 cache grains.
onnxruntime/contrib_ops/cuda/bert/xqa/mha.h Defines packed cache heads.
onnxruntime/contrib_ops/cuda/bert/xqa/mha_impl.cuh Integrates INT4 scaling and synchronization.
onnxruntime/contrib_ops/cuda/bert/xqa/int4_cache.cuh Adds INT4 dequantization.
onnxruntime/contrib_ops/cuda/bert/paged_attention.h Adds per-channel XQA control.
onnxruntime/contrib_ops/cuda/bert/paged_attention.cc Routes INT4 and per-channel execution.
onnxruntime/contrib_ops/cuda/bert/paged_attention_impl.cu Implements INT4 cache reads and writes.
onnxruntime/contrib_ops/cuda/bert/attention_data.h Adds scale-normalizer scratch state.
onnxruntime/contrib_ops/cpu/bert/paged_attention_helper.h Validates packed INT4 caches.
docs/OperatorKernels.md Regenerates kernel type documentation.
docs/ContribOperators.md Documents packed cache shapes and types.
docs/contrib_ops/webgpu/sparse_attention_indexer.md Documents WebGPU support.
docs/contrib_ops/cuda/sparse_attention_indexer.md References the WebGPU implementation.
docs/contrib_ops/cuda/paged_attention.md Documents INT4 PagedAttention.
docs/contrib_ops/cuda/gqa.md Updates the INT4 build default.
cmake/CMakeLists.txt Enables INT4 KV cache by default.
.github/workflows/android.yml Raises the Android size threshold.
Review details

Suppressed comments (1)

onnxruntime/contrib_ops/webgpu/bert/sparse_attention_indexer.cc:467

  • This second read also truncates position_ids to its low 32 bits. The existing CsaInt64MaxPosition contract expects INT64_MAX to make every compressed entry eligible, but it becomes -1 here and yields threshold zero, so WebGPU selects nothing. Compute the ceil-division threshold from the two-word int64 storage (also avoiding position + 1 overflow).
      << "  let position = " << position_ids.GetByOffset("row") << ";\n"
      << "  let threshold = select(0u, u32(position + 1) / uniforms.compress_ratio, position >= 0);\n"
  • Files reviewed: 40/40 changed files
  • Comments generated: 4
  • Review effort level: Balanced

πŸ’‘ Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cmake/CMakeLists.txt Resolved
Copilot AI and others added 4 commits September 10, 2026 00:42
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
…_infer.py

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…rse-attention-indexer-again

Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
Copilot AI and others added 2 commits October 2, 2026 21:11
…rse-attention-indexer-again

Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
…rse-attention-indexer-again

# Conflicts:
#	onnxruntime/contrib_ops/webgpu/webgpu_contrib_kernels.cc

Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
@kunal-vaishnavi
kunal-vaishnavi merged commit befed9a into main Oct 3, 2026
@kunal-vaishnavi
kunal-vaishnavi deleted the copilot/implement-sparse-attention-indexer-again branch October 3, 2026 18:58
kunal-vaishnavi added a commit that referenced this pull request Oct 5, 2026
…ching (#32618)

### Description

Adds `com.microsoft.PackedSparseAttentionIndexer` version 1 for packed,
variable-length continuous batching, with CUDA and WebGPU
implementations.

The operator supports both QSA and CSA policies over flattened token
inputs and per-request metadata while preserving fixed-capacity state
across prefill and decode calls. It is designed to produce selection
metadata compatible with `SparsePagedAttention` without changing the
existing dense `SparseAttentionIndexer` ABI or behavior.

Key changes:
- Add the shared operator schema, fixed generic QSA/CSA state slots,
strict policy-specific validation, and fixed output shape inference.
- Add CUDA and WebGPU kernels and provider registrations for FP32, FP16,
and BF16 where supported.
- Add device-side packed metadata validation without host
synchronization in normal provider paths.
- Add deterministic TopK selection and complete per-request overflow
handling that preserves prior state and returns empty selections.
- Support safe state aliasing where provider semantics permit it while
avoiding unsafe CSA buffer aliasing.
- Share policy constants and math helpers with the existing sparse
attention indexer where practical.
- Add symbolic shape inference support and focused Python coverage.
- Add C++ shape, QSA/CSA numerical, prefill/decode, zero-token request,
malformed metadata, deterministic ordering, and overflow tests.
- Add operator and WebGPU implementation documentation and regenerate
contrib operator/kernel documentation.

Validation performed:
- `onnxruntime_provider_test` CPU build completed successfully.
- All 12 `PackedSparseAttentionIndexerShapeInferenceTest` tests passed.
- Symbolic shape-inference tests passed.
- Repository linting, formatting checks, and secret scanning passed.
- CUDA/WebGPU numerical tests are included but could not be executed
locally because those providers and compatible hardware/toolchains are
unavailable in the environment.

### Motivation and Context

The existing `SparseAttentionIndexer` contract uses dense `[B, S, ...]`
inputs, dense masking, and growing contiguous state.
OgaEngine-compatible paged-attention models instead use flattened packed
tokens, `cumulative_sequence_lengths`, per-request past lengths, dynamic
request scheduling, and fixed-address state.

This separate operator bridges that contract mismatch for sparse paged
attention while keeping the existing dense operator stable. QSA
selections reference request-local positions in the main paged cache;
CSA selections reference fixed-capacity auxiliary compressed state
suitable for `SparsePagedAttention` local-plus-selected execution.

Built on the sparse attention indexer work from #32528.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Kunal Vaishnavi <kvaishnavi@microsoft.com>
Sayan Shaw (sayanshaw24) added a commit that referenced this pull request Oct 6, 2026
## Summary

Follow-up to #32528 (the initial WebGPU `SparseAttentionIndexer`
implementation). This PR reduces the QSA recomputation called out in its
follow-up list. The sparse-indexer prerequisite #32656 has merged into
`main`; this PR now targets `main` directly. The optimization changes
only the WebGPU QSA selection path.

- Cache visible token positions and block scores per query in bounded
workgroup memory. Reuse query/key RMS normalization within each block
score.
- Reuse cached positions on visibility overflow, scanning only the
uncached tail; retain exact visibility and score recomputation fallbacks
outside the cache bounds, preserving score-descending/index-ascending
TopK semantics and non-prefix masks.
- Bound both caches plus the count to 15,364 bytes, below WebGPU's
guaranteed 16 KiB workgroup-storage limit.
- Add FP32/FP16 non-prefix-mask parity tests and document the
optimized/fallback paths.

## Validation

- The original Qwen integration run passed 18 focused
`SparseAttentionIndexerShapeInferenceTest` cases. On current `main`, a
Linux Release WebGPU provider/provider-test build and all 23 focused
QSA/CSA and packed-indexer cases passed on NVIDIA H200/Vulkan, including
both bounded-cache fallback thresholds. Focused formatting and `git diff
--check` passed.
- End-to-end NVIDIA H200 Vulkan testing used a non-paged, no-MTP Qwen3.8
raw INT4 RTN/INT8-last-matmul Generator export, with 16-token prefill
chunks:

| Context | Before | After |
| --- | --- | --- |
| 16-token prefill | 43.27 s | 1.51 s |
| Next decode step after 16 tokens | 42.63 s | 0.70 s |
| 1K prefill | Did not complete within 181 s of prefill | 68.33 s (14.99
tok/s) |
| 1K decode | No valid rate | 1.29 tok/s over eight tokens |
| 2K prefill | No prior completed result | 145.37 s (14.09 tok/s) |
| 2K decode | About 30.8 s/step at the old cache boundary | 1.03 tok/s
over eight tokens |

The eight generated pieces from the four-token smoke prompt were
unchanged, as was the first token ID from the 16-token probe. Model-load
time (~58–60 s) is excluded from prefill measurements. The H200 static
WebGPU build now executes the WebGPU-specific parity tests; all 23
focused QSA/CSA and packed-indexer cases passed on current `main`.

The EngramGate and GenAI builder/runtime fixes in the working tree are
not part of this PR.

The performance table above was measured on the earlier Qwen3.8
integration branch; GPU regression tests, not full-model timing, were
rerun on current `main`.

## Current main update (October 6)

Kunal's #32656 merged, and this PR is now based on `main` with a
three-file QSA-only review diff. Merged current `main` again after that
restack. The WebGPU provider-test build and all 23 focused H200 QSA/CSA
plus packed-indexer tests passed. The October 6 Windows WebGPU job
exposed a long-running visibility-overflow boundary test that lost the
D3D12 device. Commit 9499988 avoids redundant prefix rescans; all 22
focused WebGPU QSA/CSA tests pass on H200/Vulkan, with that boundary
test taking 241 ms. Android minimal-size CI passed on the preceding
head; CI for the fix is pending.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eserscor pushed a commit that referenced this pull request Oct 7, 2026
## Summary

Follow-up to #32528 (the initial WebGPU `SparseAttentionIndexer`
implementation). This PR reduces the QSA recomputation called out in its
follow-up list. The sparse-indexer prerequisite #32656 has merged into
`main`; this PR now targets `main` directly. The optimization changes
only the WebGPU QSA selection path.

- Cache visible token positions and block scores per query in bounded
workgroup memory. Reuse query/key RMS normalization within each block
score.
- Reuse cached positions on visibility overflow, scanning only the
uncached tail; retain exact visibility and score recomputation fallbacks
outside the cache bounds, preserving score-descending/index-ascending
TopK semantics and non-prefix masks.
- Bound both caches plus the count to 15,364 bytes, below WebGPU's
guaranteed 16 KiB workgroup-storage limit.
- Add FP32/FP16 non-prefix-mask parity tests and document the
optimized/fallback paths.

## Validation

- The original Qwen integration run passed 18 focused
`SparseAttentionIndexerShapeInferenceTest` cases. On current `main`, a
Linux Release WebGPU provider/provider-test build and all 23 focused
QSA/CSA and packed-indexer cases passed on NVIDIA H200/Vulkan, including
both bounded-cache fallback thresholds. Focused formatting and `git diff
--check` passed.
- End-to-end NVIDIA H200 Vulkan testing used a non-paged, no-MTP Qwen3.8
raw INT4 RTN/INT8-last-matmul Generator export, with 16-token prefill
chunks:

| Context | Before | After |
| --- | --- | --- |
| 16-token prefill | 43.27 s | 1.51 s |
| Next decode step after 16 tokens | 42.63 s | 0.70 s |
| 1K prefill | Did not complete within 181 s of prefill | 68.33 s (14.99
tok/s) |
| 1K decode | No valid rate | 1.29 tok/s over eight tokens |
| 2K prefill | No prior completed result | 145.37 s (14.09 tok/s) |
| 2K decode | About 30.8 s/step at the old cache boundary | 1.03 tok/s
over eight tokens |

The eight generated pieces from the four-token smoke prompt were
unchanged, as was the first token ID from the 16-token probe. Model-load
time (~58–60 s) is excluded from prefill measurements. The H200 static
WebGPU build now executes the WebGPU-specific parity tests; all 23
focused QSA/CSA and packed-indexer cases passed on current `main`.

The EngramGate and GenAI builder/runtime fixes in the working tree are
not part of this PR.

The performance table above was measured on the earlier Qwen3.8
integration branch; GPU regression tests, not full-model timing, were
rerun on current `main`.

## Current main update (October 6)

Kunal's #32656 merged, and this PR is now based on `main` with a
three-file QSA-only review diff. Merged current `main` again after that
restack. The WebGPU provider-test build and all 23 focused H200 QSA/CSA
plus packed-indexer tests passed. The October 6 Windows WebGPU job
exposed a long-running visibility-overflow boundary test that lost the
D3D12 device. Commit 9499988 avoids redundant prefix rescans; all 22
focused WebGPU QSA/CSA tests pass on H200/Vulkan, with that boundary
test taking 241 ms. Android minimal-size CI passed on the preceding
head; CI for the fix is pending.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants