The Fast Fourier Transform (FFT) is an efficient algorithm for computing the Discrete Fourier Transform (DFT): it converts a signal from the time domain into the frequency domain, revealing which frequencies are present in a signal and how strong they are. It is the workhorse behind spectrum analyzers, audio effects, filtering, and countless other DSP applications.

I recently published a new FFT library that supports both integer and floating-point data types for its calculations. Using this library, I benchmarked DSP performance across a wide range of microcontroller architectures — from a vintage 8-bit AVR all the way up to a 480 MHz ARM Cortex-M7. The results reveal some surprising winners and a few important lessons about choosing the right chip (and the right data type) for your signal-processing project.


Methodology

Each benchmark measures the time to compute a single N=64 complex FFT and IFFT for five data types: int8_t, int16_t, int32_t, float (32-bit), and double (64-bit). All timings are averaged over repeated runs and reported in microseconds (µs); throughput is derived as 1,000,000 / latency.

Executive Summary & Key Takeaways

  • The single-precision float king: The STM32H7 dominates overall thanks to its 480 MHz clock and a hardware FPU with double-precision support. But the ESP32 and ESP32-S3 punch far above their weight class in single-precision float, outperforming everything except the STM32H7.
  • ESP32-S3 vs. ESP32 — a real generation leap: The ESP32-S3 (Xtensa LX7) delivers a substantial upgrade over the base ESP32 (Xtensa LX6). It cuts the floating-point FFT from 75.14 µs down to 62.62 µs (~17% faster) and crushes integer IFFTs, running int16_t in just 107.96 µs (~33% faster).
  • The double-precision cliff: Devices without a double-precision hardware FPU (ESP32/S3, STM32F411, UNO R4, RP2040) suffer a massive slowdown — frequently 5× to 11× — when stepping from 32-bit float to 64-bit double, because double-precision math must be emulated in software.
  • RP2040 integer power: The RP2040‘s integer performance is exceptionally strong — it even beats the STM32F411 in 8-bit and 16-bit FFTs — but it falls behind on floats because it has no hardware FPU and relies on its (admittedly well-optimized) ROM floating-point routines.

FFT Master Comparison Tables

FFT Calculation Latency (lower is better)

Values are in microseconds (µs) per single N=64 FFT calculation. The fastest data type per board is highlighted in bold.

Microcontroller Core Architecture Clock Speed int8_t int16_t int32_t float (32-bit) double (64-bit)
Arduino Nano AVR ATMega328P (8-bit) 16 MHz 4,144.62 9,798.18 29,160.16 17,165.54 N/A
UNO R4 ARM Cortex-M4 (32-bit) 48 MHz 732.87 668.05 1,108.19 360.89 4,045.90
STM32F411 ARM Cortex-M4 (32-bit) 100 MHz 318.39 284.30 356.52 151.90 1,737.21
RP2040 ARM Cortex-M0+ (32-bit) 133 MHz 228.24 228.37 472.07 939.43 1,672.06
ESP32 Tensilica Xtensa LX6 (32-bit) 240 MHz 255.05 250.49 398.47 75.14 756.14
ESP32-S3 Tensilica Xtensa LX7 (32-bit) 240 MHz 199.44 190.14 361.17 62.62 702.66
STM32H7 ARM Cortex-M7 (32-bit) 480 MHz 44.76 36.85 45.81 23.36 238.10

FFT Throughput (higher is better)

Values represent total FFT operations computed per second (FFT/s).

Microcontroller int8_t int16_t int32_t float double
Arduino Nano 241 102 34 58 N/A
UNO R4 1,364 1,497 902 2,771 247
STM32F411 3,141 3,517 2,805 6,583 576
RP2040 4,381 4,379 2,118 1,064 598
ESP32 3,921 3,992 2,510 13,308 1,323
ESP32-S3 5,014 5,259 2,769 15,971 1,423
STM32H7 22,341 27,141 21,827 42,808 4,200

IFFT Master Comparison Tables

IFFT Calculation Latency (lower is better)

Values are in microseconds (µs) per single N=64 Inverse FFT calculation.

Microcontroller Core Architecture Clock Speed int8_t int16_t int32_t float (32-bit) double (64-bit)
Arduino Nano AVR ATMega328P (8-bit) 16 MHz 4,033.66 9,302.30 26,380.36 18,900.00 N/A
UNO R4 ARM Cortex-M4 (32-bit) 48 MHz 741.59 652.91 1,084.73 384.70 4,415.17
STM32F411 ARM Cortex-M4 (32-bit) 100 MHz 312.65 280.38 336.16 163.91 1,878.80
RP2040 ARM Cortex-M0+ (32-bit) 133 MHz 219.27 224.29 464.54 967.96 1,808.77
ESP32 Tensilica Xtensa LX6 (32-bit) 240 MHz 170.51 161.18 195.37 83.29 830.59
ESP32-S3 Tensilica Xtensa LX7 (32-bit) 240 MHz 122.90 107.96 153.10 69.11 776.86
STM32H7 ARM Cortex-M7 (32-bit) 480 MHz 43.65 36.79 39.06 24.32 258.70

IFFT Throughput (higher is better)

