專案 GitHub:Niko1221/Strata
Strata 是一個開源的推論引擎,專門用來在家用電腦上執行 Qwen 團隊的 Qwen3.8-Flash-Next。推論引擎就是「把訓練好的模型拿來回答問題」的程式。這個模型有 1250 億個參數,壓縮到 2 位元後的檔案仍有 66 GB 左右,平常要放在伺服器上跑。Strata 的目標機器是一張 12 GB 顯示卡、64 GB 記憶體、一顆六核心處理器的電競 PC。
專案在 2026 年 9 月 25 日建立,到 10 月 6 日已有將近 14,000 顆星。作者在 RTX 5070(12 GB)上量到的寫字速度是每秒 53 到 94 個 token,視壓縮程度而定,已經比一般人讀字快。
這篇文章依序說明:
- 這個模型為什麼有機會塞進小顯卡;
- Strata 把模型的哪些部分放在哪裡;
- 產生一個 token 時,GPU 和 CPU 怎麼分工;
- 從你的程式送出請求到收到回答,中間經過哪些零件;
- 它跟常見做法比起來特別在哪,以及它的限制。
內容根據專案的 README、docs/ 裡的說明、作者附的技術報告(docs/paper/Strata-Paper.pdf),以及 src/、serve/ 的原始碼。
先認識幾個名詞
- token:模型處理文字的單位,大約是一個詞的一部分。英文裡一個 token 約等於四分之三個單字。模型一次產生一個 token。
- 參數(權重):模型裡的數字。每產生一個 token,硬體都得把這個 token 用到的權重從記憶體讀出來計算,所以「每個 token 要讀多少位元組」直接決定速度。
- VRAM:顯示卡上的記憶體。它最快(RTX 5070 約每秒 672 GB),容量卻最小。電腦主記憶體(RAM)慢了十倍左右,SSD 更慢。
- MoE(mixture of experts,專家混合):一種模型架構。每一層裡有很多組小型子網路,稱為「專家」,再由一個稱為「路由器」(router)的小網路替每個 token 挑出少數幾個專家來算。沒被挑中的專家這一步完全不用讀。
- 量化(quantization):用較少的位元存每個權重,例如從 16 位元壓到 2 到 3 位元,檔案變小,品質略降。文中的 Q2_0、IQ2_XS、IQ3_XXS、IQ3_S 都是不同的量化格式,數字越大越接近原始模型,也越慢。IQ 開頭的幾種是 llama.cpp 發展的 i-quant 格式,用查表的方式記錄權重。
這個模型為什麼有機會塞進小顯卡
Qwen3.8-Flash-Next 有 48 層,每層有 512 個專家,總共 24,576 個。路由器每次只挑 10 個,所以一個 token 只會碰到約 2% 的專家權重。
技術報告用 Q2_0 檔案列出各部分的大小,以及每個 token 實際要讀多少:
| 模型的部分 | 存放大小 | 每個 token 讀取 | Strata 放在哪裡 |
|---|---|---|---|
| 被路由的專家(48 層 × 512) | 34.0 GB | 0.66 GB(2%) | RAM 全部,VRAM 放常用的約 4,500 個 |
| 混合器、注意力、共享專家、路由器 | 1.8 GB | 1.8 GB | VRAM |
| 閘控殘差權重 | 1.3 GB | 1.3 GB | VRAM |
| 輸出層 | 0.44 GB | 0.44 GB | VRAM |
| n-gram 嵌入表 | 28.8 GB | 最多 23 KB | SSD 與作業系統快取 |
| MTP 預測層 | 0.8 GB | 每次猜測時 | VRAM |
這張表的重點在第三欄。66 GB 的檔案裡,每個 token 一定要讀的部分大約 3.5 GB,可以整個放進 VRAM。真正麻煩的是專家:總量 34 GB 放不進顯示卡,但每個 token 只用到其中 0.66 GB。
另外兩個架構特點讓長對話也不會撐爆 VRAM:
- 48 層裡有 36 層使用 Gated DeltaNet。這是一種循環式的混合器,它把讀過的內容壓成固定大小的狀態,對話再長,這個狀態也不會變大。
- 另外 12 層使用 Qwen 的稀疏注意力。一般的注意力機制要回頭看所有讀過的 token,稀疏注意力每次最多只挑約 2,048 個位置來看,計算量不隨上下文長度增加。
那張 28.8 GB 的 n-gram 嵌入表是用「最近三個 token 的編號」來查的,所以下一步要讀哪幾列,在需要之前就已經知道。Strata 因此把它留在 SSD 上,每個 token 提前一步讀 16 列。
三層記憶體:誰放在哪裡
Strata 依照上面那張表,把模型分到三個地方:
- VRAM(顯示卡記憶體):每個 token 都要用的部分,包括注意力與 DeltaNet 混合器、路由器、共享專家、輸出層、MTP 預測層,以及對話的 KV 快取(模型記住前文用的中間結果)。剩下的空間全部拿來當專家快取,放最常被挑中的專家。12 GB 的卡大約能放 4,500 個。
- RAM(主記憶體):全部 24,576 個專家都放在這裡,而且是「鎖定」(pinned)的記憶體。鎖定的意思是作業系統不會把這段記憶體換到硬碟上,顯示卡可以直接透過 PCIe(主機板上連接顯示卡的匯流排)來讀,CPU 也能就地計算。
- SSD:n-gram 嵌入表,每個 token 只讀幾列。
64 GB 記憶體剛好夠用:專家區光 Q2_0 就佔 34 GB,IQ3_XXS 佔 43 GB。這也是 README 說「第一次啟動時電腦可能卡住 1 到 3 分鐘」的原因:Strata 要把 35 到 55 GB 讀進 RAM 並鎖定一部分。
產生一個 token 時,一層裡發生什麼事
每一層的計算大致如下:
- GPU 先算這一層的混合器和路由器,得到這個 token 要用的 10 個專家編號。
- GPU 把這 10 個編號和輸入寫進一小塊主機記憶體。原始碼把它叫做 doorbell(門鈴),
src/core/layer.cpp的註解直接寫「這就是整個協定的重點」。 - CPU 一直盯著這個門鈴,一看到編號就把 10 個專家分成三份:
- 已經在 VRAM 快取裡的,交給 GPU 算;
- 沒在快取裡的,一部分由顯示卡的複製引擎透過 PCIe 從 RAM 搬上去算(IQ 系列格式約 55%,Q2_0 約 20%);
- 其餘的由 CPU 直接在 RAM 裡算。
- CPU 把結果寫回 GPU 讀得到的記憶體,GPU 把所有專家的結果加總,進入下一層。
GPU 和 CPU 在同一層裡同時工作,下一層要等兩邊中較慢的那一邊做完。為了不讓 CPU 等驅動程式,Strata 把 48 層的整段計算錄成一個 CUDA graph。CUDA graph 是 NVIDIA 提供的機制,可以把一連串 GPU 工作錄下來一次送出,省掉每一步都要和驅動程式來回溝通的時間。
技術報告拆解了 4K 上下文、Q2_0 時的一輪時間(單位:毫秒):
| 項目 | 時間 |
|---|---|
| 一輪總計 | 34.3 |
| 等 GPU 的部分 | 14.6 |
| 等 CPU 算專家 | 13.4 |
| MTP 猜測 | 2.0 |
| 其他 | 4.3 |
GPU 和 CPU 各佔約一半。作者的結論是這個引擎已經平衡,所以只升級其中一邊,速度最多只能提升約三分之一。
先猜再驗證:MTP 推測解碼
GPU 每輪最大的成本是讀那 3.5 GB 的固定權重。一次算一個 token 和一次算四個 token,讀的量幾乎一樣。推測解碼(speculative decoding)就是利用這一點:先用便宜的方法猜接下來幾個 token,再讓大模型一次把這些猜測全部檢查完,留下猜對的。
Qwen3.8-Flash-Next 本身附有一層 MTP(multi-token prediction,多 token 預測),專門用來猜後面的 token。量化過的 GGUF 檔案(llama.cpp 常用的模型檔格式)沒有包含這一層,所以 Strata 的安裝程式另外從 Qwen 釋出的原始 16 位元(BF16)檔案只抓這一層(約 5 GB),壓縮後放進 VRAM。
運作方式:
- MTP 每輪最多猜 3 個 token,只有在它至少 50% 有把握時才把猜測放進去;
- 上一個確定的 token 加上這些猜測,一起跑完 48 層,大模型留下它同意的部分,再自己多產生一個;
- 平均每輪產生 2.4 到 3.2 個 token;
- 在貪婪解碼(每步都選機率最高的 token)下,輸出和不推測時逐字相同。作者用故意塞錯的猜測測試過這一點。
整體加速 1.6 到 1.8 倍。全部放在 VRAM 的引擎通常能拿到 2.5 到 3 倍,Strata 少一些,原因是每多驗證一個 token,那個 token 也有自己的 10 個專家,其中沒在快取裡的都得讓 CPU 算。
另外有一個補充機制叫 prompt lookup:回答在重複前文時(例如改程式碼、引用原文),直接從前文複製最多 5 個 token 當作猜測。它只在實測划算時啟用,改程式碼快 6% 到 11%,其他文字不受影響。
會跟著對話調整的專家快取
不同專家被挑中的頻率差很多,VRAM 裡放哪些專家,決定 CPU 要做多少事。Strata 的做法分兩步:
- 啟動時:根據事先在其他提示上記錄的使用頻率(
data/expert-profile.bin),把最常用的專家先放進 VRAM。用沒看過的提示測試,4,500 個位置可以接住約 50% 的專家呼叫。 - 對話中:每四輪檢查一次,把這段對話一直在用、卻不在快取裡的專家換進來,一次最多 96 個,換掉最少用的。換的動作在 GPU 忙著猜測時進行。
第二步把命中率從 50% 拉到約 72%。expert_cache.hpp 的開頭註解說明了這件事的分量:CPU 算專家是整個引擎最大的單項成本,量測時每個 token 要讀 663.6 MB,佔掉一個 token 約三成的時間,唯一的解法是少讀這些位元組。
報告裡還有兩個小調整帶來明顯差異:
- 舊的先踢、新的等搬好再用。原本換專家時,下一輪要等 96 個專家複製完。改成立刻淘汰舊的、新的搬完才啟用之後,Q2_0 在 4K 上下文從每秒 91.7 提高到 94.4 個 token。
- 快取位置依位元組算。IQ3_XXS 的專家依所在層不同,大小從 1.3 MB 到 2.3 MB。每個位置都按最大的專家預留,只放得下 2,673 個;按各層實際大小分配後放得下 3,556 個,1K 上下文的寫字速度提高 13%。
這也解釋了 README 的一句建議:VRAM 大小比顯示卡快不快更重要。每多 1 GB VRAM 大約多放 700 個專家,每多一個專家在 GPU 上,CPU 就少算一個。
讀長提示:把專家整批搬上 GPU
讀提示(prefill)和寫回答的狀況不一樣。一次讀進幾千個 token 時,每個專家都會被很多 token 用到,這時在 GPU 上算最划算。
Strata 每次最多讀 8,192 個 token。每一層開始前,把沒在快取裡的專家從 RAM 經 PCIe 送上 GPU,同時 GPU 先算已經送到的部分。暫存空間向專家快取借用,讀完再還回去。因為稀疏注意力只看有限的位置,提示讀取速度幾乎不隨長度下降。依 README 的量測,RTX 5070 上讀 32K token 的提示,Q2_0 約每秒 2,650 個,IQ3_S 約每秒 1,620 個。
讀過的內容會留下來。引擎在 RAM 裡保留最多 6 個對話檢查點,每個約 118 MB,在每個新的助理回合開始時和每 16K 個 token 時各存一次。新請求的開頭只要和某個檢查點完全一樣,就從那裡接著讀。最舊的那個檢查點通常是系統提示的結尾,會永久保留,所以同一個工具開新對話時,也能跳過共用的系統提示。技術報告把這項功能列為「未來最大的改進」,現在的版本已經做出來了。README 說第一次讀約 1 分鐘處理 30,000 個 token,之後的追問幾秒內就開始回答。
從請求到回答:外層的零件
上面講的都是 C++ 引擎(src/、include/,支援 NVIDIA 的 CUDA 和 AMD 的 HIP)。使用者實際碰到的是外面幾層:
setup.py:一鍵安裝程式,由START-HERE.bat或setup.sh啟動。它檢查顯示卡、記憶體與硬碟,依記憶體大小推薦模型,下載現成的引擎(找不到合適的就就地編譯),下載約 70 GB 的模型並可續傳,另外抓 MTP 層,最後寫出啟動腳本。serve/server.py:Python 寫的 HTTP 伺服器,提供和 OpenAI、Anthropic 相容的 API(/v1/chat/completions、/v1/messages、/v1/responses),所以 Claude Code、Codex CLI 這類工具可以直接指向它。它也提供瀏覽器裡的聊天頁面和即時監看 GPU、CPU、RAM 的 Monitor 分頁。- MCP 伺服器(
serve/mcp.py、tools/strata_mcp.py):MCP 是讓 AI 工具呼叫外部功能的標準協定。透過它,AI 助理可以替使用者安裝、啟動、停止 Strata。
一次請求的路徑:
- 你的程式把對話送到
http://127.0.0.1:8080/v1/...; server.py依模型的聊天範本把對話排好,轉成 token 編號;- 伺服器在引擎的標準輸入寫一行文字指令:
GEN、最多產生幾個 token、取樣設定,後面接 token 編號; - 常駐的
strata --serve程序找出可沿用的檢查點,讀完剩下的提示,開始逐輪推測與驗證; - 引擎把產生的 token 編號從標準輸出送回,伺服器轉回文字,以串流方式傳給你的程式。
引擎和伺服器之間只用文字指令溝通,好處是 server.py 可以換上一個寫好劇本的假引擎 MockEngine,所有 API 路徑都能在沒有顯示卡的機器上測試。預設一次只處理一個請求,其他的排隊;要同時處理多個,可以設定 "parallel": 2,但在 12 GB 的卡上每個回答都會變慢。
跟常見做法比起來特別在哪
在家用電腦跑放不進顯示卡的模型,最常見的工具是 llama.cpp:把放不下的部分留在 RAM 交給 CPU 算。技術報告認為這樣做可行,但機器的大部分零件多數時間都閒著。Strata 的差異主要在以下幾點。
一個引擎只為一個模型寫。 通用引擎要支援各種模型,Strata 則依照 Qwen3.8-Flash-Next 每一部分的大小與使用頻率來決定放置位置、快取大小與分工比例。報告說這個想法來自 Splash、ninfer 和 HyperQwen 這幾個同樣只服務單一模型的專案。代價很直接:Strata 只能跑這個模型和它的幾個變體(Coder、Swift 1.5、Unsloth 的版本)。
GPU 和 CPU 在同一層裡同時工作。 讓 CPU 分擔 MoE 專家的想法早就有,Fiddler、KTransformers 都做過;MoE-Infinity 研究過專家快取,PowerInfer 利用冷熱權重的差別。Strata 把這些想法組合起來,再加上門鈴機制、會跟著對話調整的快取、MTP 推測解碼,以及讓顯示卡的複製引擎分擔一部分搬運。
堅持結果精確。 推測解碼的輸出和一般貪婪解碼逐字相同。和 llama.cpp 比較下一個 token 的機率分布,平均 KL 散度(衡量兩個機率分布差多少的指標)是 0.022,比 llama.cpp 自己的 CPU 版和 GPU 版之間的差距 0.058 還小。i-quant 格式的運算也是從 llama.cpp 的程式碼轉寫過來,再拿真實模型的各層逐一比對。
每個說法都附量測,失敗的嘗試也記下來。 專案的 AGENTS.md 明文要求「沒有量測就不下結論」。技術報告記錄了沒有效果的做法,例如把一輪拆成兩組 token、讓一組的 CPU 工作和另一組的 GPU 工作重疊。結果精確但慢了約 7%(每秒 85.8 對 91.8 個 token),原因是固定權重要多讀一次,每組共用的專家也變少。src/kernels/ 底下大量的 *_parity.cpp 測試,用來確認每個手寫運算核心和參考實作算出相同結果。
限制
- 只支援一個模型。 換其他 MoE 模型,這些放置與分工的設計都得重做。
- 吃記憶體。 至少 32 GB,跑全部尺寸要 64 GB。模型大到 RAM 放不下時,部分專家要邊回答邊從 SSD 讀,速度會掉很多;Unsloth 的 UD-Q4_K_XL 在 64 GB 機器上大多從 SSD 讀,只剩每秒 7 到 8.5 個 token。
- 長上下文會擠掉專家。 上下文拉到 262K 時,KV 快取和相關暫存佔掉約 4 GB VRAM,12 GB 的卡只剩約 1,600 個專家的空間,猜測的命中率也下降。Q2_0 的寫字速度從約每秒 95 個降到約 56 個。
- i-quant 格式受 CPU 運算限制。 IQ 系列要查表解碼權重,六核心每秒只能處理約 25 GB。IQ3_XXS 的檔案只比 Q2_0 大 25%,寫字速度卻慢了約三分之一。
- 量測主要在一台機器上。 正式數據來自 RTX 5070 加 Ryzen 5 7600,其他顯示卡的數字多是推估(報告標註誤差約 ±20%)或社群自行回報。
- 中文要選對版本。 Coder 版拿掉一半專家,README 註明它在中文和其他 CJK 文字上較弱(issue #438),中文使用者應該選 Q2_0、IQ2_XS 或 IQ3_S。
- 專案很新,變動很快。 從建立到現在不到兩週,README 和文件裡的數字都標了引擎版本,例如提示讀取速度在 0.1.13 之後大約快了一倍。引用數字時要注意對應的版本。