- 人工智能
- 大模型
- 推理引擎
- 本地部署
【免费下载链接】kimi-k3-in-c
A 2.78-trillion-parameter Kimi K3 running inference on a single CPU in 8.24 GB of RAM. Portable C99: no BLAS, no framework, no GPU.
本文围绕kimi-k3-in-c仓库中一份调查笔记 compressed-trunk.md 展开:该项目曾尝试对 bf16 稠密主干(trunk)做无损熵压缩,把 108 GB 级文件压到约 67%,以在"流式读取"预算下直接换取每 token 耗时;压缩方案完整实现并通过了字节级往返验证,却因标量解码器只有约 0.31 GB/s 每核的吞吐而最终被搁置。读完本文,你会理解熵压缩在 I/O 受限推理管线中的适用边界,以及"压缩率不是唯一变量,解码速度才是"这一用真实测量数据得出的工程结论。
背景:为什么 trunk 的字节数直接等于延迟
要理解这次实验,先看它作用的对象。Kimi K3 的 2.78T 参数中,MoE 专家是 MXFP4,而所有非专家组件(注意力投影、latent MoE 投影、共享专家、路由器)保持高精度——这部分正是"trunk"。官方技术报告中明确列出了这些未量化组件,事后 4-bit 量化在真实 K3 权重上会引入 12% 输出误差(int8 为 0.54%),所以 trunk 必须按字节原样搬运,这也是 tools/pack_trunk.py 开头注释反复强调"流式是无损的"的原因。
在低内存预算下,引擎每个 token 都要按固定层序(layer 0..92)重读整个 108.81 GB 的 trunk。TUNING.md 给出的算术很直白:给 trunk 多 1 GB 预算,就能钉住(pin)约一层,永远不再读它,约等于消除 1.17 GB/token 的确定性流量;而引擎在低预算下每 token 要搬运约 135 GB 数据,存储带宽通常是天花板而非 CPU。
于是"压缩 trunk"的诱惑非常自然:在流式预算下,trunk 少几个字节,就是每 token 少几秒。压缩比越高,SSD 读取时间越短。这个思路的逻辑链完整、无损、且与引擎输出零冲突——问题出在解码侧,这正是本文的主角。
核心思想:bf16 高字节的熵结构
实验的出发点是一个测量事实:trunk 是 bf16 格式,而 bf16 值的高字节(符号位 + 指数位)在这个 checkpoint 上只携带约 2.8 bit 的真实信息——粗略地说,十几个不同的字节取值就覆盖了 99.9% 的所有权重。换句话说,指数平面是一个极端偏斜的分布,香农熵远低于 8 bit。
由此得到方案的核心设计(见 compressed-trunk.md 的 "The idea" 一节):
- 只对高字节平面做熵编码(Huffman),把偏斜分布换成变长码;
- 低字节(尾数)平面按噪声处理,原样存储——测量表明它不具备可利用的统计结构;
- 解码出来的字节就是 checkpoint 自己的字节,因此整个方案是无损的,引擎输出一个 token 都不会改变;
- 整体效果:打包后的 trunk 缩小到约67%的体积。
为什么不做整块 LZ 类压缩?搁置原型头的注释里给出了已测量的答案(见 k3_huf.h.shelved):LZ 家族编解码器的解码速度慢了一个数量级,追不上硬盘读取速度,所以只选纯 Huffman。这是一个典型的"先用测量排除一条路线"的决策。
已实现的部分:规范限长 Huffman 编解码器
容器格式
编码器是打包时的一次性 Python 工具(huf_encode.py.shelved),解码器是引擎侧的纯 C 头文件(k3_huf.h.shelved),只解码、不编码。格式按 k3_huf.h.shelved 的定义组织:
[ K3HufLayerHdr ] 字节平面字母表的规范码长(codelen[256]) stripe 0: [K3HufStripeHdr][奇字节平面的 Huffman 位流][偶字节平面原样] stripe 1: ...关键设计点:
- stripe 并行:每个 stripe 覆盖 64 MiB 原始数据(
K3_HUF_STRIPE,k3_huf.h.shelved),各 stripe 独立解码,天然可按 stripe 并行; - 奇偶平面分离:bf16 小端存储下,奇数偏移正是高字节(指数平面)——只有这一半被 Huffman 编码,偶数偏移的尾数字节逐字节原样复制;
- 码长限制在 12 bit(
K3_HUF_MAXLEN):编码器把更深的树压平,于是解码器只需一张1 << 12项的表,一次加载即得符号与码长(sym_len打包为(symbol << 4) | code_length,见 k3_huf.h.shelved)。
规范码分配与 Kraft 校验
解码器建表函数 k3_huf_build 做了两件事,两者都是格式正确性的基石:
- Kraft 校验:
sum(count[l] << (MAXLEN - l))必须恰好满或不满 12-bit 码空间;超满(over-subscribed)或为空都判定为损坏的 trunk 而非继续解码垃圾数据; - 最长优先的规范码分配:先算出每个码长的起始码
first[l] = code; code = (code + count[l]) << 1,再按符号序填充,把每个码在 12-bit 表中展开为其覆盖的全部前缀区间。头文件特别警告:这套"最长优先规范分配"必须与 Python 编码器完全一致,改一方必须改另一方。
Python 侧的 canonical_codes 实现了同一套规范分配,code_lengths 用标准 Huffman 树累积深度生成码长,并带有 BZip2 风格的限长修正(_limit在 Kraft 超满时反复加长最低频码)。对一个"约 12 个高频符号、12 bit 上限"的字母表,限长修正实际上几乎不会触发,但正确性被要求"触发时也必须对"。
解码循环 k3_huf_decode_stripe 经过两轮手写优化:位累加器把流的首部对齐到窗口顶端,一次 refill 约服务 8 个符号(而非每符号一次);偶平面拷贝在奇平面解码完成后以独立循环完成。
验证结果
在真实 trunk 字节上,Python 编码、C 解码,字节级精确往返;在 4 MB 样本上实测1.45 倍压缩(比率 0.689),与理论预期的 ~67% 一致。格式、Kraft 校验、规范码分配全部验证通过。至此,"压缩"这一半是完成且正确的。
让方案被搁置的测量:解码速度
标量解码器的天花板
手写的标量 Huffman 解码器经过两轮优化,只达到~0.31 GB/s 每核。把这个数字代入真实场景:
- 目标设备是3 GB/s 的笔记本 SSD(trunk 流式读取的带宽来源);
- 要在这个速度下持续喂饱压缩 trunk,需要约10 个核专职解码——笔记本没有这么多核。
由此得出笔记中最锋利的一句话(compressed-trunk.md 原文):
这样建成的压缩,帮助的是那些有 RAM 到根本不需要它的多核机器,却饿死了真正需要的笔记本。这与目标背道而驰。
注意这个悖论的结构:压缩收益与解码成本发生在同一批机器上,但两者与核数/内存的关系是反的。内存充裕的机器本来就把 trunk 钉进 RAM(零读取、零压缩开销),核少的笔记本才被迫流式读盘、才最需要少读 33% 的字节——却也正是它们解不动这个码流。
快速熵解码器也不行
是否存在足够快的熵解码器?存在——FSE/Huff0 在同一批指数平面字节上实测 1724 MB/s。但两笔账依然不划算:
- 即便以 1724 MB/s 计,追上一块笔记本 SSD 仍需2 个专职解码核,占走笔记本核心资源;
- vendoring 它约需2000 行代码,而本项目的立身之本是一个 176 KB 的零依赖二进制(无 BLAS、无框架、无 GPU)。收益配不上重量,至少对"在乎的那些机器"如此。
这是全文最可迁移的工程教训:对 I/O 受限管线做无损压缩,必须同时给"压缩后字节数 × 磁盘带宽"和"解码吞吐 × 可用核数"两张账,只看第一张会把方案带进死胡同。
如果将来重启:解锁条件
笔记的 "If revisited" 一节给出了明确的重启判据(compressed-trunk.md 原文):
- 解锁条件是一个落在1~1.5 GB/s 每核区间、同时保持体积小的解码器。达到这个区间,单核即可逼近甚至超过笔记本 SSD 的喂数速度,压缩收益立刻成立;
- 标准路线有两条,且都能让现有编码器原样保留(格式不变):
- 每个 stripe 用4 条交错位流,用指令级并行(ILP)打满流水线;
- 双符号表(double-symbol table),每步解码两个符号、摊薄查表开销;
- 仓库里的两个原型是正确的起点,格式今天就能往返——缺的只是一个足够快的解码核。
换言之,这个方案的"死亡证明"只针对当前解码实现;数据特征(2.8 bit 熵)、格式(stripe + 奇偶平面分离 + 12-bit 规范表)与编码器都仍然有效。
结论:今天真正生效的 lever 是什么
在快速解码器到手之前,笔记给出的替代结论是:流式 trunk 的速度杠杆是钉层(pinning,即 RAM 优先的--preset auto)与驻留式 int8 草稿模型,而不是压缩。这与仓库其他文档的测量互相印证:
- TUNING.md 的预设表显示
server档(110 GB trunk 全钉 + 13 GB cache)约 17 s/token,且"给 trunk 的 1 GB 比给专家 cache 的 1 GB 边际价值高约 70 倍"(见 speed-2026-08.md 中--preset auto的说明);ARCHITECTURE.md 也描述了 trunk 流式"环形缓冲 + 钉住前缀"的实现,与压缩方案最终竞争的正是这条路线; - int8 草稿路线的完整账本见 int8-draft-container.md:容器、q8 内核、cache-only 路由都建好且位精确,但驻留混合解码实测 53 s/token 不敌精确解码的 19.8 s/token——因为草稿仍要流式读 25.8 GB/ token 的 MXFP4 专家。两条"非压缩"路线同样经历了"建出来、测出来、按数据取舍"的过程,与本文的 Huffman 实验构成同一套方法论的两次实例。
对读者的三点直接启发:
- 无损压缩的价值 = 少读的字节 × 存储带宽 ÷ 解码代价,三者缺一不可;本例中 33% 的字节削减被 0.31 GB/s 的解码核完全抵消;
- 先测数据分布再选编码:2.8 bit 的指数平面熵让 Huffman 一步逼近理论极限(1.45x vs 理论 1/0.689 ≈ 1.45x),而尾数平面测出是噪声就果断放弃;
- "搁置"不等于"删除":
.shelved原型保留了完整格式与双端实现,Kraft 校验、规范码分配的"改一方必改另一方"警告都写在头文件里——一旦 1~1.5 GB/s 每核的解码器出现(4 交错位流或双符号表都是公开的标准手段),这个方案可以直接从正确起点重启。
- 人工智能
- 大模型
- 推理引擎
- 本地部署
【免费下载链接】kimi-k3-in-c
A 2.78-trillion-parameter Kimi K3 running inference on a single CPU in 8.24 GB of RAM. Portable C99: no BLAS, no framework, no GPU.
相关推荐
gh_mirrors/di/directory背后的技术:GitHub数据抓取与评分算法实现
gh_mirrors/di/directory背后的技术:GitHub数据抓取与评分算法实现 GitHub 加速计划(di/directory)是一个可搜索、可
抖音批量下载去水印:用 douyin-downloader 把一位作者的作品完整存下来
抖音批量下载去水印:用 douyin downloader 把一位作者的作品完整存下来 跑完之后,你会得到一批井井有条的本地文件:某位作者全部作品的无水印视频,
网页爬虫CLIHuffman 编码:基于贪婪策略的无损压缩原理与 cosmos 多语言实现剖析
Huffman 编码:基于贪婪策略的无损压缩原理与 cosmos 多语言实现剖析 Huffman 编码是信息论与数据压缩领域最经典的无损压缩算法之一,其核心思想
教程示例工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考