ESP-NN

September 22, 2026 ยท View on GitHub

The library contains optimised NN (Neural Network) functions for various Espressif chips.

  • Supported platforms:

    • TensorFlow Lite Micro (TFLite Micro). Repo can be found here
  • Supported ESP chips include:

    • ESP32-S3 (Assembly versions optimised to benefit from vector instructions of ESP32-S3)
    • ESP32-P4 (Optimised using PIE/QACC SIMD instructions)
    • ESP32-S31 (Optimised using PIE/QACC SIMD instructions, shares ESP32-P4 kernels)
    • ESP32 (Generic optimisations)
    • ESP32-C3 (Generic optimisations)

Performance

Kernelwise performance for s8 versions:

  • Kernelwise performance on ESP32-P4 chip

    • Numbers are ticks taken for kernel to execute
    • Chip config: 360MHz, SPI-RAM: HEX 200MHz, L2-Cache: 128KB
    FunctionANSI COptimizedOpt RatioData infoMemory
    elementwise_add190786884512.16size = 1615External
    elementwise_mul76585476011.60size = 1615External
    convolution40055125724597.00input(10,10), filter(64x1x1x64), pad(0,0), stride(1,1)External
    convolution249700711043.51input(8,8), filter(16x1x1x16), pad(0,0), stride(1,1)External
    convolution8169755333181.53input(10,10), filter(64x3x3x3), pad(0,0), stride(1,1)External
    depthwise conv9628344823892.00input (16, 16), pad(0,0), stride(1,1) filter: 1x3x3x16External
    depthwise conv13650667039891.94input (12, 12), pad(1,1), stride(1,1) filter: 8x5x5x4External
    max pool4821842417819.94input(16,16), filter (1x3x3x16)Internal
    avg pool303210844013.59input(16,16), filter (1x3x3x16)Internal
    fully connected76509158.36len: 271, ch = 3Internal
    prelu (relu6)11951547.76size, 1615Internal
    softmax1426085871.66width: 256Internal
    hard_swish7039705165821.36size: 12544External
    mean1011346862.167x7x16Internal
  • Kernelwise performance on ESP32-S31 chip

    • Numbers are ticks taken for kernel to execute
    • Chip config: 320MHz, data in internal memory
    • Note: on ESP32-S31 the PIE coprocessor is available on core 1 only; tasks using optimized kernels are automatically migrated to core 1 by ESP-IDF
    FunctionANSI COptimizedOpt RatioData infoMemory
    elementwise_add196283750322.62size = 1615Internal
    elementwise_mul83337457651.82size = 1615Internal
    convolution41077876581486.24input(10,10), filter(64x1x1x64), pad(0,0), stride(1,1)Internal
    convolution277008942102.94input(8,8), filter(16x1x1x16), pad(0,0), stride(1,1)Internal
    convolution17983907657082.35input(8,8), filter(64x3x3x3), pad(0,0), stride(1,1)Internal
    depthwise conv3152011189442.65out(10,10), pad(1,1), stride(1,1), filter: 1x3x3x16Internal
    depthwise conv13252297551161.75out(12,12), pad(1,1), stride(1,1), filter: 8x5x5x4Internal
    max pool2748662172412.65input(16,16), filter(1x3x3x16)Internal
    avg pool297200752573.95input(16,16), filter(1x3x3x16)Internal
    fully connected754714755.11len: 271, ch = 3, non-zero input offsetInternal
    prelu (relu6)6251235.08size: 1615Internal
    softmax1209082251.47h: 8, w: 32Internal
    hard_swish6209504216181.47size: 12544Internal
    mean1044743992.377x7x16Internal
  • Kernelwise performance on ESP32-S3 chip

    • Numbers are ticks taken for kernel to execute
    • Chip config: 240MHz, SPI: QPI 80MHz, Data cache: 64KB
    FunctionANSI COptimizedOpt RatioData infoMemory
    elementwise_add281337744403.78size = 1615External
    elementwise_mul122703350023.51size = 1615External
    convolution471250033100814.24input(10,10), filter(64x1x1x64), pad(0,0), stride(1,1)External
    convolution312754390228.01input(8,8), filter(16x1x1x16), pad(0,0), stride(1,1)External
    convolution21932893948425.55input(8,8), filter(64x3x3x3), pad(0,0), stride(1,1)External
    convolution362880468387.75input(8,8), filter(16x3x3x16), pad(0,0), stride(2,2), SAMEInternal
    depthwise conv11598311841766.30input(18,18), pad(0,0), stride(1,1), filter: 1x3x3x16External
    depthwise conv16713633724354.49input(12,12), pad(1,1), stride(1,1), filter: 8x5x5x4External
    depthwise conv1084557821373905.07input (1, 384), pad(0,1), stride(1,1), filter: 1x3x1x128Internal
    depthwise conv541139910709315.05input (1, 192), pad(0,1), stride(1,2), filter: 1x3x1x256Internal
    max pool376294480697.83input(16,16), filter(1x3x3x16)Internal
    avg pool4272931180523.62input(16,16), filter(1x3x3x16)Internal
    fully connected843915435.47len: 271, ch = 3, non-zero input offsetInternal
    softmax15209111071.37h: 8, w: 32Internal
    prelu (relu6)11259811.48size: 1615Internal

Model-level performance:

  • Person Detection (Visual Wake Words, INT8 quantized โ€” from esp-tflite-micro)

    • Numbers are time (ms) for invoke() call, using internal memory
    ChipCPU Freqwithout ESP-NNwith ESP-NN
    ESP32-P4360MHz1395ms73ms
    ESP32-S31320MHz1669ms72ms
    ESP32-S3240MHz2300ms54ms
    ESP32240MHz4084ms380ms
    ESP32-C3160MHz3355ms426ms
  • MobileNetV3 Small (INT8 quantized, 224x224x3, 1000 classes)

    ChipCPU Freqwithout ESP-NNwith ESP-NNwith ESP-NN, dual core
    ESP32-P4400MHz10980ms388ms253ms
    ESP32-S3240MHz26679ms729ms690ms
  • YOLO11n (INT8 quantized, 192x192x3, 80 classes, object detection)

    ChipCPU Freqwithout ESP-NNwith ESP-NNwith ESP-NN, dual core
    ESP32-P4400MHz52240ms620ms417ms
    ESP32-S3240MHz130753ms1253ms1053ms

Note:

  • The above is time taken for execution of the invoke() call
  • SPIRAM used for TensorArena.
  • Person detection on ESP32-S3 with internal RAM: 47ms
  • MobileNetV3 and YOLO11n were measured with the mobilenet_v3 and yolo_test_app examples in esp-tflite-micro, with no profiler attached; ESP32-P4 with 200MHz HEX PSRAM, ESP32-S3 with 80MHz OCT PSRAM and a 64KB data cache
  • The dual core column is with esp_nn_dual_core_enable() called once at startup, which lets the heavier kernels split their work across both cores
  • Without ESP-NN case is when esp-nn is completely disabled by removing below flag from CMakeLists.txt:
      # enable ESP-NN optimizations by Espressif
      target_compile_options(${COMPONENT_LIB} PRIVATE -DESP_NN)
    

Configuration

  • To configure, please use idf.py menuconfig and under ESP-NN select NN_OPTIMIZATIONS

  • There are two options presented:

    • Optimized versions
    • ANSI C
  • Default selection is for Optimized versions. For ESP32-S3, ESP32-P4 and ESP32-S31, assembly versions are automatically selected, whereas for other chips (viz., ESP32, ESP32-C3), generic optimisations are selected.

  • For debugging purposes, you may want to select ANSI C reference versions.

Contributing

If you encounter an issue with ESP-NN, or wish to submit a feature request, please use the Issues section on the Github.

For general questions related to this library, please use the esp32.com forum.

Please check CONTRIBUTING.md for further information if you'd like to contribute to ESP-NN.

Copyrights and License

All original source code in this repository is Copyright (C) 2020-2021 Espressif Systems. This source code is licensed under the Apache License 2.0 as described in the file LICENSE.