AI-LECTURER 速報課|2026-07-27|約 24 分鐘

8美元晶片也能跑AI:拆解『查表資料搬去慢速儲存』的記憶體搬家術

取材:Running a 28.9M parameter LLM on an $8 microcontroller(Hacker News(AI 高人氣))
📍 真實場景
阿凱,做智慧灑水器新創的韌體工程師

正在幫產品加一個『裝置端小助理』功能,老闆說要用既有的8美元ESP32控制板做,不准加錢換更貴的晶片

😖 卡住的地方:他查到的語言模型範例動輒要幾百MB甚至幾GB記憶體,但手上這顆晶片只有512KB SRAM,怎麼算都覺得『這種東西根本塞不進去』,一度以為老闆的要求是天方夜譚
💡 這篇會告訴他:關鍵不是把模型『縮小』,而是把資料『搬到對的地方』——看完他就知道怎麼判斷自己的晶片有沒有機會塞進類似規模的模型

🧭 這到底是什麼(白話版)

有工程師在一顆只要8美元的微控制器(microcontroller)比迷你電腦還簡化的晶片,通常只做特定簡單工作,例如控制家電或感測器,運算能力和記憶體都比手機、電腦小很多——ESP32-S3上,成功跑出一個2890萬參數(parameters)AI模型裡儲存『學到的東西』的數字,參數越多通常代表模型懂得越多,但也需要越多空間存放的語言模型。整個過程不連網,晶片自己一個字一個字把故事寫出來,顯示在旁邊接的小螢幕上,速度大約每秒9個字。

聽起來很基本,但難處在於這顆晶片的SRAM晶片內建、速度最快但容量很小的記憶體,像是隨手可拿的抽屜,存取快但放不下太多東西只有512KB。過去在類似等級的晶片上,人們只能塞進26萬參數的模型,因為傳統做法要求整個模型都要能被快速記憶體隨時讀到,模型稍微大一點,512KB的抽屜根本裝不下。

這次能塞進足足100倍大的模型,關鍵不是把模型『縮小』,而是先看清楚模型裡的資料其實不平等。語言模型有一大塊叫嵌入表(embedding table)AI模型裡把『字』轉換成一串數字的對照表,用來讓電腦讀懂文字的意義,它佔了模型裡大多數的參數,但工作方式只是『查』,不是『算』——生成每個字的時候只需要從表裡挑出幾行來看。既然是用查的,就不必隨時待在快速的SRAM裡,而是可以放進容量大但速度慢的Flash 快閃記憶體容量大但讀取速度較慢的儲存空間,像倉庫,東西放得下但要跑一趟去拿,需要的時候才去挖那幾行,一次大約只挖450位元組。真正需要隨時運算的『思考』核心,體積小很多,才留在SRAM裡。

這個把嵌入表挪去慢速儲存的招式,叫做Per-Layer Embeddings,原本是Google設計給Gemma系列模型用的,目標是讓模型能裝進手機。這次的特別之處,是把同樣的想法套用到比手機記憶體還小上千倍的微控制器上——作者說,據他所知,還沒有人在這麼小的晶片上試過。

🎯 為什麼值得你花時間

邊緣運算不再是理論,是能買到的8美元現實這件事證明的不是『模型能力有多強』,而是『這種規模的AI已經可以塞進最便宜、最常見的控制晶片裡』。對想做智慧家電、穿戴裝置、感測器的工程師來說,這代表以後評估『要不要加AI功能』時,連最陽春的晶片都可能是選項之一,不必每次都跳去更貴的模組或雲端API。
重點是資料放哪裡,不是模型多大整篇文章真正的洞察不是『怎麼把模型變小』,而是『怎麼決定哪些資料該放快速記憶體、哪些該放慢速儲存』。這是一種很通用的工程直覺——資料庫索引、分頁快取、CDN邊緣快取都是同樣的思路,學會辨認『查表型資料』跟『運算型資料』的差別,是可以帶著走的能力。
限制被說得很清楚,才是這篇可信的地方作者老實講這個模型『不會回答問題、不會寫程式』,原因來自負責思考的核心太小、訓練資料也只是簡單故事。這種誠實劃清『技巧解決了什麼、沒解決什麼』的態度,能幫助讀者判斷:哪些場景真的適合套用這招(例如需要裝置端生成簡單文字),哪些場景不該有過高期待(例如要做通用助理)。

⚙️ 它是怎麼運作的

