第 1 章 · 02 纯 C 零依赖与一个 .c 一个模型族 本节摘要:本节讲清 Colibrì 的两条架构红线——纯 C 零引擎依赖(无 BLAS、无 Python 运行时、无 GPU 必须),与一个 一个模型族( GLM-5.2 / / / / )。介于两者之间的,是一组共享头文件( / / / )——所有模型族都 include 它们,机制集中在头里,一改全改。这条规则不是装饰,反复出现的缺陷就是"某机制只落在一个引擎、没传到兄弟引擎"。顶层 只用一行委托给 , / / 统一入口。读完本节,你理解了 Colibrì 仓库的整体形状。 内容来源:原项目源码 ("The idea" 段)、顶层 、 目录文件清单与行数统计。
本节摘要:本节讲清 Colibrì 的两条架构红线——纯 C 零引擎依赖(无 BLAS、无 Python 运行时、无 GPU 必须),与一个
.c一个模型族(colibri.cGLM-5.2 /deepseek_v4.c/inkling.c/kimi_k3.c/olmoe.c)。介于两者之间的,是一组共享头文件(st.h/quant.h/tok.h/expert_store.h)——所有模型族都 include 它们,机制集中在头里,一改全改。这条规则不是装饰,反复出现的缺陷就是"某机制只落在一个引擎、没传到兄弟引擎"。顶层Makefile只用一行委托给c/Makefile,make/make check/make clean统一入口。读完本节,你理解了 Colibrì 仓库的整体形状。
内容来源:原项目源码
README.md("The idea" 段)、顶层Makefile、c/目录文件清单与行数统计。
⚠️ 注意:"零引擎依赖"指的是运行时不需要 BLAS/CUDA/Metal 这类引擎库——它们是可选后端(CUDA=1/METAL=1/VULKAN=1 才编译进来),不是必须。CPU-only 路径只用标准库和 OpenMP,能在任何带 C 编译器的机器上
make出来。
阅读完本节,你应当能够:
.c 文件名与各自行数。Makefile 一行委托的写法和 repo layout。README.md "The idea" 段最后一句给 Colibrì 的极简画像:
The engine is a single C file (
c/glm.c) plus small headers. No BLAS, no Python at runtime, no GPU required.
注意三个"no":
quant.h 里写了多架构 SIMD 的 matmul 内核(AVX2/AVX-512/NEON/VSX,第 2 章详讲)。colibri/cli.py、repack_*.py),但推理时不需要 Python 运行时。coli chat 启动的是纯 C 编译出来的二进制。CUDA=1/METAL=1/VULKAN=1),不编就是 CPU-only,照样能跑。为什么选纯 C?Colibrì 的隐含理由可以归纳成三点:
make 就出二进制。c/Makefile 头部用 gcc -dumpmachine 探测目标三元组,自动识别 mingw/cygwin/darwin/linux/powerpc,这是 C 的天然优势。ColiExpertStoreOps),贴近硬件。README.md 说 "the engine is deliberately small enough that the next useful optimization can come from anyone willing to measure it"——引擎刻意保持小到任何人愿意测量就能贡献优化。纯 C 是这套"开放研究平台"哲学的载体。💡 深潜要点:不要把"纯 C"误解为"落后"。Colibrì 选 C 是有意识的设计选择,目的是把"软件/硬件边界"上的每一处优化(模型格式、内存层级、I/O、放置、调度、kernel、推测、CPU/GPU 重叠)都暴露给研究者和贡献者。C++的抽象层、Python 的运行时,都会把这条边界糊掉。
补充一点:C 路径上唯一的"重型依赖"是 OpenMP——quant.h:13-15 用 #ifdef _OPENMP 条件引入 omp.h,matmul 内核用 #pragma omp parallel for 多线程。OpenMP 是 C/C/Fortran 的标准编译制导(几乎所有主流编译器 gcc/clang/msvc 都内置),不算"引擎依赖"。即便没有它,代码也能编译(退化成单线程),只是慢。c/omp_tune.h 还专门做 OpenMP 调优(线程数、调度策略),这是 Colibrì 把"软件/硬件边界"暴露到极致的又一例——连线程数都让用户量着调。
第二红线:一个 .c 文件对应一个模型族。仓库 c/ 目录下的五个引擎源码及行数(wc -l 实测):
| 模型族 | 引擎源码 | 行数 |
|---|---|---|
| GLM-5.2(744B) | c/colibri.c |
9514 |
| DeepSeek V4 Flash(284B) | c/deepseek_v4.c |
10993 |
| Inkling(975B) | c/inkling.c |
2250 |
| Kimi K3(2.8T) | c/kimi_k3.c |
1938 |
| OLMoE(7B) | c/olmoe.c |
1211 |
每个 .c 是完整的、自包含的推理引擎——它知道这个模型族的架构(层数、隐藏维度、MoE 拓扑、attention 变体)、知道怎么路由、怎么算 attention、怎么解码。从行数能看出规模差异:olmoe.c 只有 1211 行(7B 小模型,最简单),deepseek_v4.c 有 10993 行(284B,但 attention 变体 MLA 复杂、还含 native FP8 读取路径)。
这种"一模型一文件"的设计有几层好处:
.c 里。colibri.c 和 deepseek_v4.c 直接读。c/Makefile 让你选择编哪个目标(make glm/make deepseek-v4),不用的模型不编进来。但这条规则有个内在张力:很多机制是所有模型族都需要的(safetensors 解析、量化解码、tokenizer、专家缓存)。如果每个 .c 都自己写一份,代码会爆炸式重复,且某个 bug 修了一处忘了同步另一处——这就是下一节"共享头文件"要解决的问题。
介于"五个独立 .c"和"一份共享代码"之间的,是一组所有引擎都 include 的头文件。它们承载了"所有模型族都需要的通用机制":
| 头文件 | 行数 | 作用 |
|---|---|---|
c/st.h |
852 | safetensors 索引与范围读取(第 2 章) |
c/quant.h |
1569 | 量化容器解码器 + 多架构 SIMD matmul(第 2 章) |
c/tok.h |
581 | tokenizer(O200K / BPE) |
c/expert_store.h |
99 | 专家流式缓存抽象 + lease 契约(第 3 章) |
c/tensor.h |
47 | ColiTensorView 容器格式枚举 |
设计规则可以一句话总结:
一个引擎拥有自己的架构;两个引擎都需要的机制——放头文件,所有引擎 include,一改全改。
为什么是头文件而不是独立的 .c?因为 Colibrì 追求"单文件可编译"——每个引擎 .c 直接 #include "st.h"/#include "quant.h"/#include "expert_store.h",所有函数都是 static inline(header-only),编译时整个引擎就是一个翻译单元,没有链接步骤,没有动态库依赖。这种风格在 quant.h:1-3 的注释里写得很直白:
1 /* quant.h — quantized matmul kernels (header-only, all functions static). 2 * Multi-architecture SIMD: AVX2 / AVX-512 / AVX-VNNI / ARM NEON / NEON-SDOT / 3 * NEON-i8mm / POWER VSX. Pure compute — no Model or QT dependency. */
三个关键修饰:header-only(纯头文件)、all functions static(全 static,允许每个 .c 各自包含不冲突)、pure compute — no Model or QT dependency(纯计算,不依赖任何模型结构体)。
⚠️ 注意:这条共享头文件规则不是装饰,而是 Colibrì 维护者反复强调的纪律。源码注释里到处可见"反复出现的缺陷就是某机制只落在一个引擎、没传到兄弟引擎"的反思——例如
st.h早期版本只支持 BF16/F16/F32 三种 dtype,加 F8_E4M3 时如果只改colibri.c不改deepseek_v4.c(它要读 native FP8 权重),就会在 DeepSeek V4 的某个 I64 张量处直接exit(1)。所以新机制必须先落到头里,再让所有引擎同步受益。
仓库根的 Makefile 只有一行有效内容,极其朴素:
1 .PHONY: all glm deepseek-v4 portable test check cuda-test clean install uninstall 2 3 all glm deepseek-v4 portable test check cuda-test clean install uninstall: 4 $(MAKE) -C c $@
这是一个透传 Makefile:无论你 make/make check/make clean/make glm/make deepseek-v4,它都委托给 c/Makefile,把目标名 $@ 原样传过去。所有真正的编译逻辑都在 c/Makefile(里面用 gcc -dumpmachine 探测平台、按目标选 CC、按变量 CUDA=1/METAL=1/VULKAN=1 决定要不要编 GPU 后端)。
整个 repo 的 layout:
colibri-main/ ├── c/ # 纯 C 引擎核心(本教程的精读对象) │ ├── colibri.c # GLM-5.2(9514 行) │ ├── deepseek_v4.c # DeepSeek V4(10993 行) │ ├── inkling.c # Inkling(2250 行) │ ├── kimi_k3.c # Kimi K3(1938 行) │ ├── olmoe.c # OLMoE(1211 行) │ ├── st.h quant.h tok.h expert_store.h tensor.h ... # 共享头 │ ├── backend_cuda.h backend_metal.h backend_vulkan.c # GPU 后端 │ ├── Makefile # 真正的编译逻辑 │ └── tools/ # 打包/重打包 Python 脚本 ├── colibri/ # Python CLI(cli.py)、resource_plan、openai_server ├── web/ # 浏览器 UI(纯 OpenAI-API 客户端) ├── desktop/ # Tauri v2 桌面壳 ├── docker/ # 容器 ├── docs/ # 文档(FORMATS.md/benchmarks.md/media/) └── Makefile # 顶层透传 Makefile
注意 c/ 目录是本教程前 8 章的全部精读对象;colibri/、web/、desktop/、docker/ 是第 9 章的 CLI/服务/Web 全栈。docs/ 里的 FORMATS.md 是第 2 章 02 节的主角(格式注册表治理)。
💡 深潜要点:顶层 Makefile 的"透传一行"是 Colibrì 工程文化的缩影——核心机制都在
c/,Python/Web/Desktop 都是壳。后续章节你会反复回到c/目录,把它当成整本书的舞台。
.c 一模型族:colibri.c(9514)/deepseek_v4.c(10993)/inkling.c(2250)/kimi_k3.c(1938)/olmoe.c(1211)。st.h/quant.h/tok.h/expert_store.h/tensor.h,header-only、all static、pure compute,一改全改。make/make check/make clean 委托给 c/Makefile,所有编译逻辑在 c/。下一节,我们走完 per-token 的五步路径(route→union→place→overlap→learn),并理解 Colibrì 的"诚实研究"风格——每个优化都是可证伪假设,必须受控端到端 A/B 验证。