2026-08-03

28,9 millions de paramètres dans 512 Ko de RAM : un LLM sur un microcontrôleur à 8 $

AIHardwareOpen Source🌍 Global

Faire tourner un modèle de langage suppose d'ordinaire un GPU doté de dizaines, voire de centaines de gigaoctets de mémoire. Ce projet en exécute un sur un ESP32-S3, un microcontrôleur à 8 $ équipé de 512 Ko de SRAM, 8 Mo de PSRAM et 16 Mo de flash. Le tout entièrement sur la puce, sans la moindre connexion réseau, avec le texte généré affiché sur un petit écran, à environ 9,5 tokens par seconde.

Les petits modèles de langage sur microcontrôleur n'ont rien de nouveau, mais le record précédent plafonnait autour de 260 000 paramètres. Celui-ci en compte 28,9 millions, soit une centaine de fois plus. D'où un problème évident : aucun des niveaux de mémoire de l'ESP32-S3 n'approche, même de loin, la taille nécessaire pour stocker un tel modèle — et encore moins pour le faire tourner.

D'abord, qu'est-ce qu'un « embedding » ?

Pour comprendre l'astuce, il faut voir ce qu'elle remplace. Un modèle de langage ne manipule pas des mots, mais des nombres. La toute première opération appliquée à une entrée est une consultation : le modèle conserve une immense table comportant une ligne par token possible — 32 768 dans le vocabulaire de ce modèle — et chaque ligne contient une courte liste de nombres, l'« embedding » du token, qui le représentera partout ailleurs dans le réseau. C'est un dictionnaire : un token entre, une ligne sort, les 32 767 autres sont ignorées.

Toute la difficulté est de savoir où loger ce dictionnaire. Dans un transformeur classique, la table d'embeddings est une matrice de poids comme les autres, et les poids d'un réseau de neurones sont censés rester en mémoire rapide pendant toute la durée de vie du modèle, puisque n'importe lequel peut en principe intervenir à n'importe quelle étape. La table d'un petit modèle ne pèse parfois que quelques mégaoctets, mais elle grossit avec le vocabulaire, et l'addition monte vite : à lui seul, le vocabulaire de 256 000 tokens de Gemma 3n représente plus d'un gigaoctet, chargé intégralement avant même la moindre étape de raisonnement. C'est exactement ainsi que le blog développeurs de Google introduit le problème que résolvent les PLE.

La solution : une petite table par couche, logée ailleurs et plus lente

Les Per-Layer Embeddings (PLE) constituent le changement d'architecture introduit par Google avec la famille Gemma 3n, dévoilée à Google I/O et pleinement disponible depuis juin 2025. L'idée tient en deux volets, et c'est le second qu'on a tendance à négliger.

Premier volet : au lieu d'un unique embedding par token, consulté une fois à l'entrée puis transporté inchangé à travers toutes les couches, les PLE dotent chaque couche du transformeur de sa propre petite table d'embeddings, distincte, pour le même vocabulaire. Un token ne donne donc plus lieu à une seule consultation, mais à une consultation par couche : chaque couche injecte son propre petit vecteur dans le calcul à mesure que le token progresse, au lieu de faire porter tout le sens par l'embedding d'entrée initial.

Second volet, celui qui économise vraiment de la mémoire : puisque chaque table de couche ne sert jamais qu'à lire une ligne — jamais multipliée, jamais engagée dans un calcul matriciel —, elle n'a pas besoin de résider dans la mémoire rapide réservée aux poids réellement calculés. Une analyse technique indépendante de Gemma 3n donne l'ordre de grandeur : pour le modèle E2B, chacune des 30 couches reçoit un vecteur de 256 nombres par token, soit 30 × 256 = 7 680 valeurs, ce qui, quantifié en 4 bits, tient dans un peu moins de 4 Ko par token. À comparer au chargement d'une table de plus d'un gigaoctet, et l'on comprend pourquoi Google annonce que les modèles E2B et E4B, malgré 5 et 8 milliards de paramètres bruts, tournent avec une empreinte mémoire comparable à celle de modèles de 2 et 4 milliards. Le reste des paramètres, ce sont ces embeddings, diffusés quelques kilooctets à la fois plutôt que maintenus en permanence dans la mémoire de l'accélérateur.

