Criando um LLM embarcado com entradas em tempo real usando ESP32-S3 e Flash de 16MB
TuBrief 편집팀
2026년 8월 12일
0
Computing/Software원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
커뮤니티의 다른 글
댓글 (0)
Log in to leave a comment
아직 작성된 글이 없습니다
원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
Log in to leave a comment
아직 작성된 글이 없습니다
Decidir rodar um modelo de linguagem de 28,9 milhões de parâmetros em uma placa ESP32-S3 de 8 dólares rapidamente traz uma sensação de impasse. O modelo que roda perfeitamente em vídeos de demonstração simplesmente trava assim que encontra os periféricos de hardware que você criou. Com apenas 512KB de SRAM e a necessidade de regravar uma partição de 15MB a cada alteração de frase, o desenvolvimento rapidamente se torna frustrante. Para superar essas restrições e construir um dispositivo que funcione recebendo entradas de teclado reais, você precisa projetar o cache de memória e os buffers de E/S de forma totalmente diferente desde o início.
Perder tempo gravando a placa novamente só para mudar uma frase de teste é um desperdício. Ao vincular interrupções UART assíncronas e semáforos FreeRTOS, você elimina a necessidade de reiniciar a placa. Cada frase digitada no monitor serial ou no teclado é compreendida instantaneamente pelo modelo.
Essa configuração reduz o tempo gasto na modificação e teste de prompts em mais de 80%.
`
+------------------+ +-------------------+ +--------------------+
| 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 a estrutura Per-Layer Embeddings (PLE) proposta pelos pesquisadores do Google Gemma 3n, podemos dividir e acomodar um modelo de 14,9MB reduzido para 4 bits. A tabela de embeddings, que alcança 25 milhões de parâmetros, fica na flash SPI de 16MB, enquanto os pesos do Output Head (3,1 milhões de parâmetros) e o cache KV ficam na PSRAM de 8MB. Apenas o Dense Compute Core de 559K parâmetros mais utilizado e o buffer Hot Activation são armazenados na SRAM de 512KB.
Aumentar a velocidade para mais de 14 tokens por segundo é mais complicado do que parece.
__attribute__((noinline)) diretamente à função de cálculo matvec_i8_range. Se o compilador realizar a in-lining por conta própria, ocorrerão falhas de cache I-RAM e o tempo de computação despencará de 94,9 ms para 155.2 ms.Ao apenas fazer a portabilidade pura em linguagem C, obtemos uma velocidade desanimadora de 0,57 tokens por segundo. No entanto, após concluir o staging INT8 e o prefetch na SRAM, ultrapassamos 14,0 tokens por segundo.
| Estágio de Otimização | Latência de cálculo por token | Tokens gerados por segundo | Principais tecnologias aplicadas |
|---|---|---|---|
| Portabilidade pura em C (Baseline) | 1.757,2 ms | 0,57 tok/s | Núcleo único, computação FP32 |
| PSRAM Head & Otimização Escalar | 193,9 ms | 4,61 tok/s | Alocação do Output Head na PSRAM |
| Aplicação Dual-Core FP32 | 139,4 ms | 6,22 tok/s | Operação de divisão de camadas em dual-core |
| INT8 Staging + Otimização SRAM | 94,9 ms | 9,88 tok/s | Quantização INT8, aplicação de noinline |
| Expansão do Buffer de Prefetch SRAM | ~71.4 ms | 14,0+ tok/s | Prefetch de camadas iniciais na SRAM |
Manter os dois núcleos rodando continuamente com um clock de 240MHz faz o consumo de corrente disparar para 210mA (777mW). Além de aquecer a placa, isso esgota a bateria rapidamente. Você precisa usar o comando esp_pm_configure para reduzir o clock para 40MHz e ativar o light sleep automático quando não houver inferência em execução.
esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_ON). Mesmo entrando no estado de sleep, a alimentação da flash SPI e da RAM deve ser mantida para evitar a perda de dados.Se você continuar executando inferências continuamente com uma bateria de polímero de lítio de 3,7V e 1000mAh, ela durará apenas 4,7 horas. No entanto, no modo de espera em light sleep, a corrente cai drasticamente para 0,24mA (0,88mW). Em ambientes de uso real com tempos de espera intercalados, a corrente média é mantida na faixa de 15 a 30mA, triplicando ou mais a autonomia da bateria.