Comparing FFT engines

juce::dsp::FFT helpfully provides wrappers to several FFT engines (which are enabled conditionally according to preprocessor definitions), but how does one know which FFT engine to use?

It would had been nice if juce::dsp::FFT would let us choose which engine to use not only at compile-time but also at run-time, so that one could write a simple benchmark that iterates over all of them and compares results.

I’ve done proof-of-concept modifications to it to allow choosing the FFT engine and incorporated a small benchmark in the SimpleFFTDemo

and then did some comparisons of the different engines, and here are the benchmarks results on my M1 Mac:

Engine Order=10 Order=15
Intel IPP (Rosetta) 23 μs 3 ms
Intel MKL (Rosetta) 23 μs 2.9 ms
Apple vDSP (Native) 20 μs 2.5 ms
Apple vDSP (Rosetta) 27 μs 3.5 ms
FFTW 3.3.9 (Native) 18 μs 2.6 ms
FFTW 3.3.9 (Rosetta) 29 μs 3.1 ms
JUCE Fallback (Native) 127 μs 26 ms
JUCE Fallback (Rosetta) 194 μs 35 ms

Some notes:

  • YMMV. This benchmark is only on my own device, as well as not being super-precise (just eyeballed the values from the app). So also feel free to run the benchmark on your devices and add your results.
  • JUCE requires small modifications to support IPP on platforms other than windows (included in the change). Also JUCE’s compilation breaks if enabling both MKL and FFTW (fix included in change)
  • To use FFTW one needs (other than installing it) to set run-time dynamic library paths to find it (LD_LIBRARY_PATH=/opt/homebrew/Cellar/fftw/3.3.9_1/lib:/usr/local/homebrew/Cellar/fftw/3.3.9_1/lib in my case)
7 Likes