Pourquoi cela convient si bien à un microcontrôleur

Un ESP32-S3 ne présente pas la séparation processeur/accélérateur d'un smartphone, mais il offre exactement celle autour de laquelle les PLE sont pensés : une petite réserve de mémoire rapide (la SRAM), taillée pour le calcul, et une réserve bien plus vaste et bien plus lente (la flash), parfaitement adaptée à des lectures qui n'ont pas besoin d'être rapides. Ce projet applique la même idée à une échelle nettement réduite : 6 couches au lieu de 30, un vecteur de 128 nombres par couche au lieu de 256, et un vocabulaire de 32 768 tokens. Résultat : environ 25 des 28,9 millions de paramètres du modèle résident en flash sous forme de table de correspondance, tandis que seul le cœur de calcul occupe la mémoire rapide.

Diagramme comparant un embedding de token traditionnel, lu une seule fois à l'entrée et nécessitant que la table complète tienne en RAM, aux Per-Layer Embeddings, qui lisent une petite tranche de la table depuis la flash à chacune des six couches du transformeur
NiveauCapacitéContenu
SRAM512 KoLe cœur de calcul, sollicité à chaque token
PSRAM8 MoTête de sortie et mémoire de travail
Flash16 MoLes tables d'embeddings par couche, environ 25 millions de paramètres

À l'inférence, produire un seul token revient à lire 6 lignes dans cette table en flash, une par couche, soit environ 450 octets — et non quoi que ce soit qui approche la structure complète de 25 millions de paramètres. L'auteur résume sa contribution ainsi : porter « les Per-Layer Embeddings façon Gemma sur une hiérarchie SRAM/flash de microcontrôleur », ce qui serait, à sa connaissance, la première adaptation de cette idée à du matériel aussi contraint. Voilà pourquoi un modèle cent fois plus gros tient là où 260 000 paramètres constituaient jusqu'ici le plafond : non pas grâce à une compression plus astucieuse, mais parce que 87 % des paramètres ont été déplacés vers un endroit qui n'avait jamais eu besoin d'être rapide.

Ce qui tient réellement sur la puce

Une fois quantifié en 4 bits, le modèle complet pèse 14,9 Mo, ce qui tient sans peine dans les 16 Mo de flash de l'ESP32-S3, aux côtés du micrologiciel. La génération tourne à environ 9,5 tokens par seconde de bout en bout — 9,7 en calcul pur, d'après les mesures du dépôt —, la sortie s'affichant directement sur l'écran, sans le moindre aller-retour vers le cloud.

Le modèle est entraîné sur le jeu de données TinyStories de Microsoft, ce qui explique très exactement ce qu'il produit : de courtes histoires simples, à la structure raisonnablement cohérente. Il ne répond pas aux questions, ne suit pas d'instructions, n'écrit pas de code et ne connaît aucun fait. Ce n'était pas l'objectif d'entraînement, et rien dans cette architecture ne vise une capacité générale. Il s'agissait de démontrer qu'un modèle deux ordres de grandeur au-dessus du précédent record pouvait tourner, de façon cohérente, sur du matériel aussi limité.

Ce que contient le dépôt

Le dépôt GitHub fournit toute la chaîne, et pas seulement un binaire : le micrologiciel ESP32 et les instructions de câblage, le code d'entraînement ayant produit le modèle, le pipeline de quantification qui le ramène à 14,9 Mo, et un rapport de résultats détaillant les ablations et les mesures effectuées sur la puce. Le tout est sous licence MIT : entraînement, quantification et micrologiciel sont donc réutilisables pour d'autres expérimentations sur matériel contraint.