Skip to content

Repository files navigation

Fast and Memory-Efficient Exact Attention for Large Headdim


FFPA: Fast and Memory-Efficient Exact Attention for Large Headdim, achieving O(1) SRAM complexity (w/ Split-D) and O(d/4) register complexity, 1.5x~6x speedup over standard PyTorch SDPA. FFPA extends the headdim support beyond D > 256 (up to 1024) without any precision loss.

Self Attn GQA/MQA Cross Attn Causal/Mask Dropout Headdim Fwd/Bwd
✔️(Nq=Nkv) ✔️(Hq!=Hkv) ✔️(Nq!=Nkv) ✔️(attn_mask) ✔️(p>0) 320~1024 1.5x~6x↑

Latest News

Quick Start

First, install the prebuilt package from PyPI or build ffpa-attn from source:

# First, install the prebuilt package from PyPI
pip3 install -U ffpa-attn # CUDA 13.0+, PyTorch 2.11+
# Or, build ffpa-attn from source, just follow the cmds
git clone https://github.com/xlite-dev/ffpa-attn.git
# Then, build the wheel package (Triton + CuTe-DSL backends)
cd ffpa-attn && pip3 install -e . --no-build-isolation
# Optional: install ffpa-attn w/ CUDA backend (forward only)
bash ./build.sh --arch sm_120f --ext all --headdim all

Then, try to accelerate the attention for large headdim with just one-line of code:

>>> import torch.nn.functional as F
>>> from ffpa_attn import ffpa_attn_func
>>> # Monkey-patch SDPA to point to FFPA. Every thing that FFPA
>>> # does not support will auto fallback to SDPA: D <= 256, etc.
>>> F.scaled_dot_product_attention = ffpa_attn_func # one-line code

For more advanced features, please refer to our online docs at 📘ffpa-attn.io.

Split-D and TiledMMA

We extend FlashAttention to support large headdim ($D&gt;256$) via fine-grained tiling at the MMA level for $QK^\top$ and $PV$ matrix multiplication. Two orthogonal $O(D)$ bottlenecks — SRAM footprint and register pressure — are broken by Split-D and TiledMMA<4,2,1> respectively.

Split-D: The tiling of the $D$ axis breaks the SRAM bottleneck. A persist-D layout keeps $Q$ resident in SRAM at $O(D)$ ($D{=}512 \Rightarrow 192\text{KB} &gt; 99\text{KB}$ per-CTA limit on sm_8x/sm_120). Split-D chunks the $D$ axis, keeping SRAM fixed at $B_r \times 16$ (with $B_r=B_c$) for Q, K and V, yielding constant SRAM complexity $O(B_r \times 16) \approx O(1)$.

TiledMMA: The M4N2 layout breaks the register bottleneck. The $QK^\top$ has $N{=}B_c$ (fixed, independent of $D$), so its acc is $O(1)$; the $PV$ GEMM instead has $N{=}D$, so the $O$ acc costs $D/(2{\cdot}N_w)$ regs/thread. M8N1 (FA-2 style, $N_w{=}1$) $\Rightarrow O(D/2)$: at $D{=}512$ this already reaches 256 regs/thread, over the 255 architectural limit and spilling. Splitting $N$ to M4N2 (FA-1 style, $N_w{=}2$) halves it to $O(D/4)$, keeping $D{=}1024$ just feasible (256 regs/thread).

Dispatch: M8N1 for $D \le 512$, M4N2 for $D &gt; 512$. On RTX 5090, M4N2 delivers 1.55× the throughput of M8N1 at $D{=}1024$ (154T vs 100T, where M8N1 collapses from register spilling).

Benchmark

Runnable benchmark are provided under bench. The performance benchmarks for the NVIDIA L20 (Ada), NVIDIA Geforce RTX 5090 (Blackwell), NVIDIA H800 PCIE (Hopper), NVIDIA H200 SXM (Hopper, CuTe-DSL backend, up to 535 TFLOPS!) with large headdims can be found at bench.


Backends

FFPA supports multiple backends for the forward and backward pass, including: SDPA (baseline), CUDA (forward only), Triton, and CuTe-DSL. The CuTe-DSL backend is currently in early stage, stay tuned for future updates. The Triton backend (forward + backward) also runs on AMD GPUs.

Backend Arch Fwd Bwd Headdim Autotune Speedup Recommend
SDPA sm>=75 All ✖️ 1.0x sm>=75
CUDA sm>=80 ✖️ 320~1024 ✖️ 1.5x~3x sm_80~89,120{a,f}
Triton sm>=80 320~1024 1.5x~5x sm>=80
CuTe-DSL sm>=80 320~1024 ✖️ 1.5x~2x sm_80~89,120{a,f}
CuTe-DSL sm_90a 320~512 ✖️ 3x~6x sm_90a

How to use different backends for your own scenario? Users can simply pass the Backend configs (SDPABackend, CUDABackend, TritonBackend or CuTeDSLBackend) to ffpa_attn_func, for example:

>>> from ffpa_attn import ffpa_attn_func, CuTeDSLBackend
>>> # CuTe-DSL backend, D=512 scenario, fastest on H200!
>>> o = ffpa_attn_func(q, k, v, backend=CuTeDSLBackend())

Persistent Autotune

Generate device-specific tuned configs for production deployment (currently, Triton only), avoiding per-process autotune cost. The generated JSON is saved under configs dir and automatically loaded when runtime autotune is disabled (the default). See the docs of Triton Autotune for details.

python -m ffpa_attn.autotune --mode max --full-tasks --overwrite # 1 GPU
export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 # Multi-GPU (`pip install ray`)
python -m ffpa_attn.autotune --mode max --full-tasks --num-gpus 8 --overwrite

End-to-End (E2E) Training

NVIDIA-NeMo Automodel PR #2436 shows that on Gemma4-31B training (L=8192, 8xH200, FSDP2 + Activation Checkpointing), accelerating the 10/60 (D=512) full-attention layers with FFPA delivers about 1.4x~1.5x higher throughput (E2E) than SDPA at similar memory footprint, with loss aligned within normal bf16 noise.

License

Apache License 2.0

Citations

@misc{deftruth2026ffpa,
  author       = {DefTruth and Butterfingrz},
  title        = {FFPA: Fast and Memory-Efficient Exact Attention for Large Headdim},
  year         = {2026},
  publisher    = {Zenodo},
  version      = {v1.0},
  doi          = {10.5281/zenodo.20638547},
  url          = {https://doi.org/10.5281/zenodo.20638547}
}

References

About

Fast and Memory-Efficient Exact Attention for Large Headdim, 1.5x~6x speedup over PyTorch SDPA.

Topics

Resources

Stars

321 stars

Watchers

4 watching

Forks

Releases

Packages

Contributors

Languages