Skip to content

FFT ​

There is a known bug in FFT which can cause segfault. The bug is stochastic and rare, we are working on a fix. If you encounter this please open an issue.

GPU-only FFTs on NDArray, following AbstractFFTs.jl conventions:

  • Every dimension is transformed unless dims is given.

  • fft and bfft! are unnormalized. ifft divides by the transformed length.

  • Real input is promoted to complex (Float32 → ComplexF32, else ComplexF64).

FunctionResult
fft(A, [dims]), ifft(A, [dims])new array
fft!(A, [dims]), ifft!(A, [dims]), bfft!(A, [dims])overwrites A
bfft!(dest, src)unnormalized inverse of src into dest
julia
using cuNumeric

A = cuNumeric.rand(ComplexF32, 64, 64)
Y = fft(A)       # all dimensions
Z = fft(A, 1)    # first dimension only
ifft(Y)          # ≈ A

fft!(A)          # in place
bfft!(A)         # ≈ length(A) * original A

In-place functions require a ComplexF32 or ComplexF64 array.

Batched transforms ​

batched_fft, batched_ifft and their ! forms treat dimension 1 as the batch and transform the rest. The batch axis can split across GPUs. An all-axes fft(A) cannot.

julia
signals = cuNumeric.rand(ComplexF32, 32, 1024)   # 32 traces
batched_fft(signals)                             # FFT along dim 2

Limitations ​

  • GPU only. A CPU-only runtime raises an error.

  • No plan_fft: cuPyNumeric plans inside its FFT task and exposes no plan.

  • On lengths with a prime factor above 131 (e.g. 137), cuFFT is much slower and uses more memory. This is a cuFFT implementation detail. cuNumeric warns when it applies. Zero-padding to a power of two avoids it.

AbstractFFTs.bfft! Method
julia
bfft!(dest::NDArray, src::NDArray)

Write the unnormalized inverse FFT of src into dest without changing src. Both arrays must have the same shape and complex eltype.

source
AbstractFFTs.fft! Method
julia
fft!(A::NDArray, [dims])

In-place fft. A must already be ComplexF32 or ComplexF64.

source
AbstractFFTs.fft Method
julia
fft(A::NDArray, [dims])

Unnormalized complex discrete Fourier transform of A, matching AbstractFFTs.fft. By default every dimension is transformed. dims selects a subset (Julia 1-based dimensions).

Real and integer inputs are converted to complex (Float32 → ComplexF32, everything else → ComplexF64). The result has the same shape as A.

This is GPU-only: cupynumeric's FFT task has no CPU variant. Multi-GPU execution is limited to batching over dimensions that are not transformed.

There is no reusable cuFFT plan; each call launches the CUPYNUMERIC_FFT task.

source
AbstractFFTs.ifft! Method
julia
ifft!(A::NDArray, [dims])

In-place ifft. A must already be ComplexF32 or ComplexF64.

source
AbstractFFTs.ifft Method
julia
ifft(A::NDArray, [dims])

Normalized inverse discrete Fourier transform of A, matching AbstractFFTs.ifft. Equivalent to the unnormalized inverse scaled by 1/N, where N is the product of the transformed lengths.

See fft.

source
cuNumeric.batched_fft! Method
julia
cuNumeric.batched_fft!(A)

In-place batched_fft. A must already be complex.

source
cuNumeric.batched_fft Method
julia
cuNumeric.batched_fft(A)

FFT every trailing dimension of A, treating size(A, 1) as a batch.

A must be at least 2-d. A (b, n) stack is b independent 1-d transforms; (b, n, m) is b independent 2-d transforms. This is the same CUPYNUMERIC_FFT task as fft; the leading axis is the one that may be partitioned across GPUs.

source
cuNumeric.batched_ifft! Method
julia
cuNumeric.batched_ifft!(A)

In-place batched_ifft. A must already be complex.

source
cuNumeric.batched_ifft Method
julia
cuNumeric.batched_ifft(A)

Normalized inverse of batched_fft.

source