Skip to content

Add GQA workspace preparation recipes - #32446

Merged
Ti-Tai Wang (titaiwangms) merged 4 commits into
microsoft:mainfrom
titaiwangms:titaiwangms/gqa-workspace-foundation
Sep 14, 2026
Merged

Ti-Tai Wang (titaiwangms) merged 4 commits into
microsoft:mainfrom
titaiwangms:titaiwangms/gqa-workspace-foundation

Conversation

@titaiwangms

Copy link
Copy Markdown
Contributor

Summary

Add the graph-free workspace preparation foundation for CUDA GroupQueryAttention, following the checked-recipe architecture established by #32321.

  • model windowed KV-cache staging and compaction without changing runtime allocations;
  • model 3-vector/6-vector sequence metadata and Flash fast-decode suppression;
  • model route-selected QKV preprocessing requirements;
  • use checked arithmetic and one internally 256-byte-aligned preparation layout;
  • distinguish transient staging/compaction from output KV cache and persistent/prepacked state.

Scope

This is the first GQA workspace-estimation PR in the #29775 rollout. It intentionally does not add backend-internal workspace recipes, route aggregation, Level-1 estimation, Level-2 declaration, cuDNN workspace queries, or #32071 planner integration. Existing GetScratchBuffer() allocation count, size, lifetime, and pointer layout are unchanged.

Follow-up PRs will add:

  1. XQA and Flash regular/fast-decode workspace recipes.
  2. CUTLASS MEA and unfused fallback recipes plus the complete route aggregate.
  3. Optional-aware Level-1/Level-2 adapters with one 256-byte-aligned operator root.
  4. cuDNN support only if an exact runtime-parity workspace query can be established.

Validation

  • 30 GQA workspace recipe and validation tests passed.
  • 73 related GroupQueryAttention runtime tests passed; 12 WebGPU-only tests skipped because WebGPU EP was unavailable.
  • CUDA provider test target built successfully.

Tracking: #29775

Introduce graph-free checked workspace recipes for GroupQueryAttention preparation buffers, including windowed cache staging, compaction, sequence metadata, and QKV preprocessing layouts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: b24d04bb-12ab-41a0-8941-76eb9769005d
@titaiwangms
Ti-Tai Wang (titaiwangms) marked this pull request as ready for review September 8, 2026 17:21
Copilot AI balanced review requested due to automatic review settings September 8, 2026 17:21
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b24d04bb-12ab-41a0-8941-76eb9769005d

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.

🟢 Approval recommended

The implementation matches runtime allocation formulas and has comprehensive boundary and parity coverage.

Pull request overview

Adds graph-free CUDA GroupQueryAttention workspace recipes with checked sizing and validation.

Changes:

  • Models staging, compaction, sequence metadata, and QKV preprocessing.
  • Adds overflow, validation, layout, and runtime-parity tests.
  • Verifies plugin-safe standalone header compilation.

No actionable issues identified.

File summaries
File Description
group_query_attention_workspace.h Defines workspace recipe interfaces.
group_query_attention_workspace.cc Implements checked sizing and validation.
group_query_attention_workspace_test.cc Tests recipes and edge cases.
group_query_attention_workspace_header_test.cc Verifies isolated header compilation.
cmake/onnxruntime_unittests.cmake Adds the plugin header test.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@chilo-ms

Copy link
Copy Markdown
Contributor

Found one blocking issue:  GetGQAPreparationRecipe  accepts impossible XQA routes and may underestimate workspace ( group_query_attention_workspace.cc:127-166, 254-264 ). Runtime XQA requires decode with  sequence_length == 1 , not first prompt, and either both caches unquantized or both K/V quantization types supported ( group_query_attention.cc:489-552 ). The recipe currently permits multi-token/first-prompt XQA and even tests asymmetric quantization ( K=PerTensor ,  V=None ) as valid. For packed multi-token input it returns Q-only storage, while the actual fallback route can require Q+K+V. I recommend validating those available XQA eligibility facts or representing this as preprocessing behavior rather than an XQA route.

Reject route facts that cannot select XQA at runtime so preparation recipes cannot underestimate fallback QKV materialization. Clarify the graph-free workspace contract and cover invalid decode and quantization combinations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@titaiwangms

Copy link
Copy Markdown
Contributor Author

Fixed the blocking XQA-route validation issue in 02064f7. GQAPreprocessMode::Xqa now rejects first-prompt and multi-token inputs, asymmetric K/V quantization, packed unquantized caches, non-8-bit quantized caches, and quantized QK-Norm. The former asymmetric/multi-token “valid” fixtures now use runtime-reachable single-token configurations, and parameterized regression tests cover each rejected case. The same fix is also pushed to stacked PRs #32453 and #32454.

