TuBrief
구독 채널
비디오
커뮤니티

On-Device-LLM mit ESP32S3 und 16MB Flash für Echtzeiteingaben erstellen

TuBrief 편집팀
2026년 8월 12일
0
Computing/Software

원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.

Deutsch한국어中文العربيةEspañolEnglishFrançaisहिन्दीPortuguêsРусскийBahasa Indonesia日本語

관련 영상

Dieser 8-Dollar-Mikrocontroller führt ein Sprachmodell lokal aus!8:14

Dieser 8-Dollar-Mikrocontroller führt ein Sprachmodell lokal aus!

Better Stack

커뮤니티의 다른 글

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

2026년 9월 13일

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

2026년 9월 13일

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

2026년 9월 13일

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

2026년 9월 13일

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

2026년 9월 12일

Apple Won the AI Race

2026년 9월 12일

댓글 (0)

Log in to leave a comment

아직 작성된 글이 없습니다

© 2026 . All rights reserved.

TuBrief
구독 채널
비디오
커뮤니티
로그인

On-Device-LLM mit ESP32S3 und 16MB Flash für Echtzeiteingaben erstellen

Wer beschließt, ein Sprachmodell mit 28,9 Millionen Parametern auf einem 8-Dollar-ESP32-S3-Board laufen zu lassen, steht schnell vor einer Wand. Modelle, die im Demo-Video reibungslos funktionieren, blockieren sofort, sobald sie auf selbst gebaute Hardware-Peripheriegeräte treffen. Bei nur 512 KB SRAM und der Notwendigkeit, für jede kleine Satzänderung eine 15-MB-Partition neu zu flashen, ist Frustration bei der Entwicklung vorgrammiert. Um diese Einschränkungen zu überwinden und ein Gerät zu bauen, das tatsächlich auf Tastenfeldeingaben reagiert, müssen Speicher-Caching und E/A-Puffer von Grund auf neu konzipiert werden.

Prompts über Serial injizieren, ohne jedes Mal neu zu flashen

Das Board für jeden Test eines einzelnen Satzes neu zu flashen, ist reine Zeitverschwendung. Durch die Kopplung von asynchronen UART-Interrupts und FreeRTOS-Semaphoren ist ein Neustart des Boards nicht erforderlich. Das Modell versteht Sätze sofort, sobald sie über den seriellen Monitor oder ein Tastenfeld eingegeben werden.

  1. Weisen Sie die GPIO-Pins 16/17 dem Port UART_NUM_2 zu, setzen Sie die Hardware-FIFO-Schwelle auf 120 Bytes und öffnen Sie den Empfangsinterrupt.
  2. Richten Sie einen 2048-Byte-Ringpuffer im internen SRAM ein. Dies verhindert Datenüberläufe und Systemabstürze während laufender Inferenzberechnungen.
  3. Fügen Sie einen Streaming-Parser hinzu, der Zeilenumbruchzeichen erkennt, und konvertieren Sie den Eingabetext mit einer 43.056 Bytes großen BTK1-Encoder-Bibliothek direkt in ein Token-ID-Array.
  4. Richten Sie das doppelte Semaphore xPromptSemaphore ein. Sobald der Empfangs-Task das Schreiben der Token abgeschlossen hat und xSemaphoreGive aufruft, erhält der wartende Inferenz-Task über xSemaphoreTake die Speichersperre und startet die Berechnung.

Mit dieser Konfiguration lässt sich der Zeitaufwand für Prompt-Änderungen und Tests um über 80% reduzieren.

`
+------------------+ +-------------------+ +--------------------+
| 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) |
+------------------+ +-------------------+ +--------------------+

`

Per-Layer Embedding Sharding und SRAM Caching für eine Geschwindigkeit von 14 Token

Die von den Forschern von Google Gemma 3n vorgeschlagene Per-Layer-Embeddings-Architektur (PLE) ermöglicht es, ein auf 4 Bit reduziertes 14,9-MB-Modell aufzuteilen und zu laden. Die Embedding-Tabelle mit 25 Millionen Parametern wird im 16-MB-SPI-Flash gespeichert, während die Output-Head-Gewichte (3,1 Millionen Parameter) und der KV-Cache im 8-MB-PSRAM abgelegt werden. Lediglich der am häufigsten genutzte Dense Compute Core mit 559.000 Parametern und der Hot-Activation-Puffer werden im 512-KB-SRAM untergebracht.

