Show HN: 如何在我的低配置电脑上运行 GLM-5.2

Hacker News 热门(buzzing.cc 中文翻译)·2026-07-10 06:18·47天前·vforno
AI 导读

colibrì v1.0 引擎以纯 C 实现、零运行时依赖,可在约 25 GB RAM 的消费级电脑上运行 744B 参数的 GLM-5.2 MoE 模型。模型经 int4 量化后磁盘占用约 370 GB,常驻内存仅 9.9 GB,通过流式加载磁盘专家实现推理。冷解码速度约

Hacker News 热门(buzzing.cc 中文翻译)
精选
70AI 编辑部评分,满分 100

Show HN: 如何在我的低配置电脑上运行 GLM-5.2

2026-07-10 06:18· 47天前· vforno
AI 导读

colibrì v1.0 引擎以纯 C 实现、零运行时依赖,可在约 25 GB RAM 的消费级电脑上运行 744B 参数的 GLM-5.2 MoE 模型。模型经 int4 量化后磁盘占用约 370 GB,常驻内存仅 9.9 GB,通过流式加载磁盘专家实现推理。冷解码速度约

推荐理由

这个单C文件项目让744B的MoE模型在25GB内存的笔记本上跑了起来,虽然慢,但证明了消费级硬件也能把前沿模型‘盘活’,做本地推理的极客值得看看。

正文 · AI 翻译

微型引擎,巨型模型。在仅配备约 25 GB 内存的消费级机器上运行 GLM-5.2(744B 参数的 MoE 模型)—— 纯 C 语言实现,零依赖,通过从磁盘流式加载专家模块实现。

Colibrì 是一个轻量级、保质量的 MoE 运行时,它将显存、内存和存储视为统一管理的内存层级。快速内存不足可能会降低速度,但默认策略绝不会静默改变模型精度或路由器语义。

$ ./coli chat
  🐦 colibrì v1.0 — GLM-5.2 · 744B MoE · int4 · streaming CPU
  ✓ ready in 32s · resident 9.9 GB
  › ciao!
  ◆ Ciao! 😊 Come posso aiutarti oggi?

查看运行效果

网页仪表盘(`./coli web`):一个 744B 参数的模型在 6× RTX 5090 上以端到端 4+ tok/s 的速度作答 —— 包含实时 token 指标、硬件面板以及显存/内存/磁盘专家层级。

大脑页面:全部 19,456 个专家构成一个活体皮层 —— 颜色代表存储层级,亮度代表路由热度,每一轮被路由到的专家会闪烁白光。悬停可查看该专家测量到的主题亲和度。

目录

  • 核心理念
  • 查看运行效果
  • 已实现功能
  • 真实数据
  • 下载模型
  • 网页仪表盘
  • 有更好的机器?

核心理念

一个 744B 参数的混合专家模型,每个 token 仅激活约 40B 参数 —— 其中每个 token 之间变化的参数仅约 11 GB(即被路由的专家模块)。因此:

  • 密集部分(注意力机制、共享专家、嵌入层 —— 共 17B 参数)以 int4 精度常驻内存(9.9 GB);
  • 21,504 个被路由的专家模块(75 个 MoE 层 × 256 个专家 + MTP 头,每个 int4 精度下 19 MB)存储在磁盘上(共 370 GB),按需流式加载,并配备每层 LRU 缓存、可选的固定热存储区,以及作为免费 L2 缓存的 OS 页面缓存。

引擎是一个单一的 C 文件(`c/glm.c`,约 2,400 行)加上少量头文件。无需 BLAS,运行时无需 Python,无需 GPU(存在一个可选的 CUDA 层级用于固定专家模块 —— 见下文)。

已实现功能

  • 忠实还原 GLM-5.2(`glm_moe_dsa`)前向传播 —— 已通过 transformers 参考实现验证 token 级别精确性(在具有真实架构的小型随机模型上,teacher-forcing 32/32 通过,greedy 20/20 通过)。
  • MLA 注意力机制(q/kv-LoRA,交错式部分 RoPE)配合压缩 KV-cache:每个 token 仅需 576 个浮点数,而非 32,768 个(缩小 57 倍 —— GLM-5.2 有 64 个注意力头且无 GQA)。
  • DeepSeek-V3 风格的 sigmoid 路由器(`noaux_tc`、`routed_scaling_factor`)、共享专家、前 3 层为密集层。
  • 原生 MTP 投机解码——GLM-5.2 自身的多 token 预测头(第 78 层)会草拟 token,主模型通过一次批量前向传播进行验证。该预测头必须采用 int8 精度(转换器默认执行此操作):在 int4 精度下,草稿接受率降至 0–4%,投机机制无法生效;而在 int8 精度下,接受率为 39–59%,每次前向传播可生成 2.2–2.8 个 token(社区实测数据,#8)。在精确算术运算下无损——但在实际应用中,其输出与无投机贪婪解码并非字节级一致(#100)。这并非 MTP 独有问题:colibrì 的量化整数内核具有形状依赖性,因此任何批量(S>1)或 GPU 前向传播的舍入方式都与单 token 路径略有不同,而 int4 精度的 GLM-5.2 又非常接近 argmax 平局状态,这种舍入变化足以翻转一个 token。MTP、CUDA 专家级推理以及批量预填充是触发相同敏感性的三种不同方式(社区在 #100 中证实:仅更换内核族就会在 3/5 的提示词上分叉贪婪解码的输出结果,且完全不涉及投机)。每个输出的 token 仍然是有效前向传播的 argmax——后续生成内容保持正确——只是不再是相同的输出流。如需实现字节级可复现性:设置 DRAFT=0(关闭投机),若还需消除内核族/GPU 依赖性,则同时设置 IDOT=0 COLI_CUDA=0。在采样模式下,拒绝采样可保持分布正确性。来自同一实测的诚实说明:在冷缓存状态下,每个被验证的草稿都会路由到额外的专家(约从 660 次专家加载/token 增至约 1100 次专家加载/token),因此在缓存/固定机制预热之前,投机解码可能反而导致净时间损失。
  • 语法强制推测草稿(GRAMMAR=file.gbnf, #48)——在约束输出工作负载(JSON/NDJSON、函数调用、结构化提取)中,语法本身是第三个草稿来源:只要语法恰好允许一个合法字节(花括号、引号、键名、枚举体),该强制跨度就会被分词并作为预接受草稿注入,接受率约 1.0——无需草稿头,无需查找表,并且即使使用 #8 中的 int4 MTP 头也能生效。它从不约束采样:强制跨度与任何草稿一样,在相同的批量联合前向传播中验证,因此错误或不同步的语法不会改变输出——最坏情况是草稿被拒绝,并且自适应防护会在接受率低于 50% 时关闭该来源。字节级 GBNF 子集(字面量、字符类、| ( ) ? * +、注释);GRAMMAR_DRAFT=n 限制每次前向传播的强制跨度(默认 24)。与 DRAFT/MTP 组合使用,后者填充强制跨度之间的自由文本间隙。完整参考——机制、实测 A/B 对比、适用场景、先前工作:docs/grammar-draft.md。
  • 真实采样——温度 + 核采样,默认值针对 int4 现实调优(0.7 / 0.90;官方 1.0 / 0.95 会从尾部采样量化噪声)。
  • 整数点积内核(Q8_0 风格的 int8 激活、AVX2 maddubs):int8 矩阵乘法速度提升 1.4–2.5 倍(实测 119 GFLOP/s),int4 在批量中提升 1.8 倍——路由根据每个形状的测量结果决定(int4 单行保持 f32:实测速度更慢)。
  • MLA 权重吸收(DeepSeek 技巧)用于解码:无需逐 token 的 k/v 重建——查询吸收 kv_b,上下文在注意力之后投影。经验证精确无误:TF 32/32 和生成 20/20,强制在所有位置使用吸收。
  • 异步专家预读:当一组专家正在被乘运算时,内核已经在读取下一组专家(WILLNEED)。
  • 量化内核:int8 / 打包 int4 / 打包 int2、逐行缩放、AVX2、按需反量化。打包经验证与 int8 容器位级一致。
  • DSA 稀疏注意力 — GLM-5.2 的闪电索引器,严格遵循参考模型 glm_moe_dsa:每层选择前 2048 个因果键(全/共享索引器层),从 out-idx-* 权重中自动检测(--indexer 转换器模式,从 FP8 仓库中提取约 189 MB)。经精确验证:强制保留所有键的选择可逐 token 复现密集注意力。DSA=0 禁用,DSA_TOPK 覆盖默认值。
  • KV 缓存持久化 — 对话在引擎重启后仍保持热状态:服务模式在每次对话轮次后将压缩的 MLA KV 追加到 .coli_kv 文件(约 182 KB/token,崩溃安全),并在启动时恢复,无需重新预填充。经验证与不间断会话字节完全一致。KVSAVE=0 禁用。
  • 路由器预取(PILOT=1,实验性)— 下一层的路由有 71.6% 的概率可从当前层的注意力后状态预测(经测量);一个专用 I/O 线程在当前层计算时预取这些专家。
  • 批量联合 MoE:在预填充(以及 MTP 验证)中,批次中每个唯一的专家只读取一次,并应用于路由到该专家的每个位置。
  • 基于 C 语言的字节级 BPE 分词器(GPT-2 风格,使用 Unicode 属性正则表达式,32 万次合并)。
  • 内存安全:专家缓存在启动时根据 MemAvailable 自动调整大小 — 一个诚实的峰值预估(工作集、KV、MTP 行、重建缓冲区),确保内核 OOM 杀手永远不会触发。
  • 离线 FP8→int4 转换器(c/tools/convert_fp8_to_int4.py):一次下载一个分片(约 5 GB),反量化(128×128 块尺度),重新量化到引擎的容器格式,然后删除该分片 — 756 GB 的 FP8 检查点无需同时存在于磁盘上。支持断点续传。

真实数据(WSL2,12 核,25 GB 内存,通过 VHDX 的 NVMe)

详细 GPU 实验:GLM-5.2 在 6 块 RTX 5090 上 — 专家完全驻留在 VRAM+RAM 中,单请求解码达到 6.84 tok/s。

指标 数值
磁盘上的模型(int4 容器) 约 370 GB
常驻内存(密集,int4) 9.9 GB
加载时间 约 30 秒
对话期间峰值 RSS 约 20 GB(自动限制)
冷解码成本 约 11 GB 磁盘读取/token(75 层 × 8 个专家)
磁盘上限(此开发机的驱动器) 约 1 GB/s → 冷启动约 0.05–0.1 tok/s
MTP 推测解码(int8 头) 测量值为 2.2–2.8 tok/前向传播(第 8 次)

这并不慢。这是一款 744B 参数的尖端级模型,在一台成本低于一块 H100 风扇的机器上正确作答。热缓存、固定热专家和 MTP 技术显著降低了有效响应延迟;剩下的就交给磁盘的物理特性了。

SSD 说明

冷启动时随机读取负载很高(约 11 GB/token),但读取操作并不会对 SSD 造成实质性磨损——colibrì 的流式传输是只读的。高负载下的真正担忧在于:(1)系统内存不足时产生的交换流量(写入操作会磨损硬盘——请保持合理的 --ram 预算;colibrì 的自动预算设计旨在避免使用交换空间);(2)持续的热量:长时间满读取负载会使廉价硬盘发热。请监控硬盘温度与健康状态。

下载模型

一个为 colibrì 预转换的 GLM-5.2 int4 模型已在 Hugging Face 上提供——请使用带有 int8 MTP 头(matey-0 的克隆版本)的版本:

⚠️ MTP 头必须是 int8 格式。原始镜像(jlnsrk/GLM-5.2-colibri-int4)提供的是 int4 MTP 头,这会导致草稿接受率为 0%——推测过程会静默失效,你将失去约 2 倍的 MTP 加速效果。这是最常见的“为什么 MTP 卡在 0%?”的报告来源(#8, #102)。int8 头可实现实测的 39–59% 接受率。上面的 matey-0 克隆版本是原始的 int4 模型,但三个 out-mtp-* 文件已替换为 int8 版本——下载这个版本即可直接使用。

检查你拥有的文件:ls -l <model>/out-mtp-* · int8(正确):3527131672 / 5366238584 / 1065950496 · int4(0% 接受率):1765523544 / 2686077736 / 536747200——如果看到这些数字,请从 int8 镜像中替换这三个文件。

下载仓库并将 COLI_MODEL 指向其目录:

COLI_MODEL=/path/to/GLM-5.2-colibri-int4-with-int8-mtp ./coli chat

这完全跳过了 FP8 到 int4 的转换步骤。感谢 DatPat 提供的原始镜像以及 matey-0 提供的 int8 头克隆版本。

快速开始

cd c
./setup.sh                      # checks gcc/OpenMP, builds, self-tests

# ONE command does everything model-side: downloads GLM-5.2-FP8 shard by shard
# (never needs the full 756 GB at once), converts to the int4 container, then
# converts the MTP head for speculative decoding. Resumable at any point.
# Conversion (only) needs python with: pip install torch safetensors huggingface_hub numpy
./coli convert --model /nvme/glm52_i4     # ~400 GB free on a real ext4/NVMe path

# chat — RAM budget, expert cache and MTP are all detected automatically:
COLI_MODEL=/nvme/glm52_i4 ./coli chat

在加载模型之前,请检查计划的存储层级结构:

COLI_MODEL=/nvme/glm52_i4 ./coli plan
COLI_MODEL=/nvme/glm52_i4 ./coli plan --gpu 0,1 --ram 128 --vram 48 --json

# apply the bounded plan to the normal runner
COLI_MODEL=/nvme/glm52_i4 ./coli chat --auto-tier

coli plan 仅读取 safetensors 文件头,并报告模型的精确稠密/专家参数量、运行时 RAM 预留量、安全专家缓存上限以及有界 VRAM 热层。其带版本号的 JSON 输出设计供 CLI、API 服务器、Web UI 和桌面 shell 共享;它不会分配模型张量或启动推理。--auto-tier 将同一方案应用于聊天、运行、服务和基准测试。它会立即设置 RAM 预算和上下文;VRAM 层仅在当前 glm 二进制文件与 CUDA 链接时才启用。显式标志和环境变量的优先级高于自动值。

在加载模型之前,coli doctor 执行一次只读就绪检查,并说明所选的磁盘/RAM/VRAM 放置方案是否可运行:

COLI_MODEL=/nvme/glm52_i4 ./coli doctor
COLI_MODEL=/nvme/glm52_i4 ./coli doctor --gpu 0 --ram 128 --json

Doctor 验证模型目录、配置、分词器、safetensors 文件头、引擎可执行文件、可用 RAM、请求的 NVIDIA 设备、CUDA 链接以及 coli plan 所使用的相同放置预算。它从不启动 glm、读取张量载荷、导入模型框架或创建 CUDA 上下文。带版本号的 JSON 报告使用稳定的检查 ID 以实现自动化。警告保持退出状态码 0;缺少需求或不安全的 RAM 预估返回 1,而无效的 CLI 值返回 2。

运行时的引擎是纯 C 语言——Python 仅用于一次性转换器。

Windows 11(原生,无需 WSL)

colibrì 在 Windows 11 x86-64 上使用 MinGW-w64 原生构建和运行。该移植在 c/compat.h 中添加了一个 _WIN32 兼容层,将 POSIX I/O 映射到 Windows API(pread → ReadFile+OVERLAPPED,posix_fadvise 为空操作,对齐分配,MoveFileEx 重命名,GlobalMemoryStatusEx RAM 检测)。所有平台差异都保留在 compat.h 中;引擎源代码保持不变。

工具链:通过 winlibs 或 MSYS2 MinGW-w64 使用 GCC。已使用 GCC 16.1.0(x86_64-ucrt-posix-seh)测试通过。

# One-time toolchain install (pick one):
scoop install mingw-winlibs                    # portable, no shell needed
# or: pacman -S mingw-w64-x86_64-gcc make     # via MSYS2

# Build (from c/ directory):
make glm.exe            # GLM-5.2 engine (static, no DLL dependencies)
make olmoe.exe          # OLMoE engine (same shims)
make iobench.exe        # disk I/O benchmark
make test-c             # run C tests
make test-python        # run Python tests (requires python)

# AVX-VNNI: Intel Alder Lake+ (and Meteor Lake+) CPUs have a 128-bit int8
# dot-product instruction (VPDPBUSD) the engine can use for ~1.3x faster
# quantized matmul. The x86-64-v3 default (portable AVX2) compiles it out;
# build for THIS machine to enable it:
make glm.exe ARCH=native                       # banner prints "idot: avx-vnni"

# Verify (tiny model, 2.4 MB):
pip install torch transformers safetensors huggingface_hub
python tools/make_glm_oracle.py                # generate tiny oracle
SNAP=./glm_tiny TF=1 ./glm.exe 64 16 16        # expect "32/32 positions"

# Run with real model:
SNAP=D:\glm52_i4 ./glm.exe 64 4 16            # batch inference
python coli chat --model D:\glm52_i4            # interactive chat
python coli serve --model D:\glm52_i4            # OpenAI-compatible API

预热(隔夜缓存预填充):引擎的专家缓存会从你的工作负载中学习。附带的 warmup.ps1 脚本以循环方式使用多种提示词运行 coli run,以无人值守方式构建 .coli_usage 直方图,从而使下一次真实会话开始时拥有一个庞大且准确的活跃专家固定集。每次运行在干净完成时都会原子化地保存使用情况。

.\warmup.ps1 -Rounds 1 -Ngen 32               # ~60-90 min, durable progress

NVIDIA GPU(可选,通过运行时 DLL):在 Windows 上,引擎使用 MinGW gcc 构建,但 CUDA 内核需要 MSVC + nvcc。两者分工明确:将 CUDA 后端构建为独立的 coli_cuda.dll(nvcc + MSVC),然后主机程序 glm.exe 在运行时通过 LoadLibrary 加载该 DLL(c/backend_loader.c)。主机从不直接链接 cudart;如果该 DLL 不存在,引擎会无错误地回退到 CPU。

# Prerequisites: CUDA Toolkit + MSVC Build Tools (cl.exe) + nvcc on PATH.
# Build the DLL from a shell with the MSVC environment set (vcvars64.bat or
# "x64 Native Tools Command Prompt for VS"):
make cuda-dll CUDA_HOME="C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.8" CUDA_ARCH=sm_120

# Build the host with the runtime loader (CUDA_DLL=1 adds -DCOLI_CUDA and
# links backend_loader.o instead of cudart):
make glm.exe CUDA_DLL=1 ARCH=native

# Run with the GPU expert tier (8 GB VRAM budget here; scale to your free VRAM):
$env:COLI_CUDA="1"; $env:COLI_GPU="0"; $env:CUDA_EXPERT_GB="8"
python coli chat --model D:\glm52_i4 --topp 0.7

该 DLL 导出了 11 个 extern "C" 符号(如 coli_cuda_init、coli_cuda_matmul 等);backend_loader.c 在首次使用时通过 GetProcAddress 解析它们。ColiCudaTensor* 对主机是不透明的(仅存储,从不解引用),因此由 MSVC 分配的结构体在 ABI 边界上是安全的。CUDA_ARCH 必须与你的 GPU 计算能力匹配(例如,Blackwell / RTX 50 系列使用 sm_120,Ada / RTX 40 系列使用 sm_89)。

状态:第一阶段已完成(可编译、结果正确、静态链接)。Windows GPU 层级(通过 LoadLibrary 加载运行时 coli_cuda.dll)已在 RTX 50 系列(sm_120)上实现并验证。O_DIRECT(第二阶段)和针对 transformers 参考实现的完整模型验证是独立的工作流。

兼容 OpenAI 的 API

coli serve 保持一个模型进程加载状态,并暴露一个纯文本的、兼容 OpenAI 的 HTTP API。网关仅使用 Python 标准库;推理仍在同一个无依赖的 C 引擎中运行。

cd c
COLI_MODEL=/nvme/glm52_i4 COLI_API_KEY=local-secret ./coli serve \
  --host 127.0.0.1 --port 8000 --model-id glm-5.2-colibri

curl http://127.0.0.1:8000/v1/chat/completions \
  -H 'Authorization: Bearer local-secret' \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "glm-5.2-colibri",
    "messages": [{"role": "user", "content": "Hello"}],
    "stream": true
  }'

已实现的端点包括 GET /v1/models、GET /v1/models/{model}、POST /v1/chat/completions 以及旧版 POST /v1/completions。聊天和补全请求支持 JSON 响应、SSE 流式传输、用量统计、max_tokens/max_completion_tokens、temperature 和 top_p。扩展参数 enable_thinking: true 可启用 GLM-5.2 的推理块;标准的 reasoning_effort 字段也会启用它,除非设置为 none。

第一个版本特意只支持文本,并且一次只服务一个生成请求:744B 模型驻留在一个持久进程中,因此并发 HTTP 请求会排队,而不会加载重复的模型副本。工具、图像/音频输入、自定义停止序列、对数概率和 token 惩罚会返回明确的错误,而不是被静默忽略。默认绑定地址是 localhost;在将服务器暴露到本机之外前,请设置 COLI_API_KEY。

Vite 开发服务器和 Tauri 本地源的浏览器访问默认已启用。重复使用 `--cors-origin https://your-ui.example` 可允许另一个精确源,或仅在受信任的本地网络上使用 `--cors-origin '*'`。

引擎拥有一个可变的 KV 上下文,因此 HTTP 生成使用有界 FIFO 准入队列,而不是假装运行不安全的并行序列。通过 `--max-queue N`(默认 8)和 `--queue-timeout SECONDS`(默认 300)进行配置,或使用 `COLI_MAX_QUEUE` / `COLI_QUEUE_TIMEOUT` 环境变量。饱和和超时的请求在流式传输头部发送之前会收到 OpenAI 格式的 HTTP 429 错误。`GET /health` 会暴露活跃/排队/已完成/被拒绝的计数器,成功的生成响应会包含 `x-colibri-queue-wait-ms`。

隔离的 KV 上下文

`coli serve --kv-slots N` 最多分配 16 个独立的序列上下文。请求通过可选的整数 `cache_slot` 字段选择一个;普通的 OpenAI 客户端会省略该字段并保持原始的 slot 0 行为。

{
  "model": "glm-5.2-colibri",
  "messages": [{"role": "user", "content": "Continue this conversation"}],
  "cache_slot": 1
}

每个 slot 拥有自己的 token 历史、压缩的 MLA/DSA KV 内存、MTP 窗口以及崩溃安全的持久化文件(`.coli_kv`、`.coli_kv.1` 等)。引擎仍然一次执行一个序列;这建立了明确的 KV 所有权,而不假装线程化 HTTP 是连续批处理。RAM 准入会考虑每个已配置的 slot。使用 `COLI_KV_SLOTS=N` 作为等效环境变量。从小值开始:在默认的 4096 token 上下文下,每个 slot 会消耗数百 MB。

实验性 Metal 后端(Apple Silicon)

在 Apple Silicon 上,解码阶段受矩阵乘法(matmul)限制,统一内存消除了让 CUDA 的流式专家停留在 CPU 上的 PCIe 拷贝开销——因此 colibrì 提供了一个可选加入的 Metal 后端,可在 GPU 上运行路由专家 SwiGLU(批处理,从 RAM slab 零拷贝)、融合解码注意力(一个命令缓冲区中的完整 MLA 层,S≤4)以及预填充阶段的大型 GEMM 操作。与 CPU 路径相比,token 结果完全一致。

cd c
make glm METAL=1          # macOS only; no Xcode needed (shader compiles at runtime)
make metal-test           # standalone kernel/attention correctness vs CPU reference
COLI_METAL=1 COLI_MODEL=/path/glm52_i4 ./coli chat --ram 96

在 M4 Max(128 GB,缓存预热,MTP 开启)上测得:CPU 0.30 → Metal 0.42 tok/s(约 1.4 倍)(最佳配置添加 DIRECT=1;相比本机首次冷启动约 3 倍)。关键设计要点:Metal 约 5 毫秒的提交延迟使得逐矩阵乘法调度得不偿失——所有操作被批量合并为每层少量命令缓冲区,且常驻专家的 GPU 工作会在未命中专家的磁盘读取之前提交,从而实现 I/O 与计算重叠。COLI_METAL_GEMM_MIN 用于调整预填充 GEMM 行阈值(默认 16)。流式传输、缓存、MTP、DSA 及持久化格式保持不变;所有 GPU 路径在发生任何故障时都会回退到逐块 CPU 处理。数值计算采用反量化→f32-MAC(与 CUDA 层级相同);贪婪解码输出与 CPU 引擎逐字节一致。

实验性常驻 CUDA 后端

colibrì 包含一个可选的 CUDA 后端,用于处理模型常驻张量。流式专家暂时仍保留在原始 CPU 路径上:每次使用都将专家从 NVMe 复制到 GPU,只会把磁盘瓶颈替换为 PCIe 瓶颈。常驻量化张量采用惰性上传方式,上传一次后重复使用。

cd c
make cuda-test CUDA=1                  # q8/q4/q2/f32 kernel correctness
make CUDA=1
# optional dense-path experiment (hot experts are configured below)
COLI_CUDA=1 COLI_GPU=0 CUDA_DENSE=1 SNAP=/nvme/glm52_i4 ./glm 64 4 4

要求:Linux 系统、NVIDIA 驱动程序以及位于 /usr/local/cuda 的 CUDA 工具包(可通过 CUDA_HOME=/path/to/cuda 覆盖)。CUDA_ARCH=native 针对当前机器中的 GPU 进行编译;交叉编译时需指定显式架构。若在仅 CPU 的二进制文件、无效设备或不可用运行时上请求 CUDA,将在启动时失败,而非静默回退。

正常的 make 构建和运行时行为保持不变。CUDA 默认作为仅限专家的加速器。CUDA_DENSE=1 会额外将常驻密集/注意力投影张量以轮询方式分配到所选设备上;其投影占用空间在放置专家层级之前预留。在六块 RTX 5090 上,搭配 150 GB 专家层级,预热后的两请求/64 token GLM-5.2 运行从 1.650 提升至 2.157 聚合 tok/s(+30.8%),同时保留完整的专家层级。在投影密集集和每设备 2 GB 运行时预留空间适配目标 GPU 之前,请将此视为可选功能。经过测量的 PIN 配置文件可将其最热门的专家提升至持久 VRAM 层级,同时将其他专家保留在 RAM 中。

STATS=stats.txt SNAP=/nvme/glm52_i4 ./glm 64 4 4   # collect routing frequencies first
COLI_CUDA=1 COLI_GPU=0 CUDA_EXPERT_GB=16 \
PIN=stats.txt PIN_GB=160 SNAP=/nvme/glm52_i4 ./glm 64 4 4
# multi-GPU expert tier, 150 GB total budget across six 32 GB devices
COLI_CUDA=1 COLI_GPUS=0,1,2,3,4,5 CUDA_EXPERT_GB=150 \
CUDA_DENSE=1 PIN=stats.txt PIN_GB=300 RAM_GB=226 \
SNAP=/nvme/glm52_i4 ./glm 64 4 4
# large-RAM host: fill safe VRAM, then keep every remaining expert in RAM
COLI_CUDA=1 COLI_GPUS=0,1,2,3,4,5 CUDA_EXPERT_GB=auto \
CUDA_DENSE=1 COLI_CUDA_ATTN=1 PIN=stats.txt PIN_GB=all RAM_GB=auto \
SNAP=/nvme/glm52_i4 ./glm 64 4 4

选定的专家会在启动时上传,因此容量故障发生在推理之前,日志会报告它们精确的张量占用空间。在预留了预估的密集常驻集以及每个选定设备 2 GB 运行时余量后,预算会被限制在空闲 VRAM 范围内。使用 COLI_GPUS 时,CUDA_EXPERT_GB 是整个设备集的总预算;专家会被完整分配给能够容纳它们且负载最低的设备。多 GPU 运行也默认启用 PIN_FILL=1:首先放置实测的热点集,然后用零热度专家填充未使用的 VRAM。CUDA_RELEASE_HOST=1(多 GPU 默认值)会在成功上传后释放 RAM 副本,并且仅在后续 CUDA 失败时才从磁盘重新加载。将任一变量设为 0 可恢复保守行为。当释放主机备份时,放置是分离且分阶段的:加载最热的前缀,上传到 VRAM,然后在下一个排名的后缀加载到 RAM 之前释放。因此,PIN_GB 描述的是合并后的排名集,而非重复的 RAM 和 VRAM 副本。在一台 256 GB 双插槽主机上,从 150 GB VRAM + 130 GB RAM 的放置方案切换到 150 GB VRAM + 150 GB RAM,固定 token 重放速度从 1.87 tok/s 提升至 2.16 tok/s(+15.7%),专家磁盘等待时间从 5.144 秒减少到 3.948 秒,并且预估的 RAM 峰值保持在 RAM_GB=226 以下。缓存上限会自动下调(在该次运行中从 54 降至 40),以便更大的固定层不会超出进程预算。在可用 RAM 较少的主机上,请从更低的数值开始。

CUDA_EXPERT_GB=auto 会为每个选中的设备自动填充,上限为该设备测得的空闲内存减去预估的稠密张量以及 2 GB 运行时余量。PIN_GB=all 随后会将所有剩余的路由专家加载到 RAM 中,从而在主机预算允许的情况下消除解码时的磁盘未命中。常规的 RAM_GB 保护机制仍然会限制每层工作缓存,并拒绝不安全的预估;此模式专为专用高内存推理主机设计,而非运行其他工作负载的桌面电脑。在一台配备六张 RTX 5090 的专用 251 GiB 主机上,此模式选择了 176.7 GB 的 VRAM 专家层级和 191.3 GB 的 RAM 层级(所有 19,456 个专家均驻留)。该模式还会每生成 16 个 token 就调整一次 VRAM 层级,方法是将热门的 RAM 专家交换到现有的 GPU 插槽中。一次真实的 64 token 贪婪解码 GLM-5.2 生成任务测得解码速度为 6.00 tok/s,而此前使用 150 GB 层级时的端到端速度为 2.20 tok/s;专家命中率为 100%,磁盘等待时间为零。提示词预填充速度另行报告。这是一个特定主机的容量结果,并非可移植的默认值。

文本模式的时间报告会将预填充与解码分开统计。解码速率从提示词 KV 构建完成后开始计算,因此其吞吐量可与 REPLAY 相媲美,且不隐藏首 token 生成时间。MTP 推测解码在 CUDA 上默认关闭,因为冷草稿路由会增加专家流量;显式的 DRAFT=n 仍会覆盖此默认设置。

在六张 RTX 5090 32 GB 显卡上,使用 GLM-5.2 int4 模型,一个 150 GB 的热优先层级在 64 token 的多样化提示词上维持了 0.94 token/s 的速度(专家命中率 87.8%),并在预热后的短提示词上达到了 1.64 token/s(命中率 99.3%)。同样的容量在没有路由热数据填充的情况下,仅能达到 0.29 token/s,因此配置文件的质量比原始 VRAM 容量更为重要。这些是单次运行的工程测量结果,并非可移植的性能保证。

当前限制:设备使用独立的上下文和同步的主机级激活副本——尚无 P2P/NCCL 依赖。独立的专家组跨设备并发执行,但单个专家不会被分片。这些内核是以正确性优先的自定义内核,而非 cuBLAS/Tensor Core 内核。

为了在不使用完整检查点的情况下实现可复现的后端 A/B 测试,请生成确定性的 3.13 亿参数 glm_moe_dsa 测试夹具,并运行固定 token 重放:

cd c
python tools/make_glm_bench_model.py --output /nvme/colibri-bench-medium --device cuda
python tools/benchmark_cuda_fixture.py --model /nvme/colibri-bench-medium --gpu 0

该测试夹具具有随机权重,并非语言模型。它仅用于保留真实的 MLA/MoE/流式形状,并使用相同的重放 token 来比较 CPU 流式、纯密集 CUDA、CPU 热存储和 CUDA 热专家执行。

网页界面

web/ 目录包含一个社区贡献的浏览器 UI(React + TypeScript,约 390 行源码,纯 API 客户端——它从不直接接触引擎):

cd web
npm ci && npm run dev        # then point it at an OpenAI-compatible endpoint

它采用标准 OpenAI Chat Completions 协议,支持 SSE 流式传输,因此可配合 colibrì OpenAI 兼容服务器(正在审核中,#21)或任何其他兼容端点使用。数据不会离开你配置的端点。终端 coli 聊天仍然是第一等接口。

实用调节参数(环境变量或标志):--temp T 设置 token 采样温度(默认 0.7 + nucleus 0.90——针对 int4 调优;0 为贪婪模式),--topp 0.7 自适应专家 top-p(减少 30–40% 磁盘用量),--ngen N 每次回答的最大 token 数(:more 可延续被截断的对话),--repin N 每生成 N 个 token 重新调整 RAM/VRAM 热专家,AUTOPIN=0 禁用学习缓存的自动固定,THINK=1 启用 GLM-5.2 的推理模块,DRAFT=n MTP 草稿深度,GRAMMAR=g.gbnf 语法约束草稿用于生成受限 JSON/NDJSON 输出(GRAMMAR_DRAFT=n 限制强制跨度长度),TF=1 教师强制验证,PILOT=1 路由器预取磁盘(实验性——见下文),CAP_RAISE=0 不自动扩展专家缓存。

资源策略

coli plan 会报告计划的热(VRAM)、温(RAM)和冷后备(磁盘)层级、每项放置的原因以及预期的瓶颈。默认的 --policy quality 和 --policy balanced 模式会保留检查点量化和路由器决策,除非传入了 --topk 或 --topp;这些显式的有损覆盖会打印警告并继续执行。

自动层级规划会根据物理核心数调整 OpenMP 大小,并将工作线程绑定到各核心上。当 SMT 兄弟线程竞争有限的内存通道时,内存受限的量化内核性能可能会急剧下降;显式的 OMP_* 设置始终具有更高优先级。

coli plan --model /models/glm52_i4 --policy quality
coli run --auto-tier --policy quality "Explain MoE offloading"
# Explicit research-only router reduction:
coli run --policy experimental-fast --topk 4 "Benchmark prompt"

磁盘是一种不可变的恢复源,而非正常的解码目标。如果方案将冷专家字节留在磁盘上,速度取决于缓存命中率;输出质量则不受影响。

冷专家读取采用延迟流水线:常驻 RAM/VRAM 的专家执行,同时缺失的专家在有限的后台 I/O 池中加载,随后冷结果在该层完成前汇入。当存在前台任务时,`IO_THREADS=n` 可覆盖默认的 8 个加载线程。性能分析报告会同时显示磁盘服务时间和较小的前台可见等待时间,从而使重叠部分明确可见,而非被归因于无法解释的加速。

`--policy balanced` 启用无损实时放置(`REPIN=64`)。在安全的请求边界处,每层的 LFRU 分数会结合衰减的会话频率与近期访问,并替换最多四个足够冷的固定专家。`--policy quality` 默认关闭实时替换;`REPIN=0` 始终禁用该功能。持久的 `.coli_usage` 历史记录与会话本地的 LFRU 状态保持分离。

对于单 token 的 q4 CPU 专家,门控投影与升维投影共享一个 OpenMP 分发,同时保留相同的逐行 AVX2/NEON 算术运算。这消除了每个 RAM 专家的一次线程团队启动,且无需激活重量化或降低精度回退。这是迈向持久原生 CPU 专家池的一块垫脚石,而非其替代方案。

专家缓存会根据你的 RAM 自动调整大小(自 2026-07-10 起):引擎现在会提高 LRU 上限以填满你的 `--ram` 预算,而不仅仅是降低它。在此修复之前,一台 128 GB 的机器与一台 16 GB 的机器运行着相同的每层 8 专家缓存(问题 #12)——如果你在此日期之前对 colibrì 进行了基准测试,请重新运行:你的数据曾受到上限限制。

路由器预取(PILOT=1,实验性功能):GLM-5.2 的专家路由具有可测量的提前可预测性——将第 L+1 层的路由器应用于第 L 层注意力后状态,可召回 71.6% 的真实 top-8 专家(相比之下,“与上一 token 相同的专家”策略仅为 41.3%)。PILOT=1 利用这一特性,在当前层计算的同时,通过专用 I/O 线程发出下一层专家预读请求。在我们的开发机上,磁盘已接近 80% 饱和,因此该功能测量结果为中性;在计算与磁盘负载均衡的机器上(如 issue #12 中的 Ryzen AI 9:磁盘 43% / 矩阵乘法 46%),它应该能实现实际工作重叠——欢迎提供测量数据。

学习型缓存:引擎会记录你的使用过程实际路由到了哪些专家(在模型旁生成 `.coli_usage` 文件,每轮对话更新),并在启动时自动将最热门的专家固定在空闲 RAM 中。colibrì 用得越多,速度就越快。

实时层级自适应(`--repin N`,可选加入):在安全的对话轮次边界,一个衰减的会话热力图会将冷门固定专家替换为更热门的流式专家。替换操作将专家从磁盘加载到现有 RAM 槽位中;GPU 后端槽位会立即刷新相同的 VRAM 层级预算。25% 的迟滞区间和四次交换上限可防止层级抖动。持久化的 `.coli_usage` 文件仍作为长期信号保留,不会衰减。

对话热恢复(`.coli_kv`,自 2026-07-10 起):coli chat 在每轮对话后将压缩的 MLA KV 缓存持久化到磁盘(约 182 KB/token,增量追加,崩溃安全)。关闭对话,第二天重新打开——模型仍能记住整个对话内容,且无需重新预填充:经验证,与不间断会话的字节级结果完全一致。`:reset` 可清除该缓存,`KVSAVE=0` 可禁用此功能。

网页仪表盘

一条命令即可在同一个端口上提供 OpenAI 兼容 API 和网页控制台,引擎就绪后自动打开浏览器:

cd web && npm install && npm run build   # once
./coli web --model <model-dir>

你将获得:

  • 带实时指标的聊天:生成过程中闪烁的 token 计数器,随后显示 tok/s、首 token 生成时间、提示词→补全计数以及队列等待时间;
  • 运行时面板:你的硬件信息(CPU、GPU + VRAM、RAM、核心数)、调度器,以及实时专家层级条——当前 19,456 个专家中有多少位于 VRAM / RAM / 磁盘中;
  • 大脑:整个模型是一个 76×256 的皮层,每个专家对应一个细胞。颜色代表层级,亮度代表路由热度,每一轮被路由到的专家会闪烁白色然后衰减——你可以亲眼看到模型在"思考"。悬停在任何细胞上,可查看其层级、热度以及测量到的话题亲和度(代码、中文、数学、法律等领域的专家分布在 11–22 层)。

仪表盘通过两条极简的协议线(TIERS、EMAP/HITS)和纯 JSON 端点与引擎通信——其负载不会超过引擎本身。

如果你有更好的机器,试试看——以下是预期效果

colibrì 是在刻意低调的硬件上构建的(12 核、25 GB 内存、一块位于 WSL2 VHDX 之后的无 DRAM 旧款 NVMe,该驱动器上测得随机读取约 1 GB/s——注意 WSL2 VHDX 本身并不慢:一台社区 5090 机器通过它测得 10.5 GB/s 的 O_DIRECT 速度,#101)。这些限制中的每一项,都是你的机器可以调高的旋钮。引擎需要:Linux(或 WSL2)、macOS 或原生 Windows 11(MinGW-w64);gcc 支持 OpenMP、AVX2、≥16 GB 内存,以及本地 NVMe(ext4/NTFS——绝不能是网络/9p 挂载)上约 370 GB 的 int4 模型。

如何按顺序测试:

cd c && ./setup.sh                 # build + architecture self-test (expects 32/32)

# 1) measure YOUR disk the way the engine uses it (parallel 19 MB random reads):
gcc -O2 -fopenmp iobench.c -o iobench
./iobench /path/to/glm52_i4/out-00069.safetensors 19 64 8 0   # buffered, 8 threads
./iobench /path/to/glm52_i4/out-00069.safetensors 19 64 8 1   # O_DIRECT (bypass cache)
# Caveat (#86): iobench reads a bounded ~1 GB shard, so buffered reads on a big-RAM box
# report the PAGE CACHE, not the disk. Use the O_DIRECT run (arg 1) for a true number, and
# run it on a shard you haven't touched this session (a prior buffered run caches its pages).
# On macOS there is no O_DIRECT — iobench uses F_NOCACHE, which stops *new* caching but can't
# evict pages a prior buffered run already resident-mapped, so a macOS "O_DIRECT" figure right
# after a buffered run still reads cache. Reboot or use a fresh shard for a real cold read.

# 2) chat; watch the per-turn stats line (tok/s, expert hit-rate, RSS):
COLI_MODEL=/path/to/glm52_i4 ./coli chat

# 3) record expert usage, then pin the hottest experts in your spare RAM:
STATS=stats.txt ./coli chat
PIN=stats.txt PIN_GB=20 ./coli chat        # scale PIN_GB to your free RAM

# 4) quality benchmarks (MMLU/HellaSwag/ARC):
./coli bench

粗略估算(解码受磁盘限制:一个冷 token 需要读取约 11.4 GB 的专家数据;缓存预热后,MTP 推测解码大致可将有效成本减半;RAM 能将冷读取变成免费的缓存命中):

机器 预期
本开发机(WSL2 VHDX,约 1 GB/s,25 GB 内存) 约 0.05–0.1 tok/s 冷启动——已验证的基准
原生 Linux,PCIe4 NVMe(随机读取约 3–5 GB/s),32 GB 内存 约 0.5–1 tok/s
PCIe5 NVMe 或 2×NVMe RAID0(约 8–12 GB/s),64 GB 内存(固定约 40 GB 的热门专家) 约 2–4 tok/s
128–256 GB 内存,12 核(热门专家已缓存) 约 2–4 tok/s——受矩阵乘法限制:约 80 GFLOP/token 对比我们 AVX2 内核的约 250 GFLOP/s
相同内存 + 24–32 核,或 AVX-512/VNNI 内核 约 5–15 tok/s——可交互;内核优化是倍增器

这些是估算值,并非实测数据——如果你在高端硬件上运行 colibrì,请提交 issue 附上你的数据:来自更好机器的真实数据点正是这个项目下一步所需要的。

社区基准测试(实测)

来自真实机器的真实数据,默认构建(setup.sh,gcc 13),贪婪解码,--ngen 32,MTP 开启:

机器 磁盘(iobench,19 MB × 64,8 线程) 配置 实测
英特尔酷睿 Ultra 7 270K Plus(24 线程)· WSL2 · 24 GB 内存 · NVMe VHDX(#2) 1.96 GB/s 缓冲 · 2.74 GB/s O_DIRECT 默认 0.07 tok/s · 专家命中率 3–4% · RSS 14.1 GB
同上 同上 --topp 0.7 0.11 tok/s · 专家命中率 11% · RSS 14.7 GB
Apple M5 Max(18 核)· macOS · 128 GB 统一内存 · 内置 SSD(#4, #5) 约 4 GB/s 冷启动(14.2 GB/s 的读取速度受缓存影响——参见注释) 默认,MTP 关闭 1.06 tok/s · 专家命中率 23% · RSS 21.8 GB
Apple M5 Max · macOS · 128 GB 统一内存 · 2 TB SSD · Metal 后端(#72, #87) (macOS 的 O_DIRECT 数值不可靠——参见注释) Metal 开启 · --ram 96 · 39.7 GB 热固定 · MTP 关闭 1.83 tok/s · 专家命中率 66% · 预热后从 1.11 升至 1.83(运行过程中)
同上 · 46.9 GB 固定(2.94M 选择历史)· --ram 110,1024 token 运行(#103) 同上 Metal 开启(专家 + 注意力)· MTP 关闭 2.06 tok/s · 命中率 72.5% · 输出连贯 · 迄今为止最快的数据点(仍在 rebase 前的 Metal 分支上)
Mac Mini M4 Pro · macOS · 48 GB 统一内存 · Metal 后端(#107) 6.59 GB/s F_NOCACHE(新分片) Metal 开启 · --ram 38 0.30 tok/s(对比纯 CPU 的 0.18)—— 该条目显示,内存仅为三分之一的 Apple Silicon 击败了 32 核 9950X 行
Epyc 9654 ES · Linux · 4x16GB DDR5-4800-rdimm · 三星 PCIe Gen3 x4 NVME SSD MTP=1 DIRECT=1 0.31 tok/s · 专家命中率 35% · RSS 21.52 GB
Ryzen AI 9 HX 370(Framework 13)· Arch Linux · 128 GB · WD SN850X,BTRFS zstd(#12) int8 MTP 头 · --cap 32 · 46.7 GB 自动学习 PIN 0.37 tok/s · 专家命中率 66% · MTP 接受率 52%(2.59 tok/fw)· RSS 105 GB
Ryzen 9 9950X(32 线程)· Linux · 123 GB · Crucial P3 QLC Gen3(#31) 1.51 GB/s 缓冲 默认,冷启动运行 2 次 0.10 tok/s · 命中率 53% · 分析:66% 磁盘
同上,同一台机器,模型移至三星 9100 PRO PCIe 5.0(#31) 8.81 GB/s O_DIRECT 同上(使用历史保留) 0.28 tok/s · 命中率 57% · 分析翻转:32% 磁盘 / 57% 矩阵乘法
Ryzen AI Max+ 395(Framework Desktop)· Ubuntu · 128 GB LPDDR5x · 英特尔 Optane 905p PCIe 3.0(#39) 3.27 GB/s 缓冲 int8 MTP 头 · 全新历史(纯 LRU,自动提升上限 65) 0.16 tok/s · 命中率 57% · 分析:49% 磁盘 / 47% 矩阵乘法
同上,五次运行后 —— 学习固定 47.6 GB(#39) 同上 --temp 0.7 --topp 0.7 0.40 tok/s · 命中率 71% · 非 Apple 设备中最快数据点
Ryzen 7 9800X3D(16T)· WSL2 · 70 GB 内存 · 三星 9100 PRO PCIe 5.0 · RTX 5090(#101) 10.51 GB/s O_DIRECT MTP 关闭 · 固定内存 24 GB · 命中率 54% · OMP 热团队开启 0.41 tok/s · 磁盘瓶颈(磁盘 36.5 秒 vs 矩阵乘法 24.0 秒)· CUDA 专家层级 ≈ 0%(AVX-512 CPU 与 5090 持平)· --topp 0.7 → 0.52 tok/s
EPYC 7443(24核/48线程,Zen3 AVX2)· Linux · 430 GB 内存 · 通过 TrueNAS 虚拟机实现的 NVMe RAID-Z1(#104) 约 1 GB/s(虚拟机开销) 固定内存 77.5 GB · 上限自动提升至 194/层 · MTP 关闭 1.00 tok/s · 命中率 98% · 磁盘瓶颈消除 → 受限于内存带宽 + 矩阵乘法(Zen3 无 AVX-512/VNNI)
Intel i5-12600K(10核/16线程,AVX2)· 原生 Windows 11,无 WSL · 32 GB · MinGW GCC 16.1(#113) 缓冲模式(MinGW 上无 O_DIRECT) int8 MTP 头 · 冷启动,小内存(上限约 2/层) 0.08 tok/s · 命中率 3.7% · MTP 接受率 57%——首个原生 Windows 数据点,移植验证通过
Ryzen 9 9950X3D2(16核/32线程,avx512-vnni)· 原生 Linux · 121 GB · Samsung 9100 PRO PCIe Gen5 · RTX 5090(28 GB 专家层级,固定内存 1475)(#120) 11.48 GB/s O_DIRECT MTP=0 DIRECT=1 PIPE_WORKERS=16 PREFETCH=1 1.23 tok/s · 关闭 MTP 在磁盘瓶颈场景胜出 · 目前最快的 x86 数据点
Ryzen AI Max+ 395(Strix Halo,16核/32线程 Zen5,avx512-vnni)· Arch Linux · 128 GB 统一 LPDDR5x 内存 · SK hynix P41 PCIe 4.0(#124) DIRECT=1 PIPE=1 --topp 0.7 · 自动固定内存 冷启动 0.06 → 稳定 1.10 tok/s · 首个 Strix Halo / gfx1151 数据点(统一内存:无独立显存层级)
Intel Core Ultra 9 185H(16核/22线程,avx-vnni)· 原生 Windows 11,无 WSL · 32 GB · Crucial P3 QLC NTFS · RTX 5070 Ti(未使用)(#128) int8 MTP 头 · 配合 #131(管道 + 内存修复),缓存预热,无 GPU 冷启动 0.03 → 预热后 0.5 tok/s(约 7 次提示词预热)· 修复可移植性阻塞后,原生 Windows 上的缓存预热——在 #131 之前,主线版本在 \r\n READY 哨兵处挂起
Dell Pro Max GB10(DGX Spark:Grace 10×X925 + 10×A725,aarch64 i8mm/sve2)· Linux · 121 GB 统一 LPDDR5x 内存 · Dell OEM 4 TB NVMe · GB10 sm_121(#136) 5.58 GB/s O_DIRECT(#76 中的 NVIDIA-OEM 设备为 10.74——同一平台,不同 SSD) int8 MTP 头 · 缓存预热 冷启动 0.21 → 预热后 0.50 tok/s · 命中率 83% · MTP 接受率 73%(3.20 tok/前向传播)· 矩阵乘法瓶颈(矩阵乘法 130 秒 vs 磁盘 58 秒)——统一内存,CUDA 放置层级中性;此处杠杆在于 i8mm 计算内核,而非放置策略

要点总结:在拥有 24 GB 内存的机器上,引擎会自动将专家缓存上限设为每层 2 个槽位,因此即使使用比开发机快 2–2.7 倍的磁盘,解码阶段仍然处于冷状态——在小内存机器上,内存上限(而非磁盘)才是真正的约束瓶颈,这与上表预测完全一致;仅 `--topp 0.7` 一项参数就带来了 1.6 倍的端到端速度提升。M5 Max 的数据点恰好落在表格的第二行:在笔记本 SSD 上运行 744B 模型,速度约为 1 token/秒——其 14 GB/s 的磁盘将瓶颈转移到了内存预算和内核上。Framework 13 的各行数据则是在同一台机器上端到端验证了缓存理论:仅通过为缓存分配内存(int8 MTP 头 + 更大的容量上限 + 学习到的固定策略),速度就从 0.29 token/秒提升至 0.37 token/秒(命中率从 28% 提升至 66%,推测机制终于在 52% 的接受率下开始生效)。容量上限部分现已实现自动化(容量自动提升功能,2026-07-10)。9950X 组合是目前最清晰的瓶颈实验——同一台机器,相同的运行历史,仅更换了磁盘:5.8 倍的磁盘带宽换来了 2.9 倍的 token 数,且性能分布从 66% 的磁盘瓶颈转变为 57% 的矩阵乘法瓶颈。但这一转折点取决于 CPU 内核:第 #101 行的 9800X3D 数据显示,在启用 OMP 热团队调优后,AVX-512 CPU 矩阵乘法速度足够快,以至于即使是 10 GB/s 的 NVMe 固态硬盘也仍然是磁盘瓶颈——此时 CUDA 专家层级带来的提升约为 0%,因为 CPU 在专家矩阵乘法上已经与 5090 相当。GPU 层级只有在 CPU 成为薄弱环节时才能发挥其显存优势,而非默认情况。(对 #101 的诚实更正:该报告的早期版本在关闭 OMP 调优的情况下运行,人为制造了虚假的矩阵乘法瓶颈转折点以及虚假的 14% CUDA 提升——这两点在重新干净运行后均不复存在。)

质量基准测试——寻求帮助

第一项测量结果已出炉(#108,感谢 dnnspaul):int4 容器在 hellaswag/arc/mmlu 上取得了 62.5% 的平均 acc_norm(0-shot 对数似然,n=40)——低于全精度 GLM-5.2 已公布的 85–95%,但这一差距目前还不能归因于量化。有两个混淆因素横亘其中:(1)0-shot 对数似然多项选择评分方式严重不利于 GLM-5.2 这类推理模型(它根本没有思考的机会),因此即使在 fp16 下,出现较大差距也是意料之中;(2)n=40 的误差幅度为 ±14 个百分点。决定性的实验是在同一测试框架下对 OLMoE 进行 fp16 与 int4 的 A/B 对比(该模型足够小,两种精度都能运行)——两者之间的差值就是量化代价,同时评分协议带来的影响已被抵消。在完成这项实验之前,62.5% 只是一个数据点,而非最终定论。

代码已就绪,一条命令即可端到端运行(首次使用时会自动下载数据集):

cd c
pip install tokenizers datasets                # in addition to the convert deps above
./coli bench                                   # hellaswag, arc_challenge, mmlu — 40 questions each
./coli bench hellaswag --limit 200             # one task, more questions
./coli bench mmlu arc_challenge --ram 100      # pick tasks, set a RAM budget

它会输出每个任务的准确率(对数似然评分,EleutherAI-harness 风格)。如果你能运行 OLMoE 的 fp16 与 int4 A/B 对比(或进行大样本量的 GLM 运行),请通过 issue 提交数据——这项测量结果将决定 62.5% 究竟是"int4 没问题,评分方式导致的假象",还是"量化是瓶颈,分组量化才是优先方向"。

支持本项目

colibrì 是一个单人项目,完全在一台 12 核、25 GB 内存的笔记本电脑上编写和测试——上述数据是我在家所能测量的上限。如果你觉得这个项目有用或有趣,并希望支持其开发(更好的测试硬件将直接转化为更快的引擎,惠及所有人:真实的 NVMe 扩展数据、更大的固定缓存、在真实基准上对 int2/int3 质量进行扫描),你可以:

  • ⭐ 给仓库点星并分享它;
  • 🐛 提交 issue,附上你硬件上的基准测试数据;
  • 💬 如果你想赞助开发或捐赠硬件,请通过 GitHub issues 联系我。

每一份贡献,无论是一个数据点还是一块硬盘,都在推动上限的提升。

仓库布局

Makefile                  root build/check entry point
c/
├── glm.c                 single-file GLM engine
├── st.h, tok.h, json.h   runtime headers
├── backend_cuda.*        optional CUDA tier
├── Makefile              build and local checks
├── coli                  user-facing CLI
├── openai_server.py      OpenAI-compatible HTTP gateway
├── setup.sh              one-command local setup
├── tools/                offline conversion, fixtures and benchmarks
├── scripts/              long-running conversion helpers
└── tests/                dependency-free C and Python tests
web/                      browser UI (pure OpenAI-API client, community-maintained)

运行时路径刻意保持扁平且易读:glm.c 及其少量头文件。辅助性的 Python 和 Shell 工具被单独分组,且永远不会成为引擎的运行时依赖。

在仓库根目录下,make、make check 和 make clean 会委托给引擎的 Makefile 执行。从 c/ 目录运行的现有命令仍可正常工作,无需修改。

为什么叫“colibrì”

蜂鸟只有几克重,能悬停在空中,每天访问上千朵花。这个引擎让一个拥有 7440 亿参数的庞然大物,仅靠蜂鸟般的“口粮”就能运行:25 GB 内存、十二个 CPU 核心,以及大量的磁盘耐心。

许可证

Apache 2.0。GLM-5.2 权重由 Z.ai 以 MIT 许可证发布。