@titaiwangms

Copy link
Copy Markdown
Contributor Author

Chi Lo (@chilo-ms) PTAL

@chilo-ms

Copy link
Copy Markdown
Contributor

ValidateProblem()  now rejects first-prompt, multi-token, asymmetric quantization, INT4, and quantized QK-Norm XQA routes. However, it still accepts XQA geometries the runtime cannot select. Runtime XQA requires:

•  head_size  ∈  {64, 128, 256} 
• Quantized group size ∈  {4, 8, 16, 32} 
• Unquantized group size ∈  {1, 2, 4, 5, 8, 16, 32} 

The recipe has both  head_size  and head counts available but does not validate these constraints ( group_query_attention_workspace.cc:167-190  versus  group_query_attention.cc:547-568 ). The updated XQA tests even use  head_size = 8 , so they validate routes that runtime always rejects. This can still underestimate preprocessing when actual dispatch falls through to a route such as MEA, particularly for packed QKV.

Use one graph-free head and group-size contract in runtime dispatch and workspace validation, enforce cache representation for selected XQA routes, and test only runtime-reachable XQA fixtures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@titaiwangms

Copy link
Copy Markdown
Contributor Author

Thanks — this was correct. Fixed in c0dadf6.

The fix is structural rather than another estimator-only copy of the constraints:

  • runtime dispatch and workspace validation now share graph-free predicates for the GQA XQA head-size and quantized/unquantized group-size domains;
  • selected-route validation also requires the matching one-byte/8-bit quantized or two-byte/unpacked cache representation;
  • XQA tests now start from a runtime-reachable H=64, group-4 decode fixture and cover the complete supported/unsupported finite domains.

This prevents the preparation estimator from accepting a claimed final XQA route that runtime would fall back from and therefore underestimating fallback preprocessing. The same shared-predicate change is synchronized to #32453 (4ac4ce9) and #32454 (8fac283).

@titaiwangms
Ti-Tai Wang (titaiwangms) merged commit b03fb52 into microsoft:main Sep 14, 2026
102 of 103 checks passed
Ti-Tai Wang (titaiwangms) added a commit that referenced this pull request Sep 15, 2026
## Summary

Stacked on #32446, add graph-free checked workspace recipes for the CUDA
GroupQueryAttention decode backends:

- reproduce XQA semaphore and multi-block scratch sizing from plain
device/shape scalars;
- retain XQA RoPE Q/K and dynamic FP32 head-sink conversion allocation
parity;
- reproduce Flash regular and fast-decode LSE/split-accumulator sizing;
- preserve the GQA fast-decode distinction between KV heads used for
split selection and query heads used for accumulator allocation;
- fail closed for unsupported XQA cache/storage configurations.

## Flash bounded-estimation constraint

Flash workspace is not monotonic in KV length. For `B=1`, `S_q=1`, two
heads, head size 64, and 108 SMs, increasing KV length from 13,824 to
13,825 changes the selected split count from 54 to 28 and reduces
workspace. Future Level-1/Level-2 aggregation must compute a
conservative envelope or report unavailable rather than evaluating only
the maximum shape.

The split heuristic matches runtime double-threshold semantics,
including a regression boundary where using `0.85f` would select 17
splits instead of the runtime 20.

## Scope

This PR adds concrete selected-backend recipes only. It does not add
MEA/unfused recipes, complete-route composition, dynamic-bound route
reachability, L1/L2 adapters, cuDNN workspace queries, runtime
allocation changes, or #32071 planner integration.

## Validation

- CUDA provider test target built successfully.
- 201 CUDA internal tests passed; 2 unrelated Lean Attention tests
skipped.
- 44 GQA preparation/XQA/Flash tests passed, including runtime-helper
parity and Flash discontinuity regressions.

Tracking: #29775
Dependency: #32446

> This draft temporarily targets `main` because GitHub cannot use a
fork-only branch as the base of an upstream PR. Its diff will reduce to
this commit after #32446 merges.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b24d04bb-12ab-41a0-8941-76eb9769005d
@titaiwangms Ti-Tai Wang (titaiwangms) added memory ep:CUDA issues related to the CUDA execution provider labels Sep 15, 2026
Ti-Tai Wang (titaiwangms) added a commit that referenced this pull request Sep 17, 2026
## Summary

Stacked on #32446 and #32453, complete the graph-free CUDA
GroupQueryAttention selected-route workspace model:

- add CUTLASS memory-efficient Attention K/V expansion and optional FP32
accumulator recipes;
- add the unfused aligned Q/Y/FP32-QK/softmax workspace recipe;
- compose preparation and exactly one selected backend into one checked
256-byte-aligned operator root;
- preserve effective staged KV-cache capacity for MEA;
- report cuDNN workspace as unavailable rather than treating its
allocator-based graph workspace as zero.