Values represent total IFFT operations computed per second (IFFT/s), derived directly from the latencies above (1,000,000 / latency).

Microcontroller int8_t int16_t int32_t float double
Arduino Nano 247 107 37 52 N/A
UNO R4 1,348 1,531 921 2,599 226
STM32F411 3,198 3,566 2,974 6,100 532
RP2040 4,560 4,458 2,152 1,033 552
ESP32 5,864 6,204 5,118 12,006 1,203
ESP32-S3 8,137 9,263 6,532 14,470 1,287
STM32H7 22,910 27,181 25,601 41,118 3,865

Device-by-Device Analysis

🔴 Arduino Nano (AVR ATMega328P @ 16 MHz)

The legacy 8-bit architecture struggles immensely with DSP workloads.

  • Why it’s slow: It has no FPU and no hardware multiplier for larger integers — every 32-bit multiplication must be emulated in software with dozens of assembly instructions.
  • Data-type anomaly: Curiously, float (17,165 µs) is actually faster than int32_t (29,160 µs). The 32-bit float library benefits from 24-bit mantissa optimizations, while full 32-bit integer multiplication and scaling on an 8-bit core requires extensive software-based register shuffling.
  • Practical verdict: Stick to int8_t — or better yet, stick to a different chip for anything beyond toy FFT sizes.

🔵 UNO R4 (Renesas RA4M1 Cortex-M4 @ 48 MHz)

A major modernization of the classic Arduino form factor.

  • FPU power: The Cortex-M4’s single-precision FPU makes float math remarkably quick (360.89 µs) — nearly 11× faster than its software-emulated double math (4,045.90 µs).
  • Its modest 48 MHz clock keeps it behind the other 32-bit boards, but for an entry-level Arduino it is a huge step up from the Nano.

🟣 RP2040 (Cortex-M0+ @ 133 MHz)

The Raspberry Pi silicon lacks a hardware FPU but offers remarkably fast integer execution.

  • Integer strength: It beats the STM32F411 at int8_t and int16_t processing, helped by its higher clock speed (133 MHz vs. 100 MHz).
  • Smart floating-point ROM: Without an FPU, the RP2040 falls back on optimized floating-point routines burned directly into its boot ROM. This keeps its software float (939 µs) and double (1,672 µs) performance respectable — though still far behind hardware-accelerated chips.
  • Practical verdict: This is the one modern board where an integer FFT is clearly the right choice.

🟢 STM32F411 (Cortex-M4 @ 100 MHz)

A well-balanced DSP workhorse.

  • Equipped with ARM’s DSP instruction extensions and a single-precision FPU, it shows exceptionally uniform integer scaling and rapid float speeds (151.90 µs) — roughly 6,500 FFTs per second.

🟠 ESP32 (Xtensa LX6 @ 240 MHz)

A long-time favorite for consumer audio projects — and the benchmark shows why.

  • Single-precision optimization: Thanks to its high 240 MHz clock and an efficient single-precision pipeline, its float FFT is blazingly fast at 75.14 µs (over 13,300 FFTs per second) — beating everything below the STM32H7 by a wide margin.
  • The IFFT speedup: Interestingly, the ESP32 computes integer IFFTs significantly faster than forward FFTs (e.g., the int32_t IFFT takes 195.37 µs vs. 398.47 µs for the FFT), suggesting highly efficient compiler code paths for the backward-scaling butterfly passes of the inverse algorithm.

⚡ ESP32-S3 (Xtensa LX7 @ 240 MHz)

The measurements highlight the real-world benefits of the upgraded LX7 core.

  • Upgraded instruction set: The S3 features PIE (Processor Instruction Extensions), adding hardware-level vector processing capability.
  • The float champ (below 480 MHz): At 62.62 µs per floating-point FFT — nearly 16,000 computations per second — the ESP32-S3 is a formidable chip for real-time edge audio processing, DSP filtering, and spectrum analysis.
  • Integer IFFT beast: It processes the int16_t IFFT in just 107.96 µs, an outstanding 9,263 IFFTs per second.

👑 STM32H7 (Cortex-M7 @ 480 MHz)

The undisputed performance benchmark of this lineup.

  • Hardware double precision: As the only chip tested with a double-precision hardware FPU, it computes double FFTs (238.10 µs) faster than the Arduino Nano or RP2040 can handle simple int8_t math!
  • Blazing clock: Its 480 MHz superscalar, L1-cached pipeline cranks out 42,808 float FFTs every second.

Conclusions

  • If you need FFTs, choose a microcontroller with an FPU. On every FPU-equipped board tested, single-precision float was the fastest data type — often by a wide margin — while also being the easiest to work with (no scaling or overflow management).
  • Integer FFTs only make sense on FPU-less chips such as the RP2040 or the old AVR boards, where int8_t/int16_t processing is 3–4× faster than software floats.
  • Avoid double on Microcontrollers: .floats are at least 10 times faster
  • Best value for real-time audio: The ESP32-S3 delivers nearly 16,000 float FFTs per second at a fraction of the cost of an STM32H7 board — plus built-in Wi-Fi and Bluetooth.

The full source code, benchmark sketches, and raw results are available in the fixedpoint-fft repository on GitHub.

Categories: Arduino

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *