Créer un LLM on-device avec saisie en temps réel sur ESP32-S3 et flash de 16 Mo
TuBrief 편집팀
2026년 8월 12일
0
Computing/Software원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
커뮤니티의 다른 글
댓글 (0)
Log in to leave a comment
아직 작성된 글이 없습니다
원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
Log in to leave a comment
아직 작성된 글이 없습니다
Tenter de faire tourner un modèle de langage de 28,9 millions de paramètres sur une carte ESP32-S3 à 8 dollars mène rapidement à une impasse. Un modèle qui fonctionne à merveille dans une vidéo de démonstration se bloque instantanément dès qu'on le confronte aux périphériques matériels de notre propre conception. Avec seulement 512 Ko de SRAM, et l'obligation de reflasher une partition de 15 Mo à chaque modification de phrase, le développement devient vite exaspérant. Pour surmonter ces contraintes et construire un appareil capable de fonctionner avec de véritables saisies au clavier, il faut repenser entièrement la mise en cache de la mémoire et les tampons d'E/S.
Perdre son temps à reflasher la carte juste pour modifier une phrase de test est une impasse. En combinant les interruptions UART asynchrones et les sémaphores FreeRTOS, il n'est plus nécessaire de redémarrer la carte. Chaque phrase saisie via le moniteur série ou le clavier est immédiatement comprise par le modèle.
Cette configuration permet de réduire de plus de 80 % le temps consacré à la modification et au test des prompts.
`
+------------------+ +-------------------+ +--------------------+
| External UART | ---> | HW FIFO Buffer | ---> | SW Ring Buffer |
| (Keypad/Monitor) | | (120 Bytes) | | (2048 Bytes) |
+------------------+ +-------------------+ +--------------------+
|
v
+------------------+ +-------------------+ +--------------------+
| LLM Forward Pass | <--- | xPromptSemaphore | <--- | BTK1 Tokenizer |
| (Inference Task) | | (Binary Lock) | | (43,056 B Library) |
+------------------+ +-------------------+ +--------------------+
`
En adoptant l'architecture Per-Layer Embeddings (PLE) proposée par les chercheurs de Google Gemma 3n, il est possible de fractionner et d'embarquer un modèle de 14,9 Mo réduit à 4 bits. La table d'embeddings, qui atteint 25 millions de paramètres, est placée dans la mémoire flash SPI de 16 Mo, tandis que les poids de la tête de sortie (Output Head - 3,1 millions de paramètres) et le cache KV résident dans la PSRAM de 8 Mo. Seuls le cœur de calcul dense (Dense Compute Core) de 559 Ko le plus sollicité et le buffer Hot Activation sont stockés dans la SRAM de 512 Ko.
Faire grimper la vitesse au-delà de 14 tokens par seconde s'avère plus ardu que prévu.
__attribute__((noinline)) à la fonction de calcul matvec_i8_range. Si le compilateur procède à un inlining automatique, des défauts de cache I-RAM surviennent et font chuter drastiquement le temps de calcul, qui passe de 94,9 ms à 155.2 ms.Un simple portage en langage C se solde par une vitesse désespérante de 0,57 token par seconde. En revanche, combiné au staging INT8 et au préchargement SRAM, le système dépasse les 14,0 tokens par seconde.
| Étape d'optimisation | Latence de calcul par token | Tokens générés par seconde | Principales technologies appliquées |
|---|---|---|---|
| Portage C pur (Baseline) | 1 757,2 ms | 0,57 tok/s | Monocœur, calcul FP32 |
| PSRAM Head & Optimisation scalaire | 193,9 ms | 4,61 tok/s | Placement de l'Output Head en PSRAM |
| Application FP32 multicœur | 139,4 ms | 6,22 tok/s | Calcul et division par couche multicœur |
| Staging INT8 + Optimisation SRAM | 94,9 ms | 9,88 tok/s | Quantification INT8, application de noinline |
| Extension du buffer de préchargement SRAM | ~71,4 ms | 14,0+ tok/s | Préchargement SRAM des premières couches |
Faire tourner les deux cœurs en continu à une fréquence d'horloge de 240 MHz fait grimper la consommation de courant jusqu'à 210 mA (777 mW). Outre la surchauffe de la carte, la batterie se vide en un clin d'œil. La commande esp_pm_configure permet d'abaisser la fréquence à 40 MHz en l'absence d'inférence et d'activer la veille légère automatique.
esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_ON). Même en état de veille, l'alimentation de la mémoire flash SPI et de la RAM doit être maintenue pour éviter toute perte de données.Une batterie lithium-polymère de 3,7 V et 1000 mAh ne tiendra que 4,7 heures en cas d'inférence ininterrompue. En revanche, en mode veille légère, la consommation chute brutalement à 0,24 mA (0,88 mW). Dans un scénario d'utilisation réelle alternant avec des temps d'attente, le courant moyen se maintient entre 15 et 30 mA, prolongeant l'autonomie de la batterie par un facteur supérieur à trois.