Workshop

实战工坊:用 Colibri 在 25GB 内存的开发机上跑 744B MoE

5 min read ·

做本地推理的人大概都接受过一个默认前提:模型得先装进显存,装不进去就装内存,内存也不够就只能换更小的模型。于是「能不能跑得动」变成了一道纯粹的硬件算术题——参数越大,需要的卡越多。

Colibri 做的事情,是把这道题的前提换掉。它是一个纯 C 写的极简推理引擎,零外部依赖:不链接 BLAS,运行时不需要 Python,也不需要 GPU。而它宣称能跑的模型,从 744B 一直到 2.8T 参数。作为参照,项目诞生时用的开发机是 25GB 内存、12 核 CPU。

💡 一句话概括它的主张:模型不需要「装进」高速内存,它需要被「放置(placed)」。

一、重新算一遍稀疏性这笔账

以 744B 的 GLM-5.2 为例,拆开看每一层到底需要什么:

总参数                     744B
每 token 激活参数          约 40B
其中的路由专家             约 11GB(随 token 变化)
稠密部分(注意力 / 共享专家 / 嵌入层)  约 17B
  → int4 常驻内存          约 9.9GB
路由专家数量               19456 个,约 370GB

结论很干脆:真正必须常驻高速内存的只有约 9.9GB,剩下的 370GB 不需要同时在场,只需要「在需要那一刻到达」。于是 Colibri 把存储、内存、显存统一成一层推理层级(AI memory tiering),把权重调度做成了一件类似 JIT 编译器的事——为权重而生的 JIT。

启动时的实际输出长这样:

./coli chat
ready in 32s · resident 9.9 GB

二、构建与权重转换

引擎在 c/ 目录下按模型系列分发,coli 启动器读 config.json 自动选对应二进制,命令行接口完全一致。 以下命令均按项目文档整理:

git clone https://github.com/JustVugg/colibri && cd colibri/c
./setup.sh                 # 检查 gcc / OpenMP、构建并自测

make -C c glm              # GLM-5.2 / 5.3  (744B)
make -C c glm53            # GLM-5.3-Flash  (321B)
make -C c kimi_k3          # Kimi K3        (2.8T)
make -C c deepseek_v41     # DeepSeek V4.1 Flash (552B)
make -C c qwen38           # Qwen3.8-Flash-Next  (仅 CPU)
make -C c olmoe            # OLMoE (7B,适合先跑通链路)

权重有两种来源:直接下载社区已经转换好的容器,或者自己转。自转可以分片断点续传,不需要一次性腾出全部磁盘空间。

./coli convert --model /nvme/glm52_i4      # 自转,可断点续传

⚠️ 先小后大:不要一上来就转 2.8T 的 Kimi K3。建议先用 OLMoE(7B,磁盘约 7GB)把 setup、convert、chat 整条链路跑通,确认本机 gcc 与 I/O 正常,再去碰几百 GB 的权重。

三、专家调度机制的五个关键点

这一层是项目最值得读的部分,全部优化都要求「端到端可复现」,不允许悄悄改变模型精度或路由语义。

机制作用环境变量
路由热度驱动调度决定哪些专家留在内存自动(.coli_usage)
学习化固定热存储记录实际路由到的专家并固定最热的自动
路由前瞻线程提前一层预取下一层专家,71.6% 可预测PILOT=1
异步 I/O 重叠算常驻专家时并行加载缺失专家PIPE=1(默认开)
批量联合去重批量位置对每个唯一专家只读一次自动

有一个工程细节值得单独说:每个专家的三个矩阵在磁盘上相邻存放,因此一次 pread 就能读完整个专家。这不是算法创新,但它是把随机读变成顺序读的关键——对磁盘而言,读 3 次小片段和读 1 次连续片段的代价差很远。

另外,开启直接 I/O 可以绕过页缓存,在有 DRAM 缓存的盘上收益明显:

DIRECT=1 COLI_MODEL=/nvme/glm52_i4 ./coli chat

四、本机调优的三条命令

不用猜配置,引擎自带测量工具:

COLI_MODEL=/nvme/glm52_i4 ./coli plan     # 只读:查看规划出的 VRAM / RAM / 磁盘放置
COLI_MODEL=/nvme/glm52_i4 ./coli doctor   # 只读:就绪检查
COLI_MODEL=/nvme/glm52_i4 ./coli tune     # 测量并保存本机最快安全配置

如果手上正好有两块 SSD,可以让两块盘同时供数:

COLI_MODEL=/fast/glm52_i4 \
COLI_MODEL_MIRROR=/second/glm52_i4 \
COLI_DISK_WEIGHTS=9,3 \
./coli chat

./c/coli mirror plan   --model /fast/glm52_i4 --mirror /second/glm52_i4 --budget-gib 200
./c/coli mirror stage  --model /fast/glm52_i4 --mirror /second/glm52_i4 --budget-gib 200
./c/coli mirror verify --model /fast/glm52_i4 --mirror /second/glm52_i4

mirror 三步是分开的,因为 stage 要写入几百 GB,中途失败可以重跑,而 verify 会逐块校验两份副本一致——这一步别省,读到损坏的专家矩阵不会报错,只会让输出变得难以解释。

