我从零写了一个流式 MoE 推理引擎,只为验证一个假设:该缓存哪些专家?
这次不是读别人的源码,而是自己从零写了一个:一个流式 MoE 推理引擎,原生读 GGUF、原生 k-quant、跨平台 C++、用我自己的构建系统 blade-build 构建。
👉 nuthatch · 11 章在线源码分析:blog.chen3feng.top/nuthatch/(搜索 + 侧边栏导航)
为什么造,而不是读
前沿开源大模型的参数量已越过 7000 亿,它们几乎都是 MoE(Mixture-of-Experts):几十上百个”专家”,但每个 token 只激活其中几个。colibrì 抓住这一点,把 744B 的模型塞进了 25GB 内存的笔记本——办法是把大部分专家留在磁盘、按需流式读入。
我读完它的源码,冒出一个念头:它的缓存策略其实很朴素(每层 LRU + 可选固定热专家)。那么——如果缓存策略本身能”学习”呢?用历史使用把最热的专家钉住常驻,是不是能明显赢过朴素的 LRU、以及操作系统页缓存这个”免费基线”?
这就是 nuthatch(䴓,shī——一种把种子囤进树皮缝、还记得藏在哪的小鸟)的护城河假设。为了验证它,我决定从零造一个引擎。目标很直白:涨 credit + 练手艺。约束也很清楚:每步一个带 CI 和单测的 PR、引入依赖前先讨论、每加一层就对拍验证一次。
结论先行:两个有数据的结果
33 个 PR 之后,假设有了答案:
① 学习式缓存在真实推理上稳定赢,且跨架构成立。 拿真实推理导出的专家选择轨迹,对比三种缓存策略的命中率(miss = 要从磁盘读):
| 每层预算(共 64 专家) | learned-pin | LRU | OS 页缓存 | 优势 |
|---|---|---|---|---|
| 4 (6%) | 20–29% | 3–5% | 0% | +15 ~ +24 pp |
| 16 (25%) | 54–73% | 46–63% | 47–63% | +6 ~ +11 pp |
预算越紧,优势越大——内存越受限(正是流式最该用的场景),朴素缓存越是崩溃(6% 预算下 OS 全局缓存直接 0% 命中),学出来的缓存越值钱。而且这不是 OLMoE 专属:换到 IBM 的 granite-moe(完全不同的架构,经 llama.cpp 导出路由)同样成立,learned 赢 +8.8 ~ +17.7pp。
② 引擎真的流式跑起来了,不是模拟。 专家不常驻,推理时按需从磁盘装进有界槽缓存再算——同一个 OLMoE、逐 token 完全一致的输出,常驻内存从 3.0GB 降到 1.2GB。
11 章源码分析涵盖什么
仓库是按建造顺序长出来的,文档也按这个顺序拆解:
| # | 章 | 内容 |
|---|---|---|
| 1–2 | 架构哲学 · 构建与 CI | 三段式依赖链、先做研究再建引擎、dogfood blade + vcpkg |
| 3–4 | 读 GGUF · 研究先行 | 专家”切片”、pread 而非 mmap(为打败 OS 基线)、trace + 三策略重放 |
| 5–6 | OLMoE 前向 · 能推理 | QK-norm/RoPE 注意力、mul_mat_id 的 MoE、对拍 llama.cpp 抓 norm_topk bug |
| 7–8 | 分词器 · KV cache | byte-level BPE、RE2→PCRE2 依赖抉择、concat/cpy 避开 ggml 图排序陷阱 |
| 9 | 护城河 | 真实推理命中率、跨领域曲线、pin 配比曲线(数据否掉我自己的假设)、granite 跨架构 |
| 10–11 | 物理流式 · 判断与边界 | 选择性加载、两段式前向、1.2GB vs 3GB、工程决策汇总与诚实边界 |
特点
- 每步一个 PR(33 个),从脚手架到跨架构验证,每个都能独立 review,且带单测——整个仓库天然是一份按学习顺序排列的推理引擎教程。
- 正确性有据可查:每加一个变体(KV cache、物理流式)都用”== 已验证路径逐 token 一致“的 parity 单测锚住;数值正确性靠逐 token 对拍 llama.cpp。
- 所有代码引用可点击直达源码;跨架构验证的路由轨迹也附在仓库里,可复现。
一点方法论
这个项目由 Claude Code 协作完成,但有意贯彻了几条我自己的工程纪律:
- 先做研究再建引擎——”学习缓存是否更好”只需轨迹 + 模拟器就能回答,不必先把引擎写出来。用最小成本先拿研究信号。
- 对拍是最好的调试器——
norm_topk=false这个 bug,靠肉眼读代码很难发现,但逐 token 对拍让它在第一个 token 就暴露。 - 数据否掉直觉时,信数据,并如实标注局限——pin/lru 配比曲线否掉了我”最优在中间”的假设,我也标注了 in-sample 直方图偏乐观这一诚实注脚。