使用29 GB内存以0.50 tok/s运行Kimi K3
摘要
WASTE是一个新的开源C语言推理引擎,它从磁盘流式加载专家权重,在仅29 GB内存的消费级笔记本电脑上运行拥有2.78万亿参数的Kimi K3模型,实现了0.49–0.54 tokens/s的速度。
查看缓存全文
缓存时间: 2026/07/31 20:00
sqliteai/waste
來源:https://github.com/sqliteai/waste
WASTE — 权重感知流式张量引擎
Kimi K3 — 2.78 万亿参数 — 在消费级笔记本电脑上运行。
$ waste run ~/models/k3.waste 'What is the capital of Italy?' waste: no --budget, using 46.24 GB of 64.00 GB (expert cache 17.56 GB) The capital of Italy is **Rome**. [16 tokens, 31.09 s, 0.51 tok/s | experts 3357 hit / 20195 miss = 14%]
WASTE 是一个用 C 语言编写的可嵌入推理引擎,没有第三方运行时依赖。它将模型主干保留在内存中,直接从磁盘流式读取选中的专家(expert),并将剩余 RAM 用作有界专家缓存。
它目前证明了完整开放权重的 Kimi K3 模型:2.78 万亿参数,转换为 982 GiB 容器,在 64 GB MacBook Pro 上以 0.49–0.54 token/s 运行。这不是蒸馏、剪枝或缩小版本。
| 模型 | 容器 | 最低 RAM | 实测速度 |
|---|---|---|---|
| Kimi K3 2.78T | 982 GiB | 29.05 GiB | 0.49–0.54 tok/s |
| Kimi-Linear 48B | 19 GiB | 1.87 GiB | 10.7 tok/s |
WASTE 是为那一个模型和那一个约束而写的:K3 放不进当前主流消费级系统的 RAM。 它发布时是 1.42 TB,转换后是 982 GB。但混合专家模型每个 token 只激活自身约 4% 的参数,因此在任何瞬间,几乎所有权重都处于空闲状态——空闲权重不需要放在内存里,它只需要能及时到达。WASTE 将其保存在磁盘上,采用一种布局:一个专家恰好对应一次读取,流式读取每个 token 实际需要的内容,并把剩余每一字节 RAM 都用于重复出现的部分。
当前进展
引擎是正确的:每一层都对照 PyTorch 参考实现验证过,最终 logits 一致到 3.6e-06,视觉塔与其自身 oracle 一致到 2.3e-06。它也很慢——每秒半个 token,上面那句话需要三十秒。
这两点都很重要,而第二点不应被理解为免责声明。据我们所知,还没有其他公开演示在消费级机器上从磁盘流式运行如此规模的模型:我们没有找到任何万亿级 NVMe 流式的先例,而资料最完整的 671B 级方案假设服务器拥有一 TB DDR5。这是我们搜索结果的报告,而不是综述——这个仓库没有参考书目,也没有对比表格,所以请把它视为邀请你发送反例,而非一项结论。有趣的部分不是速度,而是整个事情在单台消费级机器上就可触及——并且从这里开始,问题是工程问题,而不是可行性问题。
杠杆所在之处已经不是原来的位置。将专家读取与算术运算重叠带来了约 1.6 倍收益,已经发布;两个看起来更大的杠杆——每个 token 读取更少的字节,以及让更多字节留在 RAM 中——都经过测量并都被拒绝了:一个是因为这个家族的 router 没有可降级的尾部,另一个是因为无论出多少钱都买不到一个机器不会留在内存中的缓存。即使读取已经重叠,它们仍占解码步骤的 55%,而算术只占 27%,所以剩下的出路是更快的磁盘或更大内存的机器,而不是再对内核做一轮优化。docs/EFFICIENCY.md 记录了每个方案如何定价,包括两个先构建后测量的方案。
这具体打开了什么前景:一个前沿规模的模型,无需网络、无需按 token 计费、没有任何数据离开机器——这就是“你不可以把那些数据发送到 API”和“就在这里运行”之间的区别。格式和引擎在任何深层意义上都不是 K3 特有的;K3 只是当前存在的最难案例,一个能以 2.78T 规模流式运行的模型,在 48B 规模下自然也能流畅运行。
本文档中的每一个数字都是在发布该文档的 commit 上测得的,那些曾经有误的数字在 docs/LEARNED.md 中如实记录为错误,而不是悄悄修正。
为什么叫这个名字
每一次由云服务回答的 token 都要被支付两次:一次在账单上,一次在数据中心的电费里——它们在运行一个其实可以——勉强、笨拙、但真实地——放在桌面已有硬件上的模型。WASTE 希望成为终结这种 token 浪费的第一步。缩写是后来才有的。
你需要什么
| 磁盘,用于模型 | 982 GB 用于转换后的容器——请按 1 TB 规划 |
| 磁盘,用于转换 | 发布分片还需要另外 1.42 TB 暂存空间,之后可释放 |
| RAM | 在 4K 上下文打开 K3 至少需要 29.05 GB;本文数据基于 64 GB |
| 存储速度 | 容器必须放在内置 NVMe 上——见下文 |
| 构建 | C11 编译器和 make。运行时不需要 BLAS、CUDA 或 Python |
这里的大小采用 2 的幂,和 df 及引擎的报告一致:容器是 982 GiB,磁盘厂商会称之为 1.05 TB。
RAM 下限是引擎拒绝低于此值启动的阈值,它几乎全部来自 27.28 GB 常驻主干。有意义的吞吐量从更高处开始:在 64 GB 机器上,引擎给自己分配 46 GB 预算,其中 17.56 GB 是专家缓存,这就是实测曲线的顶点。32 GB 机器技术上可以打开模型,但会严重换页;请把 64 GB 视为真正的需求。
存储速度不是细节。 一个 token 要读取 17 GB 专家数据。在内置 SSD 上是 12.78 GB/s,模型可以流式运行;通过 USB 硬盘盒则只有 0.94 GB/s,同一个 token 需要十三秒。请在内置 NVMe 上转换,外部磁盘只用来下载。
如果拿不出一 TB 空间,同一个引擎和同一种格式可以从一个 19 GB 容器运行 Kimi-Linear-48B-A3B-Instruct,下限 1.87 GB,速度 10.7 tok/s。这是在把一整块磁盘投给 K3 之前试玩 WASTE 的好路径。
它是什么
- 自包含。 一个
libwaste.a,一个waste二进制,运行时只需要 libc 和 pthreads。 - 零依赖。 推理路径中没有 BLAS、没有 ONNX、没有 Python,没有任何需要安装的东西。
tools/下的 Python 用于转换模型和验证引擎;它不会与引擎同时运行。 - 完全可嵌入。 src/waste.h 中有 26 个公开函数:在 RAM 上限下打开模型、生成、保存会话、关闭。CLI 是该 API 的客户端,不触碰任何私有内容——如果 CLI 能做到,嵌入宿主也能做到。
``c waste_cfg cfg; waste_cfg_init(&cfg); cfg.ram_budget_bytes = 46ULL << 30; /* 硬上限,不是提示; 0 表示按本机自动定容 */
waste_ctx *ctx; if (waste_open(“/path/to/k3.waste”, &cfg, &ctx) != WASTE_OK) return 1; waste_generate(ctx, ids, n, ¶ms, on_token, user); waste_close(ctx); ``
路径是转换器写入的容器目录——这里不做 ~ 展开,那是 shell 的工作。
工作原理
布局决定速度
一个模型会被一次性转换为 .waste 容器:一个 JSON 清单、一个常驻主干、每层一个专家库。每条专家记录按 4 KiB 对齐,gate、up、down 矩阵彼此相邻,因此路由到一个专家恰好需要一次 pread——不是三次,也不是每个矩阵一次寻道。算术从来不是瓶颈。
读取绕过页缓存(macOS 上 F_NOCACHE,Linux 上 O_DIRECT,Windows 上 FILE_FLAG_NO_BUFFERING)。这是故意的:如果容器小于 RAM,内核会缓存一切,那样测得的命中率是虚构的,遇到 982 GB 模型就会露馅。
每条记录的头在进入时都会被检查——正确的魔数、索引请求的专家、适合的偏移——因此被截断或拼接过的专家库会停止生成并指出具体记录,而不是从错误字节返回答案。这几乎没有任何可测开销。记录还携带其负载的 crc32,而检查那个是 --verify,默认关闭:它会在每次缓存未命中时扫描每条记录,在 Kimi-Linear 上约 5%,在 K3 上约 1%。对于复制或下载后许久未读的容器,值得一用;对于自己转换并每条 token 都读的容器,则不划算。参见 docs/FORMAT.md。
每个专家权重三比特
专家以残差向量量化存储——三级 256 项码本,作用于 8 维向量,每权重 3.00 比特——并且矩阵从不实例化。对于每个 token,引擎构建一张部分点积表,每个码本条目、每个向量位置一项;之后每个专家行就是三次查表和两次加法。
主干保持 4 比特和 8 比特。模型只在专家上进行了量化感知训练,因此它对被压缩的主干没有训练出的容忍度:曾构建并测量过 3 比特主干,缓存预测成立,吞吐量没有成立,输出崩溃了。
缓存下限是一个 token 的工作集
这是本项目中最有预测力的数字。K3 每个 token 在 92 层中各触及 16 个专家:17.0 GB。低于这个值,一个为一个 token 缓存的专家会在下一个 token 请求之前被逐出,命中率不是低——而是零。高于这个值,曲线急剧弯折。
| 预算 | 专家缓存 | 命中率 | 解码 |
|---|---|---|---|
| 32 GB | 3.32 GB | 0% | 0.31 tok/s |
| 46 GB | 17.32 GB | 13% | 0.32 tok/s |
| 52 GB | 23.32 GB | 27% | 0.11–0.14 tok/s |
| 58 GB | 29.32 GB | 37% | 0.04 tok/s |
按此顺序在空闲机器上实测。顺序很重要:在 52 和 58 GB 两行把机器推到换页后再跑一次,46 GB 得到 0.22–0.25 而不是 0.32——而命中和未命中计数与数字完全一致。引擎是确定性的;机器不是,而且它在两次运行之间不会完全恢复。请向上扫描。
解码列先于预读(read-ahead)实现,尚未重新扫描:46 GB 现在跑在 0.51 而不是 0.32。表格的意义在于形状,预读不会改变形状——它把 I/O 藏在算术后面,这让每一行都更快,但不会让任何一行变成不同的预算。
内存设计中的一切都是为了让系统越过那条线,这也是为什么引擎致力于释放 RAM,而不是节省 RAM。
而另一边还有一个上限,比看起来更近。 请把那张表读两遍:命中率一路都在攀升。在 64 GB 机器上以 58 GB 预算运行时,缓存从 RAM 服务 37% 的专家,而引擎比 46 GB 预算时慢八倍——那时它服务 13%。引擎在自己的预算之内;但机器不在,于是 OS 把专家缓存换到磁盘,一次“命中”变成一次缺页,而不是引擎原本在管理的磁盘读取。
所以可用窗口很窄。它在约 46 GB 处打开,此时缓存终于超过一个 token 的工作集;而在 52 GB 之前它已经关闭——即使是在空闲机器上、运行前还有 49 GB 可用内存的情况下。这个窗口还尖锐到会在看似无关的变化下移动:把 1.11 GB 嵌入表从常驻集中移走,在固定预算下直接转化给缓存,这就足以把 58 GB 从 0.32 tok/s 推到 0.04。
因此默认配置不会填满机器。 专家缓存只有按这个工作集的整倍数才值得,超过倍数的余量只能换来几个百分点的命中率,同时把机器推向换页。当引擎为自己选择预算时,它一次下降一个完整工作集,取 RAM 八分之七以内最大的倍数:K3 请求 floor + 3×——80.63 GB——在这台笔记本上拿到 floor + 1×,即 46 GB 预算和 17.56 GB 缓存。这就是上面曲线的顶点,不需要任何 flag。128 GB 机器仍能获得完整的 3×。
早期版本会拿满上限内的每一字节,于是这台机器上得到 27 GB 缓存——落在两个实测为 0.11 和 0.04 tok/s 的预算之间。真正的教训是:你无法控制的缓存不是缓存;推论是:引擎应该在 OS 开始收回内存之前就停止要求内存。
线性注意力,以及吸收式 KV 缓存
K3 的注意力是 3:1 混合:Kimi Delta Attention,它携带固定大小的循环状态而不是不断增长的 KV 缓存,以及门控多头潜在注意力。MLA 层缓存 512 宽的潜在向量,而不是展开的每头键和值,kv_b_proj 被吸收进 query 和输出:
q_nope · (W_kb c) == (W_kbT q_nope) · c Σ_s a_s (W_vb c_s) == W_vb (Σ_s a_s c_s)
logits 一致到 1.2e-05,缓存减少 53 倍:4K 上下文下 11.25 GB 变成 0.21 GB。这也让长上下文成为可能——展开布局在 128K token 时需要 360 GB,潜在布局只需要 7.2。
性能与内存
MacBook Pro M5 Pro,64 GB,容器在内置 SSD 上。每个数字都在发布它的 commit 上实测。
Kimi K3 — 2.78T 参数,982 GB 容器
| 最低 RAM | 29.05 GB,4K 上下文 |
| 32K 时 30.54 GB,128K 时 35.63 GB,1M 时 83.21 GB | |
| 常驻主干 | 27.28 GB |
| 每 token 读取 | 17.0 GB,双线程预读以与矩阵乘法重叠 |
| 模型加载 | 20 s |
| 预填充 | 分块 0.47 tok/s,顺序 0.29(预读之前) |
| 解码 | 默认预算下 0.49–0.54 tok/s,这是这台机器的最佳值 |
| 视觉塔 | 1024 patch 图像 15.7 s,27 层 |
| 提示中的图像 | 896x896 占 256 个位置,每个 2.8 s——按文本计 |
下限几乎完全来自常驻主干。有意义的吞吐量从约 46 GB 以上开始,此时专家缓存终于超过一个 token 的工作集;到 52 GB 又消失了,因为机器开始换页。低于第一条线,额外 RAM 买不到任何东西;高于第二条线,代价惨重。在这台机器上,窗口只有一个预算那么宽。
视觉塔并不是图像的真正成本。编码 1024 个 patch 需要 15.7 s;它产生的 256 个位置随后像任何其他 token 一样经过 92 个 MoE 层,这部分是另外 731 s。图像按等长文本计价,因此 vision.json 中的 patch 预算是一个真正的旋钮:网格减半,提示长度也减半。
Kimi-Linear — 48B 参数,19 GB 容器
| 最低 RAM | 1.87 GB |
| 解码 | 10.7 tok/s,8 GB 预算,78% 缓存命中 |
同一个引擎、同一种格式,跑在一个轻松容纳的模型上。这就是 WASTE 不需要搏斗时的样子。
时间花在哪里
K3 解码,17.32 GB 缓存且仍然很冷——十步中命中 6.7%,这是新提示开始时的状态:
| 占比 | |
|---|---|
| MoE,全部 | 82.5% |
| 其中专家 I/O | 53.5% |
| 其中专家矩阵乘法 | 20.0% |
| KDA 层 | 14.5% |
| MLA 层 | 2.8% |
| lm_head | 0.2% |
用 WASTE_PROFILE=1 WASTE_CACHE_MB=17735 ./test_forward MODEL 1008,10484,318,15383,387 out.bin 5 复现。I/O 占比会随着缓存变热而下降,因此长时间会话会比这个值低;排序不会改变。
I/O 已经接近硬件极限——每个 token 17.0 GB,约 9.9 GB/s,而 SSD 实测 12.78——所以它只能通过减少发生次数来变便宜,这意味着缓存,意味着 RAM。这就是目前全部的优化故事,也是为什么下一步是关于内存而不是算术。
快速开始
bash git clone https://github.com/sqliteai/waste && cd waste make # libwaste.a, waste, libwastevq make check # 全新克隆上 23 通过,11 跳过
没有 configure 步骤,没有依赖解析。make check 不需要模型:它构建一个小型合成容器并针对它运行引擎。那十一个跳过项是需要克隆体不携带东西的检查——PyTorch oracle、与源分片的往返、任何用文本驱动 CLI 的检查(因为合成容器没有 tokenizer),以及想要容器和发布文件的 K3 检查。两项都准备好后:
bash tools/convert.py --model ~/models/Kimi-K3-278B-Instruct ~/models/k3.waste tools/verify.py ~/models/k3.waste ~/models/Kimi-K3-278B-Instruct \ --layers 0,10,42,91 --steps 3 ./waste run ~/models/k3.waste # 默认预算, 不需要 flag ./waste run --budget 32g ~/models/k3.waste # 强制下限 ./waste run --verify ~/models/k3.waste # 每条记录的 crc32
转换器在纯 PyTorch + NumPy 中运行(在 tools/HARDWARE.md 中配置分片),每步约 15–20 分钟,K3 约 90 个小时;验证器将输出的 logits 与 PyTorch 参考逐层比较,因此它覆盖了整个栈——量化、格式、读取、数学——而不只是发动机某个孤立部件。转换时使用的确切版本记录在发布的 manifest 中,因此下次该版本的发布分片发生变化时,verify.py 会指出这个偏差——这正是设计意图。
相似文章
Kimi K3 在家用实验室的首批结果 ~ 4 tokens/秒
家用实验室环境下 Kimi K3 的首批基准测试结果显示,推理速度约为每秒 4 个 token。
WASTE 推理引擎(14 分钟阅读)
WASTE 是一个开源推理引擎,通过将专家权重存储在 NVMe 上,运行比主机可用内存大得多的模型。它展示了在配备 64GB 统一内存的 MacBook Pro 上运行 Kimi K3(一个 2.78T 参数的 MoE 模型)的能力。
我成功运行了Kimi-k3......
用户成功使用llama.cpp在高端硬件上运行Kimi-k3模型,实现了较低的每秒token数(提示评估0.41,生成0.23)。
@jun_song:正在尝试将 Kimi-K2.6 (1T) 适配到 128GB Mac 上。目标是达到 40tok/s,并尽可能减少质量损失。
一位开发者正在优化 Kimi-K2.6 (1T) 模型,使其能在 128GB Mac 上高效运行,目标速度为 40 tok/s,同时尽可能降低质量损失。
有人试过Q1 Kimi K3吗?(555GB)
Kimi K3是一个庞大的2.9万亿参数混合专家模型,拥有1040亿活跃参数,100万上下文长度,原生支持MXFP4训练,现已提供从540GB到更小尺寸的GGUF量化版本,但运行需要强大的硬件。