Library / SDK
DTolm/VkFFT avatar
DTolm/VkFFT

VkFFT: one FFT header across six compute backends

Vulkan/CUDA/HIP/OpenCL/Level Zero/Metal Fast Fourier Transform library

1,786 stars148 forksC++MIT

At a glance

What is it?
A header-only Fast Fourier Transform library that compiles its kernels at run time for Vulkan, CUDA, HIP, OpenCL, Level Zero and Metal, targeting sizes up to roughly 2^32 per dimension. It positions itself as an open alternative to cuFFT and doubles as the benchmark harness for it.
Who is it for?
Use VkFFT when you need an FFT on Apple, AMD or Intel silicon, or when you want one implementation across several compute APIs instead of a vendor library per GPU. Do not reach for it on an NVIDIA-only project where cuFFT is already installed and working, since the stated aim is to be an alternative to cuFFT rather than to replace it in its own ecosystem.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Six backends, one define

VkFFT's headline is that the same library covers Vulkan, CUDA, HIP, OpenCL, Level Zero and Metal. The README states it aims to provide the community with an open-source alternative to Nvidia's cuFFT library while achieving better performance, and that it runs on Nvidia, AMD, Intel and Apple GPUs as well as the Raspberry Pi 4 GPU, across Windows, Linux and macOS.

The switching mechanism is a preprocessor value rather than an abstraction layer. You include vkFFT.h and define VKFFT_BACKEND to the constant for the API you want: 0 for Vulkan, 1 for CUDA, 2 for HIP, 3 for OpenCL, 4 for Level Zero, 5 for Metal. Each backend also has its own prerequisites, which are the part people miss. CUDA and HIP need NVRTC or HIPRTC built into the system. Level Zero needs clang and llvm-spirv to work as system calls. Metal needs metal-cpp, the C++ bindings Apple's libraries are reached through, and a metal-cpp directory is vendored in the repository for that reason.

There is a paper you can cite, published through IEEE Xplore, which is unusual for a library at this stage and useful if you need to reference the approach in academic work.

Kernels are compiled at run time, which shapes everything else

VkFFT is a header-only library, and the README says that explicitly as a feature: you append it directly to your own command buffer, and kernels are compiled at run time.

That has two consequences. The positive one is that there is no build step for your shaders and no runtime shader cache to ship; the library compiles what the current configuration needs. The cost is that planning and compilation happen at startup, and the README notes all computations are based on compute shaders with no CPU usage except for FFT planning.

The library operates on storage buffers that the user allocates. It does not require additional memory by itself, apart from lookup tables when they are enabled. It also creates and optimises the memory layout itself and picks the FFT parameters, which means you do not choose a radix or a tile size.

One more design decision: striding is achieved by grouping nearby FFTs rather than by transposition. The README qualifies this, noting that data can be reshuffled after the Four Step FFT algorithm with an additional buffer for big sequences, but that this does not matter for convolutions because they return to the input ordering.

Rader and Bluestein cover what the radices do not

The transform core is not restricted to powers of two. The README lists radix 2, 3, 4, 5, 7, 8, 11 and 13, with the claim that sequences using radix 3, 5, 7, 11 and 13 have comparable performance to powers of two.

Arbitrary lengths are handled by two named algorithms. Rader's algorithm covers primes from 17 up to roughly the maximum shared memory length, around 10000, and is described as inlined and done without additional memory transfers. Bluestein's algorithm handles everything else, and the README says it is optimised to have as few memory transfers as possible by using zero padding and the merged convolution support of the library.

Size limits are stated as approximately 2^32 in all dimensions for all transform types, and the README attributes this to the amount of shared memory available on the device. So the practical ceiling is a hardware property, not a compile-time constant you can raise.

The dimension count is not fixed either: 1D, 2D, 3D and ND are all supported, with VKFFT_MAX_FFT_DIMENSIONS used to specify the maximum number of dimensions.

Precision modes do not all behave the way their names suggest

Four precisions are supported: single, double, half and quad, where quad means double-double. The caveats matter more than the list.

Double and quad precision use LUT tables generated on the CPU. That is the practical reason they cost more and why the library needs memory for them. Half precision does not do its arithmetic in half: the README states it still does all computations in single and only uses half precision to store data.

So if you are porting a half-precision workload expecting half-precision arithmetic speed, you will not get it. You get the memory saving, not the compute saving.

Dimensions are configurable too. 1x1, 2x2 and 3x3 convolutions are supported with symmetric or non-symmetric kernels, and the README notes no register overutilisation.

Half precision also has a Vulkan version requirement that differs from the others: single and double precision need Vulkan 1.0, while half precision needs Vulkan 1.1.

R2R, R2C and C2R are treated as first-class, not as conversions

Beyond complex-to-complex, the library handles real-to-complex, complex-to-real and real-to-real Discrete Cosine Transforms of types I, II, III and IV.

The performance claim attached to these is specific: R2R, R2C and C2R are optimised to run up to twice as fast as C2C and to take half the memory. That follows from the structure of the transforms rather than being an implementation trick, and it is the reason to use the real-input paths rather than converting your data to complex and back.

The data layout is also defined. WHD+CN orders storage by increasing strides across width, height, depth, other dimensions, the coordinate (the number of feature maps), and the batch number. Knowing that order up front saves a debugging session.

Zero padding is native rather than emulated. The README describes it as up to twice as fast as simply padding the input array with zeros, because it models open systems, and you can specify both which range of sequences is zero-filled and whether padding is applied at the read or write stage.

The test suite doubles as a cuFFT comparison harness

VkFFT_TestSuite.cpp is at the repository root and doubles as the example application, with comments explaining the configuration process. It is also a command-line benchmark tool.

bash
-d 0 -o output.txt -vkfft 0 -cufft 0

That runs the single precision VkFFT and cuFFT benchmarks on device 0 and writes the log to output.txt, and it is the Windows executable form given in the README. Double precision is -vkfft 1 -cufft 1 and half precision is -vkfft 2 -cufft 2.

The full flag set: -h prints help, -devices lists available GPU devices, -d X selects a device with 0 as the default, -o NAME sets the output file path, -vkfft X runs a VkFFT sample with X in 0 to 17, 100, 101, 200, 201 or 1000 to 1003, and -cufft X runs a cuFFT sample. The cuFFT and rocFFT samples only exist if FFTW was enabled, and the README notes rocfft with a similar sample range.

Passing -test, or no other keys at all, launches the full set of benchmarks.

Building the benchmark means editing one line of CMakeLists

There is no package manager entry in the README. The documented path is to clone the repository and use the sample CMakeLists.txt, which is configured around a Vulkan_FFT.cpp source file containing examples of FFT, inverse FFT and convolution, zero padding, multiple feature and batch convolutions, large C2C systems, R2C and C2R transforms, DCT types I through IV, and the double and half precision paths.

To change backend, you edit line 5 of CMakeLists and replace VKFFT_BACKEND with the value for your API, and you can optionally enable FFTW so the cuFFT and rocFFT comparison samples build.

For Vulkan specifically you also need the glslang compiler, since the shaders are compiled at run time rather than shipped.

The repository is laid out in parallel: vkFFT/ holds the library, VkFFT_TestSuite.cpp the harness and example, documentation/ the explicit documentation, benchmark_scripts/ and benchmark_plot/ the results tooling, precision_results/ the precision data, and half_lib/ and metal-cpp/ the vendored dependencies.

A mature feature list against a release history that has stalled

The feature list is long and specific, which suggests a library that has been worked on for years. The release tags tell a different story about distribution. The three most recent releases are Windows executables builds: v1.3.4 on 2024-02-06, v1.3.3b on 2024-01-15 and v1.3.2 on 2023-10-23. They are not library version tags for the headers; they are test suite binaries.

But if you pin, note that the distribution artefacts people download are dated 2024.

The future release plan in the README lists one ambitious item: multiple GPU job splitting. Nothing else is promised, and the plan section is short enough that it reads as a to-do rather than a roadmap.

The licence is MIT. The README mentions no CLA, and the project has a documentation folder and a white paper, which suggests it is used in published work; the README provides a citation link for that reason.

Editorial conclusion

Use VkFFT when you need an FFT on Apple, AMD or Intel silicon, or when you want one implementation across several compute APIs instead of a vendor library per GPU. Do not reach for it on an NVIDIA-only project where cuFFT is already installed and working, since the stated aim is to be an alternative to cuFFT rather than to replace it in its own ecosystem. Verify first which backend you compile by setting VKFFT_BACKEND, from 0 for Vulkan through 5 for Metal, and note that double and quad precision use CPU-generated lookup tables while half precision still computes in single precision and only stores in half.

Frequently asked questions

Which GPU backends does VkFFT support?

Vulkan, CUDA, HIP, OpenCL, Level Zero and Metal, selected with the VKFFT_BACKEND define: 0 for Vulkan, 1 for CUDA, 2 for HIP, 3 for OpenCL, 4 for Level Zero, 5 for Metal. CUDA and HIP need NVRTC or HIPRTC, Level Zero needs clang and llvm-spirv, and Metal needs metal-cpp.

How does VkFFT handle FFT sizes that are not powers of two?

It uses radix 2, 3, 4, 5, 7, 8, 11 and 13 for common factors, Rader's algorithm for primes from 17 up to roughly 10000, and Bluestein's algorithm for everything else. The README says the radix 3, 5, 7, 11 and 13 sequences have performance comparable to powers of two.

Does VkFFT do half-precision arithmetic?

Not in the way the name suggests. The README states that half precision still does all computations in single precision and only uses half precision to store data. Double and quad precision use CPU-generated LUT tables, and quad means double-double.

Is VkFFT a drop-in replacement for cuFFT?

The README frames it as an open-source alternative to cuFFT, and the test suite includes cuFFT sample flags so you can benchmark the two side by side on the same device. You still select a backend with VKFFT_BACKEND and call the VkFFT API rather than the cuFFT one.

Official sources

  1. DTolm/VkFFT on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dtolm-vkfft.svg)](https://hysenlabs.com/projects/dtolm-vkfft)

Was this useful?