1
先拆開模型看有哪兩塊一個語言模型大致可以拆成兩塊:嵌入表(這個模型裡有2500萬列,佔了大部分參數),以及真正負責『思考』、把讀到的資料組合、推論出下一個字的運算核心,體積小很多。
2
分辨『查表』跟『運算』的不同嵌入表的工作方式是查表——每次只需要從裡面挑出幾行來看,不用整張表一起參與計算;運算核心才是每個字都要動用的部分。這個差別,決定了兩塊資料該放在晶片的哪個角落。
3
把查表型資料丟去慢速大倉庫既然嵌入表只是偶爾被查,就把它整包放進16MB的Flash——容量大但讀取速度慢的儲存空間,平常它就靜靜躺在那裡,不佔用寶貴的SRAM。
4
運算核心留在快抽屜裡真正需要隨時計算的運算核心,體積夠小,可以留在512KB的SRAM裡,確保每個權杖/tokenAI模型處理文字的最小單位,可能是一個字、一個詞或一個符號,生成文字時是一個一個產生的都能被快速存取到。
5
每生成一個字,只去挖需要的那幾行生成下一個token時,系統會去Flash裡挖出約6列、大約450位元組的資料,搬進SRAM跟運算核心一起計算,算完就丟出這個字,不需要把整張表搬過來。
6
順便做一次瘦身:量化除了搬資料位置,模型也用量化(quantization)把模型裡的數字用比較粗略、佔用空間更小的方式儲存,像把彩色照片存成低畫質版本以省空間的方式,把每個數字壓縮成4-bit,讓整個模型從原始大小壓到14.9MB,搭配前面的搬家技巧,最終才擠進這顆8美元晶片裡。
上一代 vs 這一代『晶片上跑語言模型』
項目上一代(約26萬參數)這一代(2890萬參數)
參數量約26萬約2,890萬(約100倍)
主要瘦身招式模型本身做得很小嵌入表搬去Flash+4-bit量化
晶片SRAM需求整包塞進SRAM僅運算核心留SRAM,約數十KB
晶片成本類似等級的微控制器約8美元(ESP32-S3)
生成速度文章未提供對照數字約9.5 tokens/秒

🔍 程式碼漫遊(點有 ● 的行看白話講解)

下面用一段簡化過的Python示範『隨用隨讀』的核心概念:嵌入表其實就是放在硬碟裡的一個大檔案,程式不會把整個檔案讀進記憶體,而是直接跳到需要的那一列,只挖那一小段出來。這不是原始韌體的真實程式碼(原版是C/C++,跑在ESP32上),但邏輯完全對應文章講的技巧。

ROW_BYTES = 75
💬 假設嵌入表裡每一列佔75個位元組,這是這個模型的設計值,不同模型會不一樣。
def get_embedding_row(file, token_id):
💬 定義一個函式,任務只有一件事:根據token_id去檔案裡挖出對應的那一列資料。
file.seek(token_id * ROW_BYTES)
💬 直接跳到那一列在檔案裡的位置,不用從頭讀起——這就是『隨用隨讀』的關鍵一行。
return file.read(ROW_BYTES)
💬 只讀這一列的位元組數(75個),而不是把整個2500萬列的表讀進來。
with open("embedding_table.bin", "rb") as f:
💬 把嵌入表想像成放在Flash(慢速大倉庫)裡的一個大檔案,平常它就靜靜躺在那裡沒人管它。
token_ids = [17, 902, 5]
💬 這一步需要用到的幾個token編號,通常生成一個字只會用到幾列而已,不會用到全部。
rows = [get_embedding_row(f, t) for t in token_ids]
💬 跑過每個需要的token,只挖出真正用得到的那幾列,加起來可能才幾百位元組,而不是整張25MB的表。

🛠️ 動手做:小晶片記憶體大挑戰:模擬『隨用隨讀』能不能省空間

  1. 先按『整包塞進SRAM』,看看512KB的小抽屜裝不裝得下25MB的嵌入表
  2. 再按『隨用隨讀(Flash)』,看看只留運算核心在SRAM時,還剩下多少空間
  3. 按『生成下一個字 ▶』,觀察晶片怎麼一個字一個字把故事寫出來
  4. 留意畫面下方『本次已從Flash讀取』的位元組數,跟25MB的嵌入表比比看差多少
👇 下面是活的,直接操作

🧠 工程思維透鏡(資深工程師看到的是什麼)