服务化用 coli serve(无头 API + 仪表盘)或 coli web(自动开浏览器):

./coli serve --model /nvme/glm52_i4

五、各硬件档位的真实数字

项目把实测数据公开得很坦率,包括不体面的那部分。整理如下:

硬件配置解码速度说明
6 × RTX 5090 全专家常驻5.8 - 6.8 tok/sTTFT 约 13s
128GB 纯 CPU 桌面约 1.8 tok/s预热后
单 RTX 5070 Ti1.07 tok/sGPU 常驻管线
25GB 开发机0.05 - 0.1 tok/s冷启动,诚实基线

有个容易被忽略的维度:首轮预填充的代价极高。在 RTX 5080 加两块 NVMe 的配置上,3324 token 的预填充约 90 秒,8.3k token 的首轮接近 4 分钟——但后续轮次回落到 6 到 9 秒,3k 上下文解码约 1.6 tok/s。这意味着多轮对话的体感远好于单次长文输入,长上下文一次性投喂是这个架构最脆弱的场景。

显存也不是完全没用,CUDA=1 可以把专家层放进 VRAM。在两张 8GB 卡的 Qwen3.6 上,这一项把速度从 1.44 拉到 10.05 tok/s,7 倍,且输出与 CPU 路径位级一致。

六、该有的怀疑

第一,冷启动基线是真的冷:25GB 开发机上 0.05 tok/s 意味着一个 token 二十秒,这个档位只能用来验证「链路能通」,不能用来和模型对话。

第二,可移植性被牺牲了:每个模型系列需要一个独立的 C 文件,加新模型是写代码。这和 llama.cpp 那种「一种格式到处跑」的路线是两种哲学,别指望拿它当通用运行时。

第三,磁盘寿命与带宽是隐藏成本:几百 GB 的权重反复流式读取,对 SSD 是持续压力,这也是双盘镜像和 DIRECT=1 存在的理由。

第四,速度和质量的取舍没有免费选项:项目明确承诺所有优化都必须可复现、不改变路由语义,这一点值得肯定,但也就意味着它不会用近似专家跳过之类的手段来换取速度。

结语

Colibri 的价值不在于它比 GPU 集群快——它显然不快。它的价值在于把一个被当作物理定律的约束降级成了工程取舍:「这个模型我跑不动」从此不再是一句终局判断,而是一句可以追问「愿意等多久、愿意牺牲多少延迟」的工程判断。

对于做本地推理、模型评测、或者单纯想亲手验证巨型 MoE 行为的人来说,先用 7B 的 OLMoE 把链路跑通,再决定要不要为 744B 腾出三四百 GB 磁盘,是成本最低的进入路径。

Frequently asked questions

为什么说「模型必须装进显存」是个错误的前提?
因为它把模型的全部参数当成每 token 都要用的东西。MoE 架构里,744B 总参数每 token 只激活约 40B,而其中真正随 token 变化的只有约 11GB 路由专家。Colibri 抓住这个稀疏性:把复用的稠密部分(注意力、共享专家、嵌入层)常驻内存,把按需命中的路由专家留在磁盘上流式读取,于是内存需求从模型体积降到了稠密部分体积。
专家流式加载是怎么避免每次都读硬盘的?
靠三层手段叠加。第一是每层的 LRU 缓存,命中过的专家留在内存;第二是学习化固定热存储,引擎记录你工作负载实际路由到的专家(写在 .coli_usage 里)并自动把最热的固定下来,用得越多越快;第三是路由前瞻线程,提前一层预测下一层要哪些专家并预取,实测这个预测在提前一层时有 71.6% 的准确率。
多块 SSD 能带来什么实际变化?
两块盘可以把完整模型放两份副本,引擎同时从两块盘读,显著提高有效带宽。做法是设置 COLI_MODEL 与 COLI_MODEL_MIRROR 两个环境变量指向两份权重,再用 COLI_DISK_WEIGHTS 指定主盘与镜像盘的带宽比例。此外开启 DIRECT=1 可绕过页缓存,在有 DRAM 缓存的盘上实测解码速度提升过 34%。
各档硬件的真实速度大概是什么水平?
要分层看。6 张 RTX 5090 全专家常驻可到 5.8 到 6.8 tok/s;128GB 纯 CPU 桌面约 1.8 tok/s;单张 RTX 5070 Ti 约 1.07 tok/s;而 25GB 内存的开发机冷启动只有 0.05 到 0.1 tok/s。关键在于首 token 延迟会随预填充长度急剧上升,例如 8.3k token 的首轮可能要 4 分钟,但后续轮次回落到 6 到 9 秒。
这个方案不适合什么场景?
不适合交互式低延迟场景。磁盘流式加载的代价是首 token 延迟高、多轮对话之外的长上下文预填充非常慢,开发机档位的速度也远低于可用阈值。它更适合批处理、离线评测、以及需要在本机验证巨型模型行为的研究用途。另外它牺牲了可移植性:每个模型系列要单独编译一个引擎文件,新增模型需要写代码而不是改配置。
// next.txt ›

Some outbound links in this post are affiliate links — see disclosure.