Creación de un LLM en el dispositivo con entrada en tiempo real usando ESP32S3 y 16MB de Flash
TuBrief 편집팀
2026년 8월 12일
0
Computing/Software원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
커뮤니티의 다른 글
댓글 (0)
Log in to leave a comment
아직 작성된 글이 없습니다
원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
Log in to leave a comment
아직 작성된 글이 없습니다
Proponerse ejecutar un modelo de lenguaje de 28.9 millones de parámetros en una placa ESP32-S3 de 8 dólares rápidamente lleva a un callejón sin salida. Un modelo que funciona de maravilla en un video de demostración se bloquea instantáneamente al entrar en contacto con los periféricos de hardware caseros. Con apenas 512KB de SRAM y la necesidad de flashear una partición de 15MB cada vez que se cambia una sola oración, el desarrollo se vuelve frustrante. Para superar estas limitaciones y construir un dispositivo que funcione con entradas de teclado reales, es necesario rediseñar por completo el almacenamiento en caché de memoria y los búferes de E/S desde cero.
Querer cambiar una sola oración de prueba y tener que reflashear la placa es una pérdida de tiempo. Al vincular las interrupciones UART asíncronas y los semáforos de FreeRTOS, se elimina la necesidad de reiniciar la placa. El modelo comprende inmediatamente las oraciones a medida que se escriben desde el monitor serie o el teclado.
Esta configuración permite reducir en más del 80% el tiempo dedicado a modificar y probar 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) |
+------------------+ +-------------------+ +--------------------+
`
Utilizando la estructura de Embeddings por Capa (PLE, por sus siglas en inglés) propuesta por los investigadores de Google Gemma 3n, es posible dividir y alojar un modelo de 14.9MB reducido a 4 bits. La tabla de embeddings, que alcanza los 25 millones de parámetros, se almacena en la memoria flash SPI de 16MB, mientras que los pesos del Output Head (3.1 millones de parámetros) y la caché KV se colocan en la PSRAM de 8MB. El núcleo de cómputo denso (Dense Compute Core) de 559K parámetros de uso más frecuente y el búfer Hot Activation se ubican directamente en la SRAM de 512KB.
Aumentar la velocidad a más de 14 tokens por segundo es más complicado de lo esperado.
__attribute__((noinline)) directamente a la función de operación matvec_i8_range. Si el compilador realiza la inlining por su cuenta, se producen fallos de caché en la I-RAM y el tiempo de cálculo empeora drásticamente, pasando de 94.9ms a 155.2ms.Una simple adaptación a C arroja una velocidad desesperante de 0.57 tokens por segundo. Sin embargo, al completar el almacenamiento en fase INT8 y el prefetch en SRAM, se superan los 14.0 tokens por segundo.
| Etapa de optimización | Latencia por token | Tokens generados por segundo | Tecnologías clave aplicadas |
|---|---|---|---|
| Puerto puro en C (Baseline) | 1,757.2 ms | 0.57 tok/s | Monocúcleo, cálculo FP32 |
| PSRAM Head y optimización escalar | 193.9 ms | 4.61 tok/s | Asignación de Output Head en PSRAM |
| Aplicación de FP32 en doble núcleo | 139.4 ms | 6.22 tok/s | Cálculo dividido por capas en doble núcleo |
| INT8 Staging + Optimización SRAM | 94.9 ms | 9.88 tok/s | Cuantización INT8, aplicación de noinline |
| Ampliación del búfer de prefetch SRAM | ~71.4 ms | 14.0+ tok/s | Prefetch de capas iniciales en SRAM |
Mantener los dos núcleos funcionando continuamente a un reloj de 240MHz dispara el consumo de corriente hasta los 210mA (777mW). Dejando de lado que la placa se calienta, la batería se agota en un abrir y cerrar de ojos. Mediante el comando esp_pm_configure, es necesario reducir la frecuencia del reloj a 40MHz y activar la suspensión ligera automática cuando no hay inferencias.
esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_ON). Es necesario mantener la alimentación de la memoria flash SPI y la RAM incluso al entrar en estado de suspensión para evitar la pérdida de datos.Si se realizan cálculos continuos con una batería de polímero de litio de 3.7V y 1000mAh, esta dura apenas 4.7 horas. Sin embargo, en el modo de espera por suspensión ligera, la corriente cae drásticamente a 0.24mA (0.88mW). En un entorno de uso real que intercala tiempos de espera, la corriente promedio se mantiene en un nivel de 15 a 30mA, lo que multiplica la duración de la batería por más de 3.