🔭 為什麼工程師選擇『把嵌入表丟去Flash』,而不是直接把模型縮小、砍參數?
如果直接縮小模型(減少參數),語言能力通常會等比例下降。PLE的洞察在於『不是所有參數都平等』——嵌入表是查表用的,不需要參與運算,搬到慢速儲存幾乎不影響效能;但真正需要即時運算的核心留在快取,這是一種對症下藥的資源分配思維,而不是暴力砍模型換取空間。
🔭 這個技巧原本是設計給手機/GPU用的Gemma模型,套用到比手機記憶體小上千倍的晶片上,中間要多做什麼取捨?
手機的Flash存取延遲跟微控制器的SPI Flash完全不是同一個等級,隨機讀取更慢。工程師必須確保每個token只需要讀取450位元組左右、約6列這麼小的量,慢速儲存的存取延遲才不會拖垮整體約9.5 tokens/秒的生成速度。這是『每次讀多少』跟『讀取延遲有多少』之間的精細平衡——讀太多次會被延遲拖垮,讀太大塊又塞不進SRAM。
🔭 為什麼開發者敢說『這個模型不會回答問題、不會寫程式』,卻不覺得這是技巧失敗?
模型的『知識與推理能力』取決於運算核心的大小與訓練資料(這裡只用TinyStories這種簡單故事訓練),而記憶體放置技巧只解決『裝不裝得下』的問題,不解決『夠不夠聰明』。這提醒工程師要分清『工程可行性』與『能力上限』是兩回事——PLE的貢獻是證明架構可行,不是宣稱做出了通用助理。
🔭 這個做法對一般不做AI/嵌入式的軟體工程師,有什麼可以偷師的地方?
『冷資料放慢速儲存、只在存取時讀出所需片段』其實是資料庫索引、分頁快取(paging)、CDN邊緣快取的common pattern。PLE只是把這個通用工程直覺套用到LLM架構設計上,說明底層的工程原則常常可以跨領域遷移——重點永遠是先分清楚哪些資料是『隨時要算』、哪些是『偶爾要查』。

📝 隨堂考(點選答案,立即回饋)

Q1. 這顆28.9M參數模型能夠塞進8美元晶片,最關鍵的技巧是什麼?
✅ 文章核心技巧是Google Gemma的Per-Layer Embeddings:把25MB的嵌入表留在慢速大容量的Flash,運算核心(思考的部分)才放進快速但小的SRAM,每個token只需讀約450位元組。
Q2. 為什麼嵌入表可以被放進速度較慢的Flash,而不會嚴重拖慢生成速度?
✅ 嵌入表的性質是查表(讀取),不是密集運算,所以只要每次抓需要的那幾行(約6列、450位元組),就不用整張表都在快速記憶體裡待命。
Q3. 這個模型『不會回答問題、不會寫程式』的限制,是被下列哪個因素決定的?
✅ 文章明講這個限制來自負責『思考』的那一小塊核心,以及訓練資料只有TinyStories這種簡單故事,跟記憶體放置技巧無關——技巧只解決『裝不裝得下』,不解決『夠不夠聰明』。
Q4. 跟上一代『能塞進類似晶片的語言模型』相比,這次的模型在參數量上大約是幾倍?
✅ 上一代模型約26萬參數,這次是2890萬參數,大約是100倍。
Q5. 如果要在其他嵌入式裝置上複製這個做法,下列哪一種考量最貼近文章談到的取捨?
✅ 文章的權衡點在於:雖然Flash慢,但只要每次token需要讀取的資料量夠小(約450位元組),存取延遲就不會拖垮整體約9.5 tokens/秒的生成速度;這是空間與時間之間的精細平衡。

🃏 翻牌記憶卡(先想答案,再點開對答)

Per-Layer Embeddings(PLE)點我翻面
把語言模型裡佔多數的嵌入表(查表用的部分)留在慢速大容量儲存(如Flash),只在需要時讀取少量資料的技巧,來源是Google的Gemma系列模型。
SRAM 與 Flash 的分工點我翻面
SRAM快但小,放『隨時要用』的運算核心;Flash慢但大,放『偶爾查一下』的嵌入表資料。
為什麼這次能塞進28.9M參數,是上一代的約100倍?點我翻面
因為不再要求整個模型都塞進SRAM,只有真正需要即時運算的小核心留在SRAM,其餘查表用的大宗資料改放Flash。
TinyStories點我翻面
訓練這個模型用的資料集,內容是簡單好懂的短篇故事,讓小模型也學得會,但也因此模型只會寫簡單故事,不會回答問題或寫程式。
每個token約讀取450位元組是什麼意思?點我翻面
代表模型生成『下一個字』時,只從Flash裡的25,000,000列嵌入表中挑出約6列來讀,而不是整張表都要讀進來。
邊緣運算AI(Edge AI)的意義點我翻面
讓AI模型直接在裝置本身運算,不用把資料傳到雲端伺服器,能離線使用、保護隱私、且不需要網路費用。

✅ 離開前自測(全勾=這課真的學會了)

0%