Repository navigation
Use NAX attention for long unmasked D72/D80 inputs - #4455
Merged
Merged
Conversation
Head dims 72 and 80 are outside the NAX gate (64/96/128/256) and run on the generic kernel. Pad q/k/v to 96 before the NAX kernel and slice the output back. Adds test_sdpa_head_dim_80 and test_sdpa_head_dim_72_80_sinks.
wyanzhao
marked this pull request as ready for review
September 3, 2026 01:22
wyanzhao
marked this pull request as draft
September 5, 2026 23:25
zcbenz
marked this pull request as ready for review
September 7, 2026 23:47
zcbenz
reviewed
Sep 8, 2026
Contributor
Author
|
@zcbenz Thanks for the review. Addressed all three comments in 96a5404:
|
zcbenz
approved these changes
Sep 8, 2026
aaishwarymishra
pushed a commit
to aaishwarymishra/mlx
that referenced
this pull request
Sep 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Padding D72 and D80 inputs to D96 lets them use the NAX attention kernel. The output is then copied back to its original width. On M5 Max, the four cases below are 1.24–1.99× faster, including those copies.
Potential users include the vision encoders in LFM2.5-VL and Qwen3.5-9B, 27B, and 35B-A3B, which use head dimension 72. Their MLX-VLM implementations (LFM2.5-VL, Qwen3.5) use unmasked attention, so fp16/bf16 inputs with at least 512 tokens per vision attention call on NAX devices can take this path.
Padding was slower for short sequences in earlier tests, so I kept their existing path. The new default applies on NAX devices to fp16/bf16 with query and key lengths ≥512, no mask and no sinks.
I benchmarked batch size 1 with 8 query / 2 KV heads, no mask or sinks. Speedups are paired geometric means of padding-off time / padding-on time.
test_fast_sdpaandtest_fastran 57 tests: 54 passed and 3 skipped, with TF32 disabled. The opt-in test requires Metal and the GPU as the default device. It sets the internal padding override to 1 for the D72/D80 reference checks, including masks and sinks, then restores the previous environment value.These measurements are from
8a516f9c8. The latest commit,96a540459, only changes documentation and tests; I have not rerun the timings. I haven't measured model performance.Tests and benchmark reproduction
Device: M5 Max, 128 GB, macOS 27.0. Measured commit:
8a516f9c80b35ef4a207ecaa3fb1a93358b9d5dd. Binary:libmlx.dylib:7e284cdf23f0+mlx.metallib:1e4de3f525d3.Each timed cell passed a 15-pair A/A calibration and the 5% drift check before its A/B result was accepted. Dispatch observations confirmed native D72/D80 with padding off and NAX D96 with padding on. The equivalence tests alone do not prove which route ran.
To run the updated tests, build
96a54045904b4915705b2f17bb92ac0aac03997afrom source:For benchmark reproduction, use a separate clean checkout of the measured commit,
8a516f9c80b35ef4a207ecaa3fb1a93358b9d5dd, and build it withpython -m pip install -e .. Save the script below asrepro_4455.pyin that checkout root. Use the same Python environment used to build it, and stop other GPU work before measuring. The script uses the internalMLX_SDPA_PAD_HEAD_DIMoverride to compare padding off and on.--smokechecks outputs and exercises short timing loops without estimating speedups. Use--helpto select a single case. Output files must be new names.The script covers all four rows, using seed 187 and 48 batches of four dependent calls per sample. It includes the padding and output copies. OFF/ON output comparison checks numerical agreement; it does not replace the pipeline observations above. Padding also needs temporary Q/K/V and output buffers.
This is an independent reproducer of the workloads, not the driver used for the existing table. It warms both arms, runs 15 alternating A/A pairs, then 15 alternating A/B pairs. Each stage gets 60 seconds of saturation, with a 90-second cooldown before A/B. It reports the geometric mean of OFF/ON time ratios and a Student-t 95% interval in log space. A/A must include 1 in its interval; either stage stops on more than 5% within-arm drift, retaining the rejected result without retrying. It does not implement the original sign-test, Wilcoxon or A/A-noise significance checks.
The JSON includes raw sample times, input shapes, numerical checks, source revision, device and binary hashes. New estimates depend on the machine and build; they do not replace the measurements above.