## Scope

This PR creates concrete selected-route roots. It does not enumerate
routes reachable under dynamic bounds, add Level-1/Level-2 framework
adapters, query cuDNN graphs, change runtime allocation topology, or opt
into #32071 planning.

## Validation

- CUDA provider test target built successfully.
- 213 CUDA internal tests passed; 2 unrelated Lean Attention tests
skipped.
- 56 GQA workspace tests passed, including MEA, unfused, complete-route
composition, XQA/Flash parity, and cuDNN-unavailable behavior.
- 73 related GroupQueryAttention runtime tests passed; 12 WebGPU-only
tests skipped because WebGPU was unavailable.

Tracking: #29775
Dependencies: #32446 and #32453

> This draft temporarily targets `main` because GitHub cannot use a
fork-only branch as the base of an upstream PR. Its diff will reduce to
this commit after the preceding stacked PRs merge.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b24d04bb-12ab-41a0-8941-76eb9769005d
Chi Lo (chilo-ms) pushed a commit that referenced this pull request Sep 17, 2026
## Summary

Add the graph-free workspace preparation foundation for CUDA
`GroupQueryAttention`, following the checked-recipe architecture
established by #32321.

- model windowed KV-cache staging and compaction without changing
runtime allocations;
- model 3-vector/6-vector sequence metadata and Flash fast-decode
suppression;
- model route-selected QKV preprocessing requirements;
- use checked arithmetic and one internally 256-byte-aligned preparation
layout;
- distinguish transient staging/compaction from output KV cache and
persistent/prepacked state.

## Scope

This is the first GQA workspace-estimation PR in the #29775 rollout. It
intentionally does **not** add backend-internal workspace recipes, route
aggregation, Level-1 estimation, Level-2 declaration, cuDNN workspace
queries, or #32071 planner integration. Existing `GetScratchBuffer()`
allocation count, size, lifetime, and pointer layout are unchanged.

Follow-up PRs will add:

1. XQA and Flash regular/fast-decode workspace recipes.
2. CUTLASS MEA and unfused fallback recipes plus the complete route
aggregate.
3. Optional-aware Level-1/Level-2 adapters with one 256-byte-aligned
operator root.
4. cuDNN support only if an exact runtime-parity workspace query can be
established.

## Validation

- 30 GQA workspace recipe and validation tests passed.
- 73 related GroupQueryAttention runtime tests passed; 12 WebGPU-only
tests skipped because WebGPU EP was unavailable.
- CUDA provider test target built successfully.

Tracking: #29775

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b24d04bb-12ab-41a0-8941-76eb9769005d
Chi Lo (chilo-ms) pushed a commit that referenced this pull request Sep 17, 2026
## Summary

Stacked on #32446, add graph-free checked workspace recipes for the CUDA
GroupQueryAttention decode backends:

- reproduce XQA semaphore and multi-block scratch sizing from plain
device/shape scalars;
- retain XQA RoPE Q/K and dynamic FP32 head-sink conversion allocation
parity;
- reproduce Flash regular and fast-decode LSE/split-accumulator sizing;
- preserve the GQA fast-decode distinction between KV heads used for
split selection and query heads used for accumulator allocation;
- fail closed for unsupported XQA cache/storage configurations.

## Flash bounded-estimation constraint

Flash workspace is not monotonic in KV length. For `B=1`, `S_q=1`, two
heads, head size 64, and 108 SMs, increasing KV length from 13,824 to
13,825 changes the selected split count from 54 to 28 and reduces
workspace. Future Level-1/Level-2 aggregation must compute a
conservative envelope or report unavailable rather than evaluating only
the maximum shape.

The split heuristic matches runtime double-threshold semantics,
including a regression boundary where using `0.85f` would select 17
splits instead of the runtime 20.

## Scope

This PR adds concrete selected-backend recipes only. It does not add
MEA/unfused recipes, complete-route composition, dynamic-bound route
reachability, L1/L2 adapters, cuDNN workspace queries, runtime
allocation changes, or #32071 planner integration.

## Validation

- CUDA provider test target built successfully.
- 201 CUDA internal tests passed; 2 unrelated Lean Attention tests
skipped.
- 44 GQA preparation/XQA/Flash tests passed, including runtime-helper
parity and Flash discontinuity regressions.

Tracking: #29775
Dependency: #32446

> This draft temporarily targets `main` because GitHub cannot use a
fork-only branch as the base of an upstream PR. Its diff will reduce to
this commit after #32446 merges.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b24d04bb-12ab-41a0-8941-76eb9769005d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ep:CUDA issues related to the CUDA execution provider memory

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants