Repository navigation
Add Adapt reconstruction for FFT, NFFT, and Toeplitz normal operators - #43
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #43 +/- ##
==========================================
+ Coverage 69.23% 73.01% +3.78%
==========================================
Files 15 15
Lines 520 593 +73
==========================================
+ Hits 360 433 +73
Misses 160 160 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
nHackel
left a comment
There was a problem hiding this comment.
I'm a bit worried that the code for the NFFT adapt will be fairly brittle and will be need frequent changes if NFFT.jl or NonuniformFFTs.jl changes.
An alternative approach would be caching/storing the arguments which are given to the (N)FFT plan constructor call inside the operator and then replaying those with the approriate array types. We could then also have an additional kwarg argument which allows callers to disable caching in case that is performance critical. Adapt shouldn't be used in a hot loop, so probably a Dict{Symbol, Any} is fine
shukebeta
left a comment
There was a problem hiding this comment.
Addressed review 5664445957 in 325cb8e.
The Adapt reconstruction no longer infers state from NFFT.jl or NonuniformFFTs plan internals. FFTOp caches its FFT planner kwargs; NFFTOp caches the explicit backend, original nodes, shape, and every plan_nfft kwarg; and Toeplitz operators cache their FFT planner kwargs. Adapt transfers array-valued cached arguments to the target and replays the public constructor call, preserving exact NFFT grids and custom point transforms. cache=false opts out of retention and makes Adapt fail explicitly rather than guessing.
The PR description now documents this design. Julia 1.10.12 Pkg.test() passes with 699 passed, 1 explicitly broken, 700 total; the broken case is the known NonuniformFFTs + JLArray upstream CPU-kernel gap. The refreshed head is pushed and ready for re-review.
|
Follow-up commit
Validation on Julia 1.10 in Docker: the Adapt-focused suite reports 402 passed, 1 explicitly broken, 403 total, plus 5/5 explicit cache-disabled checks. The broken case is the known NonuniformFFTs + JLArray CPU-kernel gap and remains explicitly marked broken. The earlier package-suite result was 707 passed, 1 explicitly broken, 708 total. The PR description now documents the reconstruction contract, cache tradeoff, unsupported-target behavior, and validation details for the refreshed head. |
What this PR fixes
FFTOpImpl,NFFTOpImpl, andNFFTToeplitzNormalOpcontain backend-bound plans, workspaces, and closures. GenericAdapt.adaptdoes not rebuild those captured resources, so an adapted operator can remain tied to the source storage/backend. Unsupported Adapt targets must not silently fall back to a host operator.How it fixes it
This PR adds explicit
Adapt.adapt_structureimplementations that rebuild fresh target-side plans, workspaces, and closures while preserving operator semantics:FFTOpretains the public FFT planner kwargs by default and replays them with a target-backed work array, preserving shape, shift, unitary normalization, and planner configuration.NFFTOpretains the explicit backend, original node matrix, shape, and all public arguments passed toplan_nfft. Adapt transfers array-valued arguments to the target and replays the same constructor call, preserving the NFFT algorithm family, exact oversampled grid, kernel/settings, and NonuniformFFTs custompoint_transformwithout inspecting backend-specific plan internals. The defaultcache=trueretains a defensive copy of the node matrix and constructor arguments, which has an intentional additional memory cost;cache=falseopts out of that retained state and reconstruction support.NFFTToeplitzNormalOptransfersλand weights to the target, retains its FFT planner kwargs, and rebuilds fresh FFT plans and doubled-shape workspaces there. Workspaces are allocated directly from target storage; adapted values are copied only when Adapt returns the source array itself, avoiding redundant target buffers.cache=falseis available on these constructors for callers who do not want to retain reconstruction arguments; adapting such an operator fails explicitly because faithful replay is unavailable.ArgumentErrorinstead of silently rebuilding on hostArray; supported concrete targets, including same-backendArray, remain valid.Base.copy(::FFTOpImpl)preserves an explicitcache=falseopt-out while keeping its existing default-planner behavior; copy does not unexpectedly replay cached FFT planner kwargs.No Metal capability claim is made by this PR.
Validation
The Julia 1.10 package test suite passed on the preceding head
850cf9c:flags=FFTW.MEASURE, assert the cached kwargs, and assert that rebuilt FFT plans carry the requested flags.ArrayandJLArraytarget storage, FFT forward/adjoint behavior, compound operators and round trips, exact NFFT.jl grid preservation for(12, 16), m=2, σ=1.25, NFFT algorithm-family preservation, NonuniformFFTs custompoint_transformwithfftshift=false, Toeplitzλ/weights, source immutability, unsupported targets, and explicitcache=falsebehavior.GPU CI results will be reported separately when the refreshed head completes. No Metal lane is claimed.