Die Steigerung der Geschwindigkeit auf über 14 Token pro Sekunde ist anspruchsvoller als gedacht:

  1. Fügen Sie der Berechnungsfunktion matvec_i8_range unbedingt das Attribut __attribute__((noinline)) hinzu. Wenn der Compiler eigenständig eine Inlining-Optimierung durchführt, kommt es zu I-RAM-Cache-Misses, wodurch sich die Berechnungszeit von 94,9 ms auf 155.2 ms verschlechtert.
  2. Teilen Sie die Operationen ple_model_proj und qkv auf die Dual-Xtensa-LX7-Kerne des ESP32-S3 auf. Die gleichzeitige Nutzung beider Kerne ist für die Zielgeschwindigkeit unerlässlich.
  3. Erweitern Sie den Prefetch-Puffer, um die Embedding-Daten der frühen Layer vorab in den freien SRAM-Bereich zu laden und so den Flash-Speicher-Engpass zu beseitigen.

Bei einer reinen Portierung nach C ergibt sich eine enttäuschende Geschwindigkeit von nur 0,57 Token pro Sekunde. Mit INT8-Staging und SRAM-Prefetching werden jedoch über 14,0 Token pro Sekunde erreicht.

Optimierungsstufe Berechnungsverzögerung pro Token Erzeugte Token pro Sekunde Hauptsächlich angewandte Technologien
Reine C-Portierung (Baseline) 1.757,2 ms 0,57 tok/s Einzelner Kern, FP32-Berechnung
PSRAM Head & Skalar-Optimierung 193,9 ms 4,61 tok/s Platzierung des Output Head im PSRAM
Dual-Core FP32-Anwendung 139,4 ms 6,22 tok/s Aufteilung der Layer-Berechnung auf Dual-Core
INT8 Staging + SRAM-Optimierung 94,9 ms 9,88 tok/s INT8-Quantisierung, Anwendung von noinline
Erweiterung des SRAM-Prefetch-Puffers ~71.4 ms 14.0+ tok/s SRAM-Prefetching für frühe Layer

Steuerung des Light Sleep zur Reduzierung des Stromverbrauchs auf 210 mA

Wenn die Dual-Kerne kontinuierlich mit einem Takt von 240 MHz betrieben werden, steigt der Stromverbrauch auf bis zu 210 mA (777 mW). Abgesehen davon, dass das Board heiß wird, entlädt sich der Akku in kürzester Zeit. Mit dem Befehl esp_pm_configure muss der Takt bei Inaktivität auf 40 MHz gesenkt und der automatische Light-Sleep-Modus aktiviert werden.

  1. Setzen Sie in der Struktur esp_pm_config_esp32s3_t den Wert max_freq_mhz auf 240, min_freq_mhz auf 40 und aktivieren Sie light_sleep_enable (true).
  2. Führen Sie esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_ON) aus. Die Stromversorgung für SPI-Flash und RAM muss auch im Sleep-Modus aufrecht erhalten werden, um Datenverluste zu vermeiden.
  3. Verwenden Sie uart_set_wakeup_threshold und esp_sleep_enable_uart_wakeup, um einen Wiederherstellungsinterrupt einzurichten, der die CPU beim Eintreffen serieller Signale sofort aus dem Sleep-Modus aufweckt.

Bei kontinuierlicher Berechnung mit einem 3,7V 1000mAh Lithium-Polymer-Akku hält das System nur 4,7 Stunden. Im Light-Sleep-Bereitschaftsmodus sinkt der Stromverbrauch jedoch drastisch auf 0,24 mA (0,88 mW). In realen Einsatzszenarien mit gemischten Wartezeiten bleibt der durchschnittliche Stromverbrauch auf einem Niveau von 15 bis 30 mA, wodurch sich die Batterielaufzeit um das Dreifache oder mehr verlängert.