Accélérer la vision par ordinateur avec SIMD sur un ESP32-S3 à 2 $
(shraiwi.github.io)- Le détecteur de features FAST est accéléré grâce aux instructions SIMD 128 bits de l’ESP32-S3 à bas coût, traitant une frame QVGA (320×240) en environ 6 ms
- Cette puce est un microcontrôleur doté d’un CPU double cœur jusqu’à 240 MHz, du WiFi et du Bluetooth Low Energy, et son manuel de référence technique inclut une prise en charge SIMD limitée
- Le cœur de l’implémentation consiste à traiter 16 pixels 8 bits à la fois dans le pre-test des corners FAST, tout en contournant les lectures non alignées et les contraintes de comparaison signée
- Pour adapter les pixels unsigned 8-bit aux comparaisons signées, les valeurs sont transformées par XOR avec 0x80 en utilisant la propriété
x - 128 == x ^ 0x80 - Le débit de test passe de 5,1 MP/s à 11,2 MP/s, atteignant un niveau permettant aussi de traiter un flux VGA à 30 fps sur ESP32-S3
Accélération du détecteur de features FAST sur ESP32-S3
- Un détecteur de features FAST accéléré par SIMD a été implémenté pour l’ESP32-S3, avec des performances environ deux fois supérieures à l’implémentation de référence
- Le traitement d’une frame QVGA (320×240) prend environ 6 ms
- L’ESP32-S3 est un microcontrôleur bon marché, mais il intègre un CPU double cœur jusqu’à 240 MHz ainsi que le WiFi et le Bluetooth Low Energy
- Le manuel de référence technique de l’ESP32-S3 permet de confirmer la prise en charge limitée des instructions SIMD
Instructions SIMD moins connues et préparation de l’implémentation
- Les instructions SIMD de l’ESP32-S3 ne sont pas une fonctionnalité secrète, mais elles restent relativement peu connues
- Les exemples de référence disponibles se résument à trois sources
- Le blog de Larry Bank : exploration des fonctionnalités et exemple minimal
esp-dsp: bibliothèque Espressif utilisée pour des fonctions de type DSP comme la convolution et la FFTesp-dl: bibliothèque Espressif utilisée pour l’accélération IA sur puce
- Pendant l’implémentation, la structure de base de l’assembleur ESP32-S3 a été assimilée, et un allocateur de registres de base maison,
basm, a également été écrit
Mode de traitement SIMD du pre-test des corners FAST
- Le pre-test des corners du détecteur de features FAST échantillonne les pixels dans les directions est, ouest, sud et nord afin de vérifier s’il existe au moins 3 pixels « extrêmes »
- Ici, un pixel extrême est un pixel dont la différence absolue avec le pixel central dépasse un certain seuil
- Chaque registre vectoriel pouvant stocker 16 valeurs 8 bits, l’implémentation est organisée pour calculer l’extrema count de 16 pixels à la fois
- Dans chacune des directions est, ouest, sud et nord, quatre chunks de pixels sont échantillonnés puis comparés aux pixels centraux correspondants
Contraintes du SIMD de l’ESP32-S3 et contournements
- La première contrainte est que l’ISA n’autorise pas les lectures misaligned directes
- En supposant que les pixels centraux soient alignés, les blocs à l’est et à l’ouest ne le sont pas
- Les blocs est et ouest sont obtenus avec une instruction qui concatène deux registres adjacents puis extrait une slice
- La deuxième contrainte est que l’ESP32-S3 n’implémente que des comparaisons signed 8-bit
- Les données de pixels étant stockées en unsigned 8-bit, les interpréter telles quelles en signed mappe non linéairement la plage
[128, 255]vers[-128, -1] - Dans cet état, les opérations de comparaison ne fonctionnent pas correctement
- Les données de pixels étant stockées en unsigned 8-bit, les interpréter telles quelles en signed mappe non linéairement la plage
Adapter les pixels unsigned aux comparaisons signées
- Les valeurs de pixels doivent être déplacées de
[0, 255]vers[-128, 127]pour que les comparaisons et l’arithmétique aient un sens - On pourrait penser qu’il suffit de soustraire 128, mais toutes les opérations arithmétiques SIMD de l’ESP32-S3 sont en saturating arithmetic, ce qui pose problème
- Les valeurs de pixels supérieures à 127 ne provoquent pas d’underflow correct et sont clampées à
-128
- Les valeurs de pixels supérieures à 127 ne provoquent pas d’underflow correct et sont clampées à
- La solution consiste à soustraire 128 en parallèle sans instruction de soustraction
- En signed 8-bit, le bit de poids fort a pour valeur de position
-128 x - 128revient à inverser le bit de poids fort- La relation
x - 128 == x ^ 0x80est donc exploitée
- En signed 8-bit, le bit de poids fort a pour valeur de position
- À chaque chargement de valeurs unsigned 8-bit, elles sont combinées par XOR avec
0x80afin de les convertir dans une plage linéaire exploitable pour l’arithmétique et les comparaisons
Résultats de performance et possibilité de traitement temps réel
- Les deux techniques de contournement ont permis d’implémenter un pre-test des corners FAST accéléré par SIMD
- Une scoring function accélérée par SIMD a également été écrite avec une combinaison d’opérations similaire, mais les détails ne sont pas abordés
- Lors des tests, le débit du détecteur de features FAST est passé de 5,1 MP/s à 11,2 MP/s
- Le débit atteint environ 220 % du niveau précédent
- Ces performances se situent dans une plage acceptable pour les tâches de vision par ordinateur en temps réel et permettent à l’ESP32-S3 de traiter facilement un flux VGA à 30 fps
1 commentaires
Avis sur Hacker News
Parce que les grandes entreprises exploitent les plantations locales et maintiennent de fait des monopoles régionaux, forçant les producteurs à leur vendre à des prix bien inférieurs à la valeur réelle
Des pays du monde entier achètent ce genre d’objets par milliards pour surveiller leurs citoyens, et Big Brother crée ainsi d’énormes économies d’échelle
Ça ressemble à une sorte de Zynq d’entrée de gamme pour la vision par ordinateur
https://wiki.sipeed.com/hardware/en/tang/Tang-Nano-4K/Nano-4...
https://www.aliexpress.us/item/3256806880637138.html
La variante S3 justifie largement son léger surcoût, car avec le SIMD et la FPU, elle est facilement plusieurs fois plus rapide, dans un facteur à un chiffre
https://github.com/espressif/esp-dl/tree/master/examples/fac...
Une détection de personne en 54 ms, c’est impressionnant : https://github.com/espressif/esp-tflite-micro?tab=readme-ov-...
Nous travaillons directement avec plusieurs fournisseurs pour optimiser à bas niveau des tâches de deep learning, de vision par ordinateur et de traitement numérique du signal sur des dizaines de microcontrôleurs et d’architectures CPU, des accélérateurs spécialisés (y compris le calcul neuromorphique) et des GPU edge
L’ESP32 est également inclus : https://docs.edgeimpulse.com/docs/edge-ai-hardware/mcu/espre...
Si vous téléversez des modèles TensorFlow, PyTorch ou JAX, vous pouvez récupérer immédiatement une bibliothèque C++ optimisée avec quelques lignes de Python sur votre ordinateur portable, ce qui est assez bluffant
Il y a aussi un Studio pour entraîner des modèles, ainsi qu’une optimisation d’hyperparamètres consciente du matériel, qui trouve le meilleur modèle en fonction d’architectures conçues pour bien tourner sur divers matériels embarqués et des contraintes de latence et d’utilisation mémoire du dispositif cible
Features from accelerated segment test : https://en.wikipedia.org/wiki/Features_from_accelerated_segm...
Je me demande s’il y a des fonctionnalités proches d’un TPU même sur des puces de cette gamme de prix
Neon est une extension d’instructions SIMD optionnelle d’ARMv7 et ARMv8, donc à partir du Pi Zero il existe des extensions SIMD
Si je comprends bien, l’Orin Nano atteint 40 TOPS, ce qui suffit pour Copilot+. "A PCIe Coral TPU Finally Works on Raspberry Pi 5" https://news.ycombinator.com/item?id=38310063
Selon https://phys.org/news/2024-06-infrared-visible-device-2d-mat..., une longueur d’onde infrarouge de 1550 nm a été convertie vers le haut en lumière visible à 622 nm, et l’onde lumineuse de sortie peut être détectée par les caméras classiques à base de silicium
Comme ce processus conserve la cohérence, si l’on inscrit un motif particulier dans la fréquence infrarouge d’entrée, il serait automatiquement transféré vers la nouvelle fréquence de sortie
"Show HN: PicoVGA Library – VGA/TV Display on Raspberry Pi Pico" https://news.ycombinator.com/item?id=35117847#35120403
https://news.ycombinator.com/item?id=40275530
"Designing a SIMD Algorithm from Scratch" https://news.ycombinator.com/item?id=38450374
Les instructions SIMD de l’ESP32-S3 semblent avoir été conçues pour accélérer l’inférence de modèles d’IA quantifiés (https://github.com/espressif/esp-dl), avec aussi du traitement du signal comme les FFT
Dans le sens où il existe des instructions spécifiques aidant l’inférence ML, on pourrait dire que cela ressemble à un TPU. Par exemple, EE.VRELU.Sx effectue une opération ReLU
Cela dit, utiliser ces instructions consomme toujours du temps CPU, et comme un TPU fonctionne généralement de façon asynchrone sur un cœur de traitement séparé, c’est plus proche d’ARM NEON
Le logiciel et la documentation étaient plutôt bien faits, mais il n’a malheureusement pas réussi à se diffuser largement
Aujourd’hui, on trouve facilement des cartes de développement bon marché basées sur RV1103 (« LuckFox »), BL808 (« Ox64/Pine64 ») ou CV1800B/SG20002 (« MilkV »), qui disposent toutes d’un équivalent basique de TPU
Mais comme elles sont conçues comme des cartes Linux, tout ce qui concerne le TPU y est extrêmement abstrait et la documentation interne est quasiment inexistante, si bien qu’il est impossible de savoir s’il s’agit vraiment d’un TPU ou d’une imitation via de bonnes optimisations de code
À première vue, MicroPython semble assez accessible, et je me demande s’il serait facile de porter ce code vers WebAssembly
Pour les cas d’usage sur appareil, on peut l’essayer sur https://micropython.org/unicorn/
Pour le développement côté client, il peut être utilisé dans PyScript, avec aussi un pont JavaScript/DOM
https://pyscript.net/tech-preview/micropython/about.html
D’après mon expérience, le no-std de Rust sur ESP32 n’est pas mauvais non plus, mais les parties qui s’interfacent avec des composants comme le Wi-Fi, le réseau ou la caméra sont encore moins abouties
Comme dans d’autres commentaires, la prise en charge du SIMD et de l’assembleur en Rust est tout à fait suffisante
Avant de se lancer sérieusement, il vaudrait mieux poser la question dans un salon de discussion Rust embedded ou Rust ESP32
En intégrant beaucoup de SIMD avec du SMT-4 ou SMT-8, les threads pourraient masquer la latence, ce qui pourrait améliorer le rapport performances/surface