Skip to content

Reuse Stockham twiddles in large batched Bluestein FFTs - #4084

Open
PhysicistJohn wants to merge 1 commit into
ml-explore:mainfrom
PhysicistJohn:reuse-bluestein-stockham-twiddles
Open

Reuse Stockham twiddles in large batched Bluestein FFTs#4084
PhysicistJohn wants to merge 1 commit into
ml-explore:mainfrom
PhysicistJohn:reuse-bluestein-stockham-twiddles

Conversation

@PhysicistJohn

@PhysicistJohn PhysicistJohn commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Fused Bluestein runs two Stockham transforms with the same stage roots for every
transform in the batch. For complex64 transforms using the exact 4096-point
internal plan with total batch at least 1024, this change generates one
584-value radix-twiddle table on the host, appends it to the existing Bluestein
constants allocation, and reuses it in both internal FFTs. Dynamic and
precomputed roots use the same shared radix codelets.

On an Apple M5 Max, matched public fft and ifft calls improve by 3–4% at
batch 1024 and by up to 7% at batch 2048. The selected path adds 16,384 bytes
of measured peak allocation and 34,288 bytes (0.0206%) to mlx.metallib, with
no symbol-name changes.

Smaller batches, other internal plans, and real transforms retain dynamic
twiddles. No public API, buffer binding, or kernel entry point changes.

Results

Public lengths 1030, 1031, 1531, and 2047 all select the 4096-point internal
plan. All 20 selected timing cases improved with paired 95% lower bounds above
1.0.

Path Batch Median speedup range Lowest paired 95% lower bound Peak allocation delta
fft 1024 1.0329–1.0379x 1.0195x +16,384 B
ifft 1024 1.0320–1.0355x 1.0243x +16,384 B
fft 1025 1.0284–1.0339x 1.0244x +16,384 B
fft 2048 1.0572–1.0651x 1.0470x +16,384 B
ifft 2048 1.0263–1.0736x 1.0171x +16,384 B
fft control 1023 0.9951–1.0095x all intervals include 1.0 0 B

The other controls were neutral: the smaller 1024-point Bluestein plan
measured 1.0009x in both directions, and rfft(1031) measured 0.9991x. Their
paired intervals included 1.0 and peak allocation was unchanged.

Validation

  • Static and JIT Metal builds passed the focused forward/inverse regression
    under Metal API validation.
  • AIR inspection confirmed that the selected specialization removes all
    reachable fast sin/cos calls from both internal passes and uses
    packed-table loads.
  • The full GPU FFT module passed in both builds: 16 passed, 2 expected skips.
  • Deterministic varied complex inputs were compared with each artifact's
    batch-one dynamic-twiddle result. All recorded cases were finite and passed
    the existing tolerances; worst normalized RMSE was 5.443e-7 and worst
    absolute error was 6.574e-4.
  • Pre-commit formatting and diff checks passed.
Methodology and artifact accounting

Measurements compare main at 8d666298 with candidate b5cd45e4 using
static Metal on macOS. Each case used deterministic matched inputs, 10
warmups, 9 samples of 30 transforms, 5 alternating ABBA/BAAB rounds, and 10
paired comparisons. Timings include operation construction, host constant
generation, dispatch, evaluation, and synchronization.

Artifact main Candidate Delta
mlx.metallib 166,579,352 B 166,613,640 B +34,288 B (+0.0206%)
libmlx.dylib 22,038,704 B 22,038,928 B +224 B
Defined Metal symbols 16,632 16,632 0

The Metal symbol-name sets are identical.

@zcbenz zcbenz added the await verification This pull request is non-trivial and requires a human expert to verify its correctness. label Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

await verification This pull request is non-trivial and requires a human expert to verify its correctness.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants