Skip to main content

Non-uniform FFTs (types 1/2/3, dims 1/2/3) on Apple GPUs via Metal/MLX

Project description

mlx-nufft: non-uniform FFTs on Apple GPUs (Metal/MLX)

tests PyPI DOI License: Apache 2.0 Python Platform Backend: MLX

mlx-nufft computes non-uniform fast Fourier transforms, types 1, 2 and 3 in dimensions 1, 2 and 3, on Apple-silicon GPUs via Metal/MLX, with a drop-in mirror of the finufft Python API. It runs an fp32 GPU pipeline with the precision-critical coordinate setup performed in double precision at plan time ("crit64"), so it reaches fp64-grade accuracy on hardware that has no native double precision.

Paper: mlx-nufft.pdf, a technical report describing the method, accuracy, and performance (types 1/2/3 in 1/2/3D, the crit64 precision mechanism, and M1 / M5 Max benchmarks). The performance figures in the report reflect v0.1 and predate the v0.2 speedups; see CHANGELOG.md for current numbers. Pin a tagged release rather than tracking main.

Install

Requires an Apple-silicon Mac (Metal/MLX).

pip install mlx-nufft

Or pin a tagged release straight from GitHub:

pip install "git+https://github.com/martinlachaine/mlx-nufft.git@v0.2.0"

then import mlx_nufft. Dependencies are pinned (notably mlx==0.31.2).

For development, and to run the test and benchmark harness that uses CPU finufft and scipy as references:

git clone https://github.com/martinlachaine/mlx-nufft && cd mlx-nufft
uv venv --python 3.13 .venv
uv pip install -p .venv/bin/python -e ".[dev]"

Verify the install by running the full correctness suite (each test compares against CPU finufft and/or an exact direct-summation oracle):

.venv/bin/python harness/run_tests.py

It prints a per-test pass/fail summary and exits non-zero on any failure. The optional VkFFT backend test reports SKIP unless the bridge in vkfft_bridge/ is built.

Quickstart

A complete, copy-paste-runnable 2-D type-1 transform (M nonuniform points to a N1 × N2 grid of uniform Fourier modes):

import numpy as np
import mlx_nufft as finufft

rng = np.random.default_rng(0)
M, N1, N2 = 100_000, 256, 256
x = rng.uniform(-np.pi, np.pi, M)                          # coords in [-pi, pi)
y = rng.uniform(-np.pi, np.pi, M)
c = rng.standard_normal(M) + 1j * rng.standard_normal(M)   # source strengths

fk = finufft.nufft2d1(x, y, c, (N1, N2), eps=1e-6)         # -> (256, 256) complex

A fuller runnable script (basic call, plan reuse, and a self-check against an exact direct DFT, no finufft install needed) is in examples/quickstart.py:

python examples/quickstart.py

Usage

Drop-in finufft API (same call surface):

import mlx_nufft as finufft

fk = finufft.nufft2d1(x, y, c, (N1, N2), eps=1e-6)   # all nufft{1,2,3}d{1,2,3}
plan = finufft.Plan(1, (N1, N2), n_trans=8, eps=1e-6)
plan.setpts(x, y)
fk = plan.execute(c)

Native plan classes are Type3Plan (the type-3 engine) and Type1PlanND / Type2PlanND (dims 1 to 3):

from mlx_nufft import Type3Plan

# plan once (geometry-dependent setup cached), execute per call
plan = Type3Plan((x1, x2, x3), (s1, s2, s3), eps=1e-5, isign=+1)
f = plan.execute(c)            # f[k] = sum_j c[j] exp(i*isign * s_k . x_j)

Type1PlanND also offers a batched multi-strength execute over one shared point spread, and a cheap re-point of a fixed-mode-box plan to new coordinates:

from mlx_nufft import Type1PlanND

plan = Type1PlanND((x, y), (N1, N2), eps=1e-5, isign=+1)
fk = plan.execute_batch(cs)               # cs: (B, P) over the same points -> (B, N1, N2)
plan.set_sources((x2, y2), backend="gpu") # re-point without recompiling kernels
fk2 = plan.execute(c2)

The double-single phase primitive is also exposed standalone, for callers with a large-magnitude fp64 phase that cannot be reduced mod 2π in fp32 but want the cos/sin on the GPU:

from mlx_nufft import expi, EXPI_MAX_PHASE

z = expi(phi)                    # device complex64 e^{i*phi}, phi an fp64 array
z = expi([a, b, c], isign=-1)    # phase summed in double-single: e^{-i*(a+b+c)}

An optional VkFFT-Metal FFT backend is selectable for the type-3 slab path (Type3Plan(..., fft_backend="vkfft"), requires building the bridge in vkfft_bridge/); MLX's FFT is the default. vkfft_available() reports whether the bridge is built.

Documented differences from finufft

  • Computation is fp32-grade (crit64): eps below 1e-6 clamps with a warning; complex128 inputs are accepted and returned but transformed at fp32 grade.
  • modeord=1 (FFT ordering) is not implemented.
  • 1D/2D type 3 run as degenerate slices of the 3D type-3 kernel.
  • Plans hold points as plan state (setpts); out= and multi-vector (n_trans, ...) shapes mirror finufft, and Plan.execute_adjoint (finufft 2.5) is supported for all three types.

Layout

  • mlx_nufft/, the library: gpu_t3.py (type-3 engine), nd.py (Type1PlanND/Type2PlanND), types12.py, dfmath.py (the expi / double-single primitive), sizing.py (kernel/grid sizing), api.py (the finufft-compatible surface), and vkfft_backend.py.
  • examples/: runnable, dependency-light usage examples (quickstart.py).
  • harness/: correctness tests (test_*.py), the suite runner (run_tests.py), the acceptance/benchmark runner, and the CPU-reference oracle.
  • vkfft_bridge/: optional VkFFT-Metal backend build.

Development and validation

mlx-nufft is AI-assisted, human-directed research software. Its scope, numerical requirements, validation strategy, acceptance criteria, and release decisions are the author's; generative AI tools accelerated implementation, refactoring, test scaffolding, and documentation.

Generated code was not trusted by default. Every component was validated against independent references: CPU FINUFFT, exact direct-summation oracles on small problems, transform-convention and adjoint checks, full dimension/type coverage, dtype/device behavior, and API-parity tests (see harness/).

The author is responsible for the released software, including its design, limitations, and maintenance. Known limitations and hardware assumptions are documented; corrections are welcome via the issue tracker.

License & citation

Apache-2.0 (see LICENSE). mlx-nufft is an independent implementation that follows the FINUFFT/cuFINUFFT algorithms and was validated against FINUFFT; see NOTICE for attribution and the methods papers to cite, and CITATION.cff to cite mlx-nufft itself.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mlx_nufft-0.2.0.tar.gz (72.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mlx_nufft-0.2.0-py3-none-any.whl (74.5 kB view details)

Uploaded Python 3

File details

Details for the file mlx_nufft-0.2.0.tar.gz.

File metadata

  • Download URL: mlx_nufft-0.2.0.tar.gz
  • Upload date:
  • Size: 72.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mlx_nufft-0.2.0.tar.gz
Algorithm Hash digest
SHA256 217d8921add8b548ce79976d1b73e77b4c2ea171f703f53b12cfefe7d7fa94ae
MD5 3faed124152847dfc71cd6d0a9e2c1fd
BLAKE2b-256 641eefb34982007e4aed09ab42ceef09f6157d8cccbd4376e9abf506b52acf53

See more details on using hashes here.

Provenance

The following attestation bundles were made for mlx_nufft-0.2.0.tar.gz:

Publisher: publish.yml on martinlachaine/mlx-nufft

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mlx_nufft-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: mlx_nufft-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 74.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mlx_nufft-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 997631776cafb705bce0842d068855a7f993fe815decfb7588aa3cc3d2914534
MD5 be01fc2638e34bb05cda4ad6c754a707
BLAKE2b-256 45e10f065a60d6ad26a777bab9f4bdf4f3b93ea1e5050c6bed233e97500c3b04

See more details on using hashes here.

Provenance

The following attestation bundles were made for mlx_nufft-0.2.0-py3-none-any.whl:

Publisher: publish.yml on martinlachaine/mlx-nufft

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page