8月3日、CNX Softwareが「28.9M-parameter LLM runs locally on ESP32-S3 at 9 tokens/s」と題した記事を公開した。この記事では、約10ドルのESP32-S3マイコン上で2,890万パラメータのLLMをローカル動作させることに成功した個人プロジェクトについて詳しく紹介されている。
ESP32-S3単体でLLMを動かす
開発者のSlava S.(slvDev)は、ESP32-S3搭載の開発ボード1枚の上でLLMを完全にローカル動作させ、約9トークン/秒でテキスト生成(短編ストーリーの生成)を実現した。
ESP32-S3は、Xtensa LX7デュアルコアを最大240MHzで駆動できるマイコンだ。Wi-Fi・Bluetoothを内蔵しつつ消費電力を抑えたIoT向けチップとして広く普及しているが、LLM推論を単体でこなすには非常に非力な部類に入る。512KB SRAMという搭載メモリの少なさは、数百MB〜数GBのメモリを当然のように要求する通常のLLM実行環境とは桁違いの制約だ。
ESP32-S3とLLMの組み合わせ自体は過去にも見られたが、これまでの多くのプロジェクトはESP32-S3をクラウド上のLLMサーバーへの低消費電力ゲートウェイとして使うものだった。HiWonder WonderLLM、ESP-Clawフレームワーク、ESP32 Agent Dev Kitなどがその例だ。Slavaの「esp32-ai」プロジェクトはそれらと根本的に異なり、推論処理のすべてがESP32-S3の上で完結する。
ハードウェア構成は次のとおりだ:
- 価格:約8ドルのESP32-S3ボード
- メモリ:512KB SRAM + 8MB PSRAM
- ストレージ:16MB フラッシュ
- 出力先:小型I2Cディスプレイ(生成したショートストーリーを表示)
モデルファイルは4bit量子化で14.9MB。16MBフラッシュにギリギリ収まるサイズだ。
「どうメモリに収めるか」が最大の工夫
先行事例として、Dave BennetのESP32-LLMプロジェクトがある。ただしこちらは26万パラメータのモデルに留まっており、今回の2,890万パラメータとは桁が異なる。
Slavaがこの差を埋めた鍵は、埋め込みテーブル(embedding table)の扱い方にある。
言語モデルのパラメータの大半は埋め込みテーブルに集中しており、このプロジェクトでは埋め込みテーブルだけで約2,500万パラメータを占める(全2,890万パラメータのうちの大部分にあたる)。これをすべて高速なSRAMに載せようとすれば、ESP32-S3の512KB SRAMはとうてい足りない。そこでSlavaは発想を転換し、埋め込みテーブルを低速なフラッシュに置いたままにした。
各トークンの処理に実際に必要なエントリは少数(約6行、約450バイト)に過ぎない。その分だけをトークンごとにフラッシュから読み出してSRAMに展開すれば、巨大なテーブルをSRAMに常駐させる必要がなくなる。ただし、フラッシュはSRAMと比べて読み出し速度が遅く、このフラッシュアクセスがスループットのボトルネックになる。ESP32-S3では内部フラッシュへのアクセスにXIPキャッシュを利用できるが、それでもSRAMアクセスと比べれば遅延は大きい。元記事では、約9トークン/秒という値はこのフラッシュ読み出し制約を含む実測値として示されているが、クロック周波数やキャッシュの詳細な設定条件については元記事のGitHubリポジトリおよびRedditスレッドを参照してほしい。
このアイデアの出所は、GoogleがGemma 3n / Gemma 4で採用したPer-Layer Embeddingsという手法だ(Googleの公式発表はGoogle Developers Blogでも確認できる。手法の詳細な解説としてはSebastian Raschkaによるアーキテクチャ解説記事も参考になる)。
結果として、メモリの役割分担は次のように整理されている:
| 領域 | 役割 |
|---|---|
| SRAM(高速・小容量) | 推論の「思考」コア。全トークン処理で使用 |
| PSRAM(中速) | 出力ヘッドとワーキングメモリ |
| フラッシュ(低速・大容量) | 埋め込みテーブル(約2,500万パラメータ分)。トークンごとに約450バイトを読み出し |
実用的なLLMではない
記事では率直に「これは工学的な達成であり、実用的なLLMプロジェクトではない」と述べられている。モデルはTinyStoriesというデータセットで訓練されており、短くシンプルなストーリーを生成することだけを目的としている。
- 質問への回答はできない
- 指示への追従はできない
- コード生成はできない
通常のLLMに期待するような機能は一切持たない。あくまで「ESP32-S3単体でここまでできる」という技術実証だ。
ソースコードと解説
ソースコード・セットアップ手順・詳細な実験結果はGitHubで公開されている。また、Redditのスレッドにも追加情報が投稿されている。動作の仕組みを視覚的に確認したい場合は、元記事に掲載されているデモ動画が参考になる。
詳細は28.9M-parameter LLM runs locally on ESP32-S3 at 9 tokens/sを参照していただきたい。
