TornadoVM’s cuFFT integration brings NVIDIA’s highly optimized FFT library into the sameDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Deepak-Sangle/TornadoVM/llms.txt
Use this file to discover all available pages before exploring further.
TaskGraph programming model you use for JIT-compiled Java kernels. FFT transforms run as library tasks that share TornadoVM-managed device buffers with adjacent JIT kernels — no host round-trips between the transform and the spectral-domain processing code. This is particularly powerful for filter pipelines: you can express a complete FFT → filter → inverse FFT → normalize workflow as a single graph where none of the intermediate results ever leave the GPU.
Prerequisite: CUDA Toolkit with cuFFT (
libcufft). cuFFT ships inside the CUDA Toolkit — no separate installation is needed. Build with make BACKEND=cuda.Factory Methods
All factories are static methods onuk.ac.manchester.tornado.cufft.CuFft. Pass them as the second argument to taskGraph.libraryTask(id, factory, args...).
1D Transforms
| Factory | cuFFT Call | Input / Output Types | Notes |
|---|---|---|---|
cufftForwardC2C(in, out, n, batch) | cufftExecC2C(FORWARD) | FloatArray (interleaved re/im) | batch contiguous transforms of length n |
cufftInverseC2C(in, out, n, batch) | cufftExecC2C(INVERSE) | FloatArray (interleaved re/im) | Unnormalized: inverse(forward(x)) = n·x |
cufftForwardR2C(in, out, n, batch) | cufftExecR2C | in: FloatArray (reals); out: FloatArray (complex, Hermitian half) | Output length is (n/2+1)·batch complex elements |
cufftInverseC2R(in, out, n, batch) | cufftExecC2R | in: FloatArray (Hermitian complex); out: FloatArray (reals) | Unnormalized; inverse of R2C |
cufftForwardZ2Z(in, out, n, batch) | cufftExecZ2Z(FORWARD) | DoubleArray (interleaved re/im) | FP64 complex-to-complex |
cufftInverseZ2Z(in, out, n, batch) | cufftExecZ2Z(INVERSE) | DoubleArray (interleaved re/im) | FP64 inverse, unnormalized |
2D Transforms
| Factory | cuFFT Call | Input / Output Types | Notes |
|---|---|---|---|
cufftForward2dC2C(in, out, nx, ny) | cufftExecC2C (2D plan) | FloatArray (interleaved re/im) | Row-major nx × ny grid |
cufftInverse2dC2C(in, out, nx, ny) | cufftExecC2C(INVERSE) (2D plan) | FloatArray (interleaved re/im) | Unnormalized inverse |
Data Layout
Complex Arrays (C2C, Z2Z)
Complex data uses interleaved
(real, imaginary) pairs. A signal of n complex samples requires a FloatArray of length 2n. Access element i as array.get(2*i) (real) and array.get(2*i+1) (imaginary).Real-to-Complex (R2C)
For R2C, the input is a
FloatArray of n real samples per batch. The output is a FloatArray of 2*(n/2+1) complex samples per batch (Hermitian symmetry halves the spectrum). The inverse C2R restores the original n reals.Automatic Plan Caching
cuFFT plans are created once per(transform type, shape) key and cached in the per-(device, execution-plan) context. The provider’s prepare() hook runs before CUDA Graph capture starts, so all plan allocations happen outside the capture region. Subsequent dispatch() calls allocate nothing — they simply reuse the cached plan.
FFT Filter Pipeline Example
The following example implements a complete GPU-resident low-pass filter: a real-to-complex forward FFT, a JIT kernel that zeroes high-frequency bins, a complex-to-real inverse FFT, and a JIT normalization kernel — all in oneTaskGraph with no host-side data movement between steps.
lowpass JIT kernel runs entirely on-device, consuming the spectrum buffer produced by cuFFT and writing back to the same buffer. The inverse cuFFT immediately consumes that modified buffer — zero bytes move through the host.
CUDA Graph Capture
cuFFT library tasks are fully CUDA Graph compatible. Enable graph capture withplan.withCUDAGraph() on the execution plan — iteration 0 captures the graph (including the FFT calls), and all subsequent iterations replay it with a single cuGraphLaunch.
2D FFT Example
For image processing and spectral analysis on 2D grids, usecufftForward2dC2C and cufftInverse2dC2C with row-major nx × ny layout.
Performance
Benchmark: n = 65536
BenchmarkFft compares three implementations on an RTX 4090 at n = 65536 with 20 warm iterations:| Implementation | Time | vs JIT DFT |
|---|---|---|
| Sequential Java DFT | 228,819 ms | baseline |
| TornadoVM JIT DFT kernel | 63.4 ms | 3,611× faster |
| cuFFT library task | 0.080 ms | 793× faster than JIT |
Run the Benchmark
Unit Tests and Runnable Examples
Known Limitations
The following cuFFT features are not yet bound in the current provider. They remain available by implementing a custom provider if needed:cufftPlanManywith advanced strided or embedded layouts- 3D FFT plans
- D2Z / Z2D (double-precision real-to-complex)
- FP16/BF16 via
cufftXtMakePlanMany - LTO callbacks (
cufftXtSetJITCallback) - Explicit workspace control (
cufftSetWorkArea) - Multi-GPU
cufftXtAPI
The
cufftInverseC2C and cufftInverseC2R results are unnormalized. A signal of length n satisfies inverse(forward(x)) = n·x. Normalize by multiplying by 1.0f / n after the inverse transform — as shown in the filter pipeline example above using a JIT scaleBy task.