Skip to content

ONNX Attention CUDA: Remaining Opset 24 Feature Gaps #28351

Description

ONNX Attention Op — Remaining CUDA Implementation Gaps

Parent issue: #27516
Related (closed): #27880
Related (open): #28379 (PR — partial closure of item 5 via CPU oracle coverage)

After #27992 merged (3-tier dispatch, unified unfused kernel), the following gaps remain between the ONNX Attention opset 24 spec and our CUDA EP implementation.

Gap Summary

# Feature Spec CUDA Status Code Location Test Coverage Priority
1 qk_matmul_output_mode 1/2/3 Capture post-softcap, post-mask, post-softmax intermediates NOT_IMPLEMENTED (only mode 0 = raw QK / kQK) Reject: core/providers/cuda/llm/attention.cc:1432-1437 · kQK writer: contrib_ops/cuda/bert/unfused_attention.cu:440-445 · CPU reference hooks: core/providers/cpu/llm/attention.cc:500, 519, 546, 554 CPU: covered by spec test (mode 1/2/3 paths in cpu/llm/attention.cc). CUDA: none (the NOT_IMPLEMENTED path means tests can only assert the rejection.) Medium
2 float64 / float8e4m3fn dtypes Type constraint allows Not registered for CUDA EP Kernel registration: core/providers/cuda/llm/attention.cc (search BuildKernelCreateInfo<...Attention...>) None — no registered kernel Low
3 GQA + output_qk output_qk with num_heads > kv_num_heads Flash/MEA excluded by !has_output_qk; falls to unfused. Unfused supports kQK for GQA via reshape-Q trick; modes 1/2/3 share the same gap as item 1. Eligibility filter: attention.cc:1351, 1377 (Flash/MEA exclude on has_output_qk) · Unfused kQK writer: unfused_attention.cu:440-445 (works for GQA) · Modes 1/2/3 reject: same as item 1, attention.cc:1432-1437 CUDA: kQK + GQA exercised indirectly via existing unfused tests; modes 1/2/3 + GQA: none (blocked by item 1) Low
4 Mask right-padding attn_mask last dim < total_seq_length (pad with -inf) Rejected at validation Validation: core/providers/cpu/llm/attention_helper.h:146 (ORT_ENFORCE on exact match). TODO already in source: attention_helper.h:141-145. Used by both CPU and CUDA EPs. None — rejected before kernel dispatch Low
5 softcap + fp32 (no Flash/MEA fallback) Should work for all dtypes fp32 only has unfused path; CUDA path correctness now indirectly attested via CPU oracle parity fp32-GQA fall-through: attention.cc:1373-1376 (!(is_gqa && std::is_same<T, float>::value) filter) · Unfused entry: attention.cc:976-1000 (RunUnfusedAttention header) CPU: added in #28379 — test/python/transformers/test_onnx_attention/test_gqa.py:2892 TestONNXAttentionGQASoftcapFloat32CPU and test_mha.py:1955 TestONNXAttentionMHAUnfusedSoftcapCPU. CUDA: still implicit (covered by oracle parity at runtime when applicable). Low (partial)

Details

1. qk_matmul_output_mode (Medium)

The unified unfused kernel only supports kNone (no output) and kQK (raw QK scores, scale * Q @ K^T before softcap/mask/softmax). Modes 1 (post-softcap), 2 (post-mask/bias), and 3 (post-softmax) require capturing intermediate values at different pipeline stages. Flash/MEA cannot support this — only the unfused kernel can, but it needs pipeline-stage hooks.

Proposed approach (mirrors CPU): The CPU implementation in core/providers/cpu/llm/attention.cc already handles all four modes by snapshotting the QK buffer at four well-defined stages — kQK (line 500, after scaled QK), kPostSoftCap (line 519, after softcap), kPostMaskBias (line 546, after mask + additive bias), kPostSoftMax (line 554, after softmax normalization). The CUDA unfused kernel in contrib_ops/cuda/bert/unfused_attention.cu already has the same staged structure (lines 415-470 implement softcap → mask → softmax sequentially); add three more if (output_qk != nullptr && qk_matmul_output_mode == ...) snapshot launches mirroring the CPU sites, then drop the early-reject guard at attention.cc:1432-1437. No new kernel required — reuse ScaledCopyQkKernel (already at unfused_attention.cu:63) with appropriate scale=1.0 for the post-stages.

2. float64 / float8 (Low)

The CUDA EP only registers float16, bfloat16, float32. float64 is impractical for GPU attention. float8e4m3fn would require kernel specialization (Hopper sm_90 + intrinsics).

3. GQA + output_qk (Low)

The Flash and MEA paths exclude output_qk requests via the !has_output_qk filter at attention.cc:1351 (Flash) and attention.cc:1377 (MEA), routing all output_qk cases (MHA or GQA) into the unfused path. The unfused kernel handles GQA + kQK natively via the reshape-Q trick (no K/V replication). The remaining gap is GQA + modes 1/2/3, which is blocked by item 1; closing item 1 closes this automatically.

4. Mask right-padding (Low)

Spec allows attn_mask with last_dim < total_sequence_length (remaining positions treated as -inf). The validation in cpu/llm/attention_helper.h:146 enforces exact match; this validator is shared by both CPU and CUDA EPs. A TODO note already lives at attention_helper.h:141-145 describing the fix shape: change == to <=, allocate a padded buffer, fill remainder with mask_filter_value<T>(). Workaround for users today: pad the mask to full size before calling.

5. softcap + fp32 edge case (Low — partially closed)

fp32 cannot use Flash or MEA (fp16/bf16 only). The unified unfused kernel handles softcap+fp32 correctly. PR #28379 added CPU EP twin classes (TestONNXAttentionGQASoftcapFloat32CPU and TestONNXAttentionMHAUnfusedSoftcapCPU) that exercise softcap+fp32 against the attention_ref() oracle, providing reference parity coverage. CUDA-side coverage remains implicit (any CUDA softcap+fp32 GQA/MHA invocation falls through the unfused path validated by the same oracle when CUDA-enabled torch is available — see comment #28351 (comment) for context on this dispatch).

Not Gaps (confirmed not in spec)

  • smoothing_factor — not an ONNX Attention attribute
  • cache_indirection — not an ONNX Attention input
  • sliding_window — not in ONNX Attention (GQA contrib op only)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

ep:CUDAissues related to the CUDA execution providermodel:transformerissues related to a transformer model: BERT, GPT2, Hugging Face, Longformer, T5, etc.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions