Skip to content

frost(sdpa): SM80 adapters still normalization-copy non-compact operands (_stage/_to_bshd .contiguous()) — should address declared strides natively #787

Description

@egilliam-nv

Follow-up from #716 review (requested by @vedaanta): remove the SDPA SM80 adapters' operand staging — most immediately the per-execute .contiguous() allocations inside it — in favor of kernels that address declared operand strides natively.

Current state

Backwardpython/cudnn/sdpa/bwd/api.py execute._stage (on develop today):

return _pad_last_dim(view.contiguous() if not view.is_contiguous() else view, fd)
...
return view.contiguous()

Every execute with a dense_flex (non-BSHD-compact) operand or a head-dim pad allocates fresh tensors — an AGENTS.md Rule 1 violation ("no per-execute allocation") that #716's carving pass fixed for the kernel-internal buffers but not for these operand gathers.

Forward — the SdpaFwdDsl base helpers have the same issue for wrapper-path callers:

  • _to_bshd: return view if view.is_contiguous() else view.contiguous()
  • _to_bshd_writable: torch.empty_like(view, ...) per execute

Two milestones

  1. Kill the allocations (Rule 1) — gather into carved workspace instead of .contiguous(). For the backward this lands with frost(sdpa): port the SM80 backward onto SdpaBwdDsl + TemplateParams with sym_int THD extents (issue #604) #765, which deletes bwd/api.py; its replacement _stage carves via the Convert torch-native SM80 SDPA adapters to scratch workspace carving #514 machinery (zero allocation when a workspace is provided). The forward's _to_bshd/_to_bshd_writable residual remains open after frost(sdpa): port the SM80 backward onto SdpaBwdDsl + TemplateParams with sym_int THD extents (issue #604) #765.

  2. Kill the staging copies entirely (Rule 2 end-state) — even a carved gather is a copy per execute. The kernels should address non-compact operand layouts natively via declared strides, the way the forward f16 kernels already handle THD declared token strides ("no normalization-copy fallback") and the way frost(sdpa): SM80 backward native strided-LSE reads + THD max_s_kv grid hint #766 makes the backward's LSE reads stride-aware (after frost(sdpa): enable sdpa_fwd engines to write dense LSE directly to non-contiguous, dense-compatible layouts #712 did the forward's LSE writes). Concretely: stride-parameterized global loads for Q/K/V/O/dO (and stores for dQ/dK/dV) in the SM80 kernels, with the plan-time declared strides carried on the template compile() seam like lse_stride. Once operands bind natively, _stage and the gather sizing in scratch_workspace_bytes() can be deleted outright. Declarations the hardware/addressing cannot express should be REJECTED in check_support, not silently copied.

Head-dim padding (flavor envelopes) is a separate concern from layout normalization and may legitimately keep a carved staging path — or move into the kernels as predicated loads; to be decided as part of milestone 2.

Related

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions