Flash Attention for PyTorch on Apple Silicon (M1/M2/M3/M4)
Project description
MPS Flash Attention
Flash Attention for PyTorch on Apple Silicon (M1/M2/M3/M4/M5).
O(N) memory instead of O(N²), enabling 100K+ sequence lengths on unified memory.
Performance
Benchmarked on Apple Silicon (M1/M2/M3/M4/M5):
| Seq Length | vs PyTorch SDPA | Notes |
|---|---|---|
| 1024 | 1.1-2.0x faster | Crossover point |
| 2048 | 1.7-3.7x faster | Sweet spot |
| 4096 | 2.0-3.9x faster | Peak performance |
| 8192+ | 3-4x faster | SDPA often OOMs |
Average speedup: 1.8x across all configurations.
Installation
pip install mps-flash-attn
Build from source
git clone --recursive https://github.com/mpsops/mps-flash-attention.git
cd mps-flash-attention
# Build Swift bridge
cd swift-bridge && swift build -c release && cd ..
# Install (uses the torch already in your environment)
pip install -e . --no-build-isolation
To build the full PyPI matrix (5 Python versions, dual torch ABIs), use
scripts/build_all_wheels.sh. The wheels land in dist/. Run
bash tests/wheel_matrix/test_wheel_matrix.sh to verify each wheel against
the torch versions it claims to support.
Usage
Basic Attention
from mps_flash_attn import flash_attention
# (B, H, N, D) format
q = torch.randn(2, 8, 4096, 64, device='mps', dtype=torch.float16)
k = torch.randn(2, 8, 4096, 64, device='mps', dtype=torch.float16)
v = torch.randn(2, 8, 4096, 64, device='mps', dtype=torch.float16)
out = flash_attention(q, k, v)
Causal Masking
out = flash_attention(q, k, v, is_causal=True)
Sliding Window (Mistral/Llama 3.2)
# Only attend to last 4096 tokens
out = flash_attention(q, k, v, is_causal=True, window_size=4096)
Quantized KV Cache (2-4x memory savings)
from mps_flash_attn import flash_attention_fp8, quantize_kv_fp8
# Quantize K/V to FP8
k_quant, k_scale = quantize_kv_fp8(k)
v_quant, v_scale = quantize_kv_fp8(v)
# Run attention with quantized KV
out = flash_attention_fp8(q, k_quant, v_quant, k_scale, v_scale)
100K+ Long Sequences
from mps_flash_attn import flash_attention_chunked
# Process 100K tokens without OOM
q = torch.randn(1, 8, 100000, 64, device='mps', dtype=torch.float16)
k = torch.randn(1, 8, 100000, 64, device='mps', dtype=torch.float16)
v = torch.randn(1, 8, 100000, 64, device='mps', dtype=torch.float16)
out = flash_attention_chunked(q, k, v, chunk_size=8192)
Drop-in SDPA Replacement
from mps_flash_attn import replace_sdpa
replace_sdpa() # Patches F.scaled_dot_product_attention
# Now all PyTorch attention uses Flash Attention on MPS
torch.compile() Support
from mps_flash_attn import register_custom_op
register_custom_op()
@torch.compile
def my_attention(q, k, v):
return torch.ops.mfa.flash_attention(q, k, v, False, None, None)
Training with BF16 Backward
out = flash_attention(q, k, v, bf16_backward=True) # 2x faster backward
loss = out.sum()
loss.backward()
Benchmarking
# Quick benchmark
python -m mps_flash_attn.benchmark --suite quick
# Full suite with report
python -m mps_flash_attn.benchmark --suite full --output report.html
from mps_flash_attn.benchmark import run_suite, compare_vs_sdpa
results = run_suite(seq_lengths=[1024, 2048, 4096])
compare_vs_sdpa()
Features
| Feature | Supported | Notes |
|---|---|---|
| Forward pass | yes | FP16/BF16/FP32 |
| Backward pass | yes | Full gradient support |
| Causal masking | yes | Native kernel support |
| Attention masks | yes | Boolean masks |
| Sliding window | yes | For local attention models |
| GQA/MQA | yes | Grouped-query attention |
| Quantized KV | yes | FP8, INT8, NF4 |
| Chunked attention | yes | 100K+ tokens |
| torch.compile() | yes | Custom op backend |
| Dropout | no | Not supported |
Architecture
Python API (mps_flash_attn)
|
C++ Extension (_C_legacy.so or _C_modern.so, picked at import)
| dlopen
Swift Bridge (MFABridge.swift)
|
Metal Flash Attention (kernel generation)
|
Metal GPU Shaders
Requirements
- macOS 14+ (Sonoma, Sequoia, or Tahoe)
- Apple Silicon (M1/M2/M3/M4/M5)
- Python 3.10, 3.11, 3.12, 3.13, or 3.14
- PyTorch 2.5 through 2.11
Tested torch + Python combinations
| torch 2.5 | 2.6 | 2.7 | 2.8 | 2.9 | 2.10 | 2.11 | |
|---|---|---|---|---|---|---|---|
| py 3.10 | OK | OK | OK | OK | OK | OK | OK |
| py 3.11 | OK | OK | OK | OK | OK | OK | OK |
| py 3.12 | OK | OK | OK | OK | OK | OK | OK |
| py 3.13 | OK | OK | OK | OK | OK | OK | |
| py 3.14 | OK | OK | OK |
Empty cells are combinations PyTorch itself does not ship wheels for.
The dependencies field in the wheel pins torch>=2.5,<2.12, so pip install mps-flash-attn will refuse to install on a torch outside this range rather
than installing and crashing at runtime. When a new torch minor is released we
cut a release that bumps the upper bound.
Credits
- metal-flash-attention by Philip Turner
- Flash Attention paper by Tri Dao et al.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mps_flash_attn-0.6.1-cp314-cp314-macosx_11_0_arm64.whl.
File metadata
- Download URL: mps_flash_attn-0.6.1-cp314-cp314-macosx_11_0_arm64.whl
- Upload date:
- Size: 856.8 kB
- Tags: CPython 3.14, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d714dcca32cece3a355bda7ebfd45137457684e51eff46b9f57197b2274d06c
|
|
| MD5 |
0ec261884a540bcc35a38d79cbd8dff0
|
|
| BLAKE2b-256 |
fc82ab5537c5b4383b5677e1bb704acf5d02090c7d66ce99182a379b4f23f051
|
File details
Details for the file mps_flash_attn-0.6.1-cp313-cp313-macosx_11_0_arm64.whl.
File metadata
- Download URL: mps_flash_attn-0.6.1-cp313-cp313-macosx_11_0_arm64.whl
- Upload date:
- Size: 958.8 kB
- Tags: CPython 3.13, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b45ffb027a0c4b005d614f94b586120d3e0b0716608117cd6e7797044d77482f
|
|
| MD5 |
6053e09d99266147eff116aac9009e8f
|
|
| BLAKE2b-256 |
4c8b0d2064dc03c489ae44d649f5640a94167417e4eb20be6408d10723714b62
|
File details
Details for the file mps_flash_attn-0.6.1-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: mps_flash_attn-0.6.1-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 958.7 kB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
924f53b4b6d84e0757dcc3ad17119721b9065b62b608ed69fa70603496852287
|
|
| MD5 |
b39ff98c92113cf4db7395a0af056db7
|
|
| BLAKE2b-256 |
539207b70d44c1115a437e604bad518a971f6d9a3a200d88e5fc95ce184410a1
|
File details
Details for the file mps_flash_attn-0.6.1-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: mps_flash_attn-0.6.1-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 962.9 kB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d3e94f9c414212f184fcf02d81aa891fe7844d70195af7a35840b71c789fe92d
|
|
| MD5 |
be8a6e271dc019cda7ec151739801423
|
|
| BLAKE2b-256 |
41a6823724217d8f43ce8764fa61a0a253e39378d6efdf4212ea2b5335580398
|
File details
Details for the file mps_flash_attn-0.6.1-cp310-cp310-macosx_11_0_arm64.whl.
File metadata
- Download URL: mps_flash_attn-0.6.1-cp310-cp310-macosx_11_0_arm64.whl
- Upload date:
- Size: 956.9 kB
- Tags: CPython 3.10, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d136e5b28c2d59b33bb48f401d0e5d53ee028e6c9c43a697ca22aa7004e7fd1
|
|
| MD5 |
1ffc70f4c7a2a4b490ad00621edb46fb
|
|
| BLAKE2b-256 |
0e93ffd8a04ffc7122c9cf75a8d53a470ae6b4f98b447056e18738e5864133fe
|