对应 Maps to:CMU 11-868 / 11-968 Large Language Model Systems(Spring 2026,Lei Li)课表末尾列出、本学期未排课的主题 LLM Serving on Heterogeneous Hardware(slides:llmsys-28-mooncake-kTransformer.pdf,Mingxing Zhang @ KVCache.AI / 清华大学,70 页)。 阅读材料:Qin et al. (2025) Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving(FAST 最佳论文;arXiv 2407.00079);Chen et al. (2025) KTransformers: Unleashing the Full Potential of CPU/GPU Hybrid Inference for MoE Models(SOSP)。 依据说明:slides 五部分。动机:更多数据 + 更大模型 + 更长上下文 = 更高的智能,也 = 更高的服务负载(Kimi 2024 年 3 月支持 200 万字输入、频繁”服务繁忙”;DeepSeek-V3 / R1 的长输出);不同硬件擅长不同维度(H800 / H20 / 至强 + DDR5)。Mooncake:以 KV 缓存为中心的分离式架构、预填充 / 解码分离 vs 分块预填充、KV 缓存对存储的挑战、全局 vs 本地缓存、Mooncake Store 与传输引擎、评测(有效请求容量最多 +498%、节省 29%–61% 的 GPU 计算)、开源与被 Dynamo / SGLang / vLLM 采用。KTransformers:MoE 的稀疏化趋势、本地部署的硬件门槛、CPU 内存适合稀疏模型、按算术强度卸载、预填充的 AMX 内核、解码的 CUDA 图 / NUMA 感知的张量并行 / 专家推迟、开源。教程:用 KTransformers + LLaMA-Factory 在本地做 LoRA 微调、用 SGLang + KTransformers 推理。本讲义的硬件账、全局缓存与过载调度的模拟、DeepSeek-V3 的解码时间账、在城市语言上训练的小 MoE 与”专家推迟”的准确率实验,都是本讲义自己设计的,不代表课堂上讲了什么;slides 声明其中的价格”不准确,只是演示”。 配套代码 Code:
code/appendixA2/(3 个脚本 +hetero.py;第一次运行 03 号脚本会训练一个小 MoE 约 1 分钟) 预计阅读时间:2.5 小时(含运行代码)
0. 本讲导航 · How to read this lecture
0.1 学习目标 Learning goals
- 用”算力、带宽、容量”三个维度比较 GPU 与 CPU 服务器,说明预填充、解码、KV 缓存、冷门专家各适合放在哪种硬件上。
- 说出 Mooncake 的架构:预填充 / 解码分离 + 由集群闲置的 CPU、内存、SSD 组成的分布式 KV 缓存池;解释全局缓存池为什么比本地缓存好、传输引擎为什么要聚合多张网卡。
- 解释过载时”提前拒绝”的动机、它引起的负载振荡,以及按预测拒绝的思路。
- 说出 KTransformers 怎样让一张 GPU + 一台 CPU 服务器跑 6710 亿参数的 DeepSeek-V3:按算术强度放置、AMX、CUDA 图、NUMA 感知、专家推迟。
0.2 先修与本讲范围
| 默认你已经会 | 本讲只给直觉 |
|---|---|
| 预填充 / 解码分离(第 26 讲);KV 缓存的存储与传输(第 27 讲) | RDMA、GPUDirect 的细节 |
| MoE 与专家并行(第 17 讲);量化(第 19 讲) | CPU 微架构(缓存、NUMA)的细节 |
| 屋顶线与算术强度(第 4 讲) | LoRA 微调的流程(第 23 讲已讲原理) |
0.3 本讲地图
§1 为什么要异构:不同的硬件擅长不同的维度 ← 代码 01
§2 Mooncake:以 KV 缓存为中心的分离式架构 ← 代码 02
§3 Mooncake:过载时的调度 ← 代码 02
§4 KTransformers:CPU + GPU 混合跑 MoE ← 代码 03
§5 小结 §6 常见误区 §7 练习 §8 延伸阅读 §9 下一讲预告
1. 为什么要异构 · Why heterogeneous hardware
1.1 负载在增长
slides 开头的一个公式:更多数据 + 更大模型 + 更长上下文 = 更高的智能;换个角度也是 = 更高的服务负载。Kimi 在 2024 年 3 月支持 200 万字的输入后迅速走红,尽管多次扩容推理集群,仍然频繁”服务繁忙”、限流;DeepSeek-V3 / R1 带来了很长的输出(推理链)。要服务这样的负载,不能只是”多买一样的 GPU”。
1.2 每种硬件擅长一个维度
slides 第 7 页把三种硬件放在一起(价格只是示意):
| H800 | H20 | 至强 SPR + 8 × DDR5-4800 | |
|---|---|---|---|
| 规格 | 80 GB,3.3 TB/s,约 1 PFLOPS | 96 GB,4 TB/s,约 200 TFLOPS | 512 GB,8 × 40 GB/s,< 20 TFLOPS |
| 每美元最划算的是 | 算力 | 带宽 | 容量 |
| 适合 | 预填充 | 解码 | KV 缓存 |
01 号脚本用 slides 后面给出的另一组示意价格(A100 约 1.5 万美元,CPU 服务器约 8 千美元)算”每千美元买到什么”:A100 买到 20.8 TFLOPS、133 GB/s、5.3 GB;CPU 服务器买到 2.5 TFLOPS、40 GB/s、64 GB——算力差 8 倍、带宽差 3.3 倍,容量却反过来便宜 12 倍(每 GB 显存约 187 美元 vs 内存约 15.6 美元)。
H800 与 H20 跑 LLaMA-3.1-70B(8 卡,固定效率的屋顶线):预填充 8K token,H800 0.26 秒、H20 1.75 秒(算力差 6.7 倍);批 1 的解码一步,H20 5.6 ms 反而比 H800 的 6.6 ms 快(带宽 4.0 vs 3.35 TB/s)。所以 H800 做预填充、H20 做解码——第 26 讲的预填充 / 解码分离让这种按阶段挑硬件成为可能(Splitwise 也是这个思路)。批开得很大时解码也会变成计算受限(批 64:H20 13.7 ms vs H800 10.6 ms),解码节点的批大小、显存容量要一起规划。
KV 缓存呢?一台 8 × H800 的服务器放下 70B 模型后,显存只能放约 137 万个 token 的 KV——Kimi 的平均输入有 8,590 个 token,只够约 159 个请求;同一台机器的 2 TB 内存能放约 610 万个,SSD 能放上亿个。集群里有大量闲着的 CPU、内存和 SSD——这是 Mooncake 的出发点。
2. Mooncake:以 KV 缓存为中心的分离式架构 · Mooncake
2.1 架构
Mooncake 是 Kimi 的服务平台(月之暗面与清华大学 KVCache.AI 团队),slides 第 11 页的三句话:
- 预填充 / 解码分离,架构以分布式 KV 缓存池为中心;
- 用更多的存储换更少的计算(trading more storage for less compute)——让 Kimi 的吞吐提高 75%;
- 满足 SLO(TTFT 与 TBT)。
组件:
- 预填充池:每个实例有自己的 GPU 显存(分页的 KV)和本地的 CPU / 内存 / SSD;长上下文用分块的流水线预填充;
- 解码池:连续批处理;
- 分布式 KV 缓存池(Mooncake Store):所有节点的 CPU 内存与 SSD 组成一个池子,节点之间用 RDMA 传 KV;
- Conductor(全局调度器):为每个请求选一对预填充 / 解码实例。选预填充实例时不只看负载,还看”这个实例上能命中多长的前缀”与”要从远处搬多少 KV”——估计每个实例上的 TTFT(排队 + 传输 + 预填充未命中的部分),选最小的;达不到 SLO 就直接返回 HTTP 429。选解码实例时按负载均衡,并检查 TBT 的 SLO。
为什么要分离,而不是分块预填充?slides 第 14–16 页:分离把两个阶段的干扰彻底去掉,SLO 更好控制;而且两个阶段需要不同的并行策略(DeepSeek-V3 / R1 就是如此,第 26 讲),分离已经成为必然。
2.2 KV 缓存对存储的挑战
每个 token 的 KV 是”2 × 层数 × 隐藏维度”,几十 KB;而值得复用的 KV 总量很大——10B 级模型几百 GB、100B 级几 TB、TB 级模型几十 TB 到 PB。缓存的命中率随容量增长;整体上需要 PB 级的缓存,远超一台机器。Mooncake 论文用 Kimi 的真实请求(平均输入 8,590 个 token、输出 182 个)做了分析:全局缓存池的容量从 1,000 块增加到 50,000 块,命中率从 34% 升到 55%;而且块的热度极不均匀——超过一半的块从未被复用,少数块被访问上万次,热门块需要复制以免传输拥塞。
2.3 全局缓存池 vs 本地缓存
02 号脚本第 1 部分(8 个预填充实例;20,000 个请求,400 篇长文档按 Zipf 分布被问):
| 每个实例的缓存 | 做法 | 命中率 | 最忙实例 / 平均 |
|---|---|---|---|
| 1,000 块(0.5M token) | 本地缓存,轮流派发 | 51.4% | 1.04 |
| 本地缓存,同一文档固定发给同一实例 | 95.6% | 1.54 | |
| 全局缓存池 | 96.6% | 1.08 |
本地缓存加轮流派发:同一篇热门文档在 8 个实例上各存一份,有效容量只有 1/8。按文档固定派发避免了重复,却把热门文档压在少数实例上(第 22、26 讲的缓存感知路由也面对这个取舍)。全局缓存池两者兼得——任何实例都能取用任何一块,代价是跨机传输。slides:全局缓存的命中率高于本地缓存,节省 29%–61% 的 GPU 计算。
2.4 传得够快:传输引擎
02 号脚本第 2 部分:一段 128K token 的 LLaMA-3-70B KV 约 42 GB。单张 200 Gb/s 网卡要约 2 秒;Mooncake 的传输引擎把一台机器上的多张网卡聚合起来、按拓扑选路(选离 GPU 近的网卡)、支持多种协议(RDMA、NVMe-oF……),并提供零拷贝的接口——slides 的实测:4 × 200 Gb/s RoCE 达到 87 GB/s(线速的 87%),8 × 400 Gb/s 达到 190 GB/s。重算这 128K 个 token 的预填充约 10 秒(注意力是平方的),所以即使单网卡也快约 5 倍,聚合后快 21–46 倍——“用存储换计算”成立。
Mooncake Store 的其他特性:弹性(500 GB 内存 + 8 张 RDMA 网卡的节点 80 秒内加入)、多层存储(内存 → SSD)、可配置的副本数与放置(软固定、偏好的段)、Put / Get / 批量 / 零拷贝的接口。它独立于推理引擎:vLLM、SGLang(HiCache)都能接;训练框架也能用它(P2P Store 做 RL 中的权重快速分发,checkpoint-engine)。
2.5 效果与影响
slides 第 21–22 页:有效请求容量(满足时延要求的请求数)比 vLLM(包括开启前缀缓存与分块预填充的 vLLM)最多提高 498%;论文报告在模拟场景里吞吐最多提高 525%,在真实负载上让 Kimi 多处理 75% 的请求。SGLang + Mooncake 的一个部署(3 个预填充 + 9 个解码节点、DeepEP + EPLB、双批重叠)每个节点每秒 52.3K 输入 token、22.3K 输出 token。
开源的时间线:2024 年 3 月 Kimi 走红、用 Mooncake 应对流量;6 月发布技术报告;11 月开源;2025 年 2 月获 FAST 最佳论文;NVIDIA Dynamo 的架构受它启发(GTC 2025 主题演讲提到,Dynamo 的传输库 NIXL 把它作为后端之一),SGLang 的分布式架构与它共同开发,vLLM 也已集成。
3. Mooncake:过载时的调度 · Scheduling under overload
3.1 过载是常态
大多数服务系统的研究假设”所有请求都会被处理”。现实中,用户请求的增长远快于集群扩容的速度,高峰期过载是常态。系统要在负载达到阈值后拒绝(或推迟)一部分请求。分离式架构带来一个独特的问题:预填充与解码之间有时间差。
3.2 提前拒绝与负载振荡(Mooncake §7)
- 基线:预填充实例只看自己的负载接纳请求;预填充做完、要进入解码池时,才发现解码池满了(预计 TBT 超标)——这次预填充白做了,长上下文的预填充很贵。
- 提前拒绝(early rejection):请求一到,就同时看预填充池与解码池”现在”的负载,有一个超载就拒绝。
- 问题:它看的是”现在”的解码负载,而这个请求要排队、做完预填充(长上下文要十几秒)才进入解码池。论文观察到预填充与解码机器的负载出现反相位振荡:解码池满时拒绝一切,预填充池随之空闲;解码池空了又大量接纳,十几秒后这些请求一起涌进解码池,解码池又满……集群利用率因此很差。预填充机器越少、预填充越慢,振荡越明显。
- 按预测提前拒绝:预测这个请求进入解码池时解码池的负载,据此决定。Mooncake 用的是系统级的预测——假设每个请求的解码都花同样的时间,把”那时已完成预填充的请求”加进解码池、把”那时已经解码完的”移出,算出预计的 TBT 负载;请求级的输出长度预测留作未来工作。
论文的实测(8 个预填充 + 8 个解码实例,23,000 个真实请求以 2 倍速回放):被拒绝的请求从 4,183(基线)降到 3,771(提前拒绝)、3,589(按预测)。
02 号脚本第 3 部分(两个池各能处理约 2 个请求 / 秒,到达 2.6 个 / 秒,1 小时):
| 接纳策略 | 完成 请求/秒 | 白做的预填充 | 预填充池利用率 | 解码池利用率的波动 |
|---|---|---|---|---|
| 基线 | 1.730 | 12.5% | 100% | 0.116 |
| 提前拒绝(看现在) | 1.698 | 11.2% | 97% | 0.123 |
| 按预测提前拒绝 | 1.694 | 9.3% | 94% | 0.117 |
| 按预测 + 超订 10% | 1.733 | 12.3% | 100% | 0.118 |
玩具模型给出的是一个取舍而不是论文那样的”全面更好”:看”现在”的提前拒绝几乎没减少浪费、完成的请求反而少了、波动略大(时间差的问题);按预测拒绝把白做的预填充减少约四分之一,代价是更保守、少完成约 2%;适度超订又回到基线。原因之一是这里的解码时间是方差很大的指数分布,“按平均值预测”的误差大。论文的收益本身也不大(多处理 2–3% 的请求),但它指出的问题是真实的:分离式架构里,接纳决策必须看到未来的负载。
4. KTransformers:CPU + GPU 混合跑 MoE · KTransformers
4.1 稀疏化的趋势与本地部署的门槛
slides 第 41–43 页:开源模型的前十名里,2024 年有 2 个是 MoE,到 2025 年 10 个全是。MoE 把一个大的 FFN 换成几百个小专家、每次只激活 6–8 个(第 17 讲)。总参数越来越大(DeepSeek-V3 6710 亿、Kimi K2 1 万亿),传统的”全放 GPU”方案需要 8 × H20 或 4 × A100 这样昂贵的硬件。
观察:CPU 内存特别适合稀疏模型——容量便宜一个数量级,而稀疏专家每次只读很小一部分,带宽的要求不高。
4.2 按算术强度放置
03 号脚本第 1 部分:DeepSeek-V3 的 6710 亿参数里,路由专家 654B(58 层 × 256 个),每个 token 只用其中 8 个(20.4B);注意力(MLA)、稠密层、共享专家、嵌入约 17B,每个 token 都用。
批大小 B 时,一个路由专家的参数平均只被 B × 8 / 256 个 token 用到——B = 64 时也才 2 个:读一次权重只做很少的计算(算术强度低)。注意力、共享专家每个参数被 B 个 token 用到(算术强度高)。KTransformers 的卸载优先级:路由专家 > 共享专家 > 注意力——算术强度越低越先放到 CPU,并且让 CPU 就地计算(不把权重搬上 GPU)。结果:GPU 只要约 18 GB(8 位;MLA 的 KV 也很小,一张 24 GB 的消费级显卡就够),CPU 内存约 368 GB(4 位)——slides 的实际配置是”单张 GPU + 382 GB 内存”。
4.3 解码:把 CPU 与 GPU 之间的空隙填满
批大小 1 时,一切受带宽限制:CPU 每个 token 要从内存读 8 个路由专家 × 58 层(4 位约 11 GB),GPU 读其余 17B 参数。03 号脚本第 2 部分的时间账(RTX 4090 级 GPU,双路至强):
| 做法 | 每个 token | token/秒 |
|---|---|---|
| 逐个启动约 7,000 个内核(Fiddler 式) | 112.3 ms | 8.9 |
| 逐个启动约 3,000 个内核(llama.cpp 式) | 92.3 ms | 10.8 |
| + CUDA 图 | 77.3 ms | 12.9 |
| + NUMA 感知的张量并行 | 52.4 ms | 19.1 |
| + 专家推迟 | 30.0 ms | 33.3 |
三个优化:
- CUDA 图:Fiddler / llama.cpp 生成一个 token 要启动约 7,000 / 3,000 个 CUDA 内核,启动时间占总时间的 73% / 21%(slides)。KTransformers 把整个前向录成一个 CUDA 图,并小心避开会打断图的 CPU 操作。
- NUMA 感知的张量并行:双路服务器跨 NUMA 节点访问内存延迟高、带宽低。把每个专家的权重按张量并行切开,放在各自 NUMA 节点的本地内存里,两路 CPU 都只读本地内存。
- 专家推迟(expert deferral):CPU 算专家时 GPU 闲着,GPU 算注意力时 CPU 闲着。让一部分专家的结果晚一层再加到残差流上——CPU 算这些专家的同时,GPU 已经在算下一层的注意力。推迟多少个?刚好让 CPU 忙满即可,并且每层至少保留 2 个不推迟的专家来保护准确率。
slides 的实测:全精度实现比 llama.cpp 快最多 1.92 倍、比 Fiddler 快最多 4.09 倍;专家推迟再快最多 1.45 倍。(纸面估算的倍数不同,来自假设的启动开销、NUMA 带宽与重叠比例。)
4.4 推迟会不会伤准确率?
03 号脚本第 4 部分在城市语言上训练了一个小 MoE(4 层,每层 16 个路由专家选 4 个 + 1 个共享专家,约 1 分钟),真的测一遍:
| 推迟 / 跳过权重最小的 | 推迟:交叉熵变化 | 直接跳过:交叉熵变化 |
|---|---|---|
| 1 个 | −0.0 毫 nat | +0.0 |
| 2 个 | −0.0 | −0.0 |
| 3 个(只剩 1 个) | −0.1 | +21.4 |
推迟 1–3 个专家几乎没有损失:被推迟的输出仍然加到了残差流上,只是下一层的注意力没看到它们。这个小模型的路由非常集中(排第 1 名的专家平均权重 0.88–0.99),连”直接跳过”权重最小的 1–2 个都几乎无损;但跳过 3 个就损失 21.4 毫 nat,推迟 3 个仍然无损——推迟保住了信息,跳过丢掉了信息。层数更多、更依赖逐层精炼的大模型对推迟更敏感,这就是 slides 建议”每层至少保留 2 个不推迟的专家”的原因。
4.5 预填充:CPU 变成计算受限
预填充时每个专家的权重会被批里很多 token 用到,CPU 这一侧从带宽受限变成计算受限。AMX(Intel 第 4 代至强起的矩阵扩展)每条指令处理一个 16 × 64 × 16 的 INT8 块(16 个周期 32,768 次运算),每核每周期 2,048 次运算,是 AVX-512(256 次)的 8 倍;配上按缓存分块的内存布局,单路 CPU 的 BF16 矩阵乘超过 20 TFLOPS、INT8 / INT4 超过 37 TOPS。03 号脚本第 3 部分的估算:1K token 的提示,CPU 上的专家计算从 AVX-512 的约 17 秒降到 AMX 的约 2 秒。slides 的实测:预填充比 llama.cpp 快最多 19.74 倍、比使用 PyTorch 自带 AMX 内核的 Fiddler 快最多 5.88 倍。
4.6 开源与生态
KTransformers 2024 年 7 月首次发布(DeepSeek-V2,单 GPU + 136 GB 内存),2025 年 2 月支持 DeepSeek-V3 / R1(单 GPU + 382 GB 内存),5 月加入 AMX 内核,10 月并入 SGLang(多 GPU + CPU 推理;同样 8 张 GPU 比 1 张吞吐高 264%)与 LLaMA-Factory(本地 LoRA 微调)。slides 的微调实测:DeepSeek-V2-Lite(14B)5 GB 显存 + 30 GB 内存,每秒 227.6 个 token;DeepSeek-V3 / R1(671B)70 GB 显存 + 1.2 TB 内存,40.35 token/秒;Kimi K2(1T)81 GB 显存 + 2.1 TB 内存,36.55 token/秒——MoE 的反向也放在 CPU 上用 AMX 计算。下一步:稀疏注意力(只扫描少数几个块)。
5. 小结 · Summary
- 不同的硬件擅长不同的维度:高算力 GPU 适合预填充,高带宽 / 低价的 GPU 适合解码,大容量的 CPU 内存与 SSD 适合 KV 缓存与冷门专家。把它们组合起来,靠的是分离与按算术强度放置。
- Mooncake:预填充 / 解码分离 + 由集群闲置资源组成的分布式 KV 缓存池;全局缓存池兼得命中率与负载均衡;多网卡聚合的传输引擎让”取 KV”比”重算”快一个数量级以上;Conductor 按 TTFT 选预填充实例。
- 过载时,分离式架构的接纳决策要看到未来的解码负载;看”现在”的提前拒绝会引起预填充与解码的反相位振荡。
- KTransformers:路由专家放 CPU 就地计算,注意力与共享专家留在 GPU;CUDA 图、NUMA 感知、专家推迟填满 CPU 与 GPU 之间的空隙;AMX 让 CPU 的预填充快 8 倍——一张 GPU + 一台服务器就能跑 6710 亿参数的模型。
6. 常见误区 · Common pitfalls
- “最好的 GPU 适合所有阶段。” 解码受带宽限制,H20 这种算力弱、带宽高的卡反而合适;KV 缓存与冷门专家放在 CPU 内存里更划算。
- “把 MoE 卸载到 CPU,就是把权重搬到 GPU 上算。” 每个 token 都搬几 GB 的专家权重,PCIe 根本扛不住;KTransformers 让 CPU 就地计算,只在 CPU 与 GPU 之间传激活值。
- “缓存放在每个实例本地就够了。” 要么重复存储(命中率低),要么按前缀固定派发(负载失衡);全局缓存池才能兼顾。
- “过载时,只要看各池现在的负载就能决定拒绝谁。” 预填充与解码之间有十几秒的时间差,看”现在”会引起振荡。
- “推迟专家和跳过专家一样,都是近似。” 推迟的输出最终仍然加到了残差流上,只是晚一层;跳过是丢掉信息(小 MoE:跳过 3 个 +21 毫 nat,推迟 3 个无损)。
- “CPU 太慢,做不了预填充。” 用 AMX 与缓存友好的内核,单路 CPU 的矩阵乘能到二三十 TFLOPS;对稀疏的专家足够了。
7. 练习 · Exercises
- 用 slides 的示意价格算:A100(80 GB,2 TB/s,1.5 万美元)与 CPU 服务器(512 GB,320 GB/s,8 千美元)的每 GB 价格与每 GB/s 价格。为什么 KV 缓存适合放在后者?
- 一个 70B 的 GQA 模型(每个 token 320 KiB)在 8 张 80 GB 的卡上用 BF16 部署。显存还能放多少个 token 的 KV(留 10% 余量)?每个请求平均 8,590 个 token,能放几个请求的 KV?
- 在 02 号脚本第 1 部分的设置下,为什么”本地缓存 + 轮流派发”的有效容量约是全局池的 1/8?
- 4 张 200 Gb/s 网卡的线速合计多少 GB/s?Mooncake 测到 87 GB/s,是线速的百分之几?8 张 400 Gb/s 测到 190 GB/s 呢?
- 解释”提前拒绝”为什么会引起预填充与解码负载的反相位振荡。一个更好的接纳规则需要哪些信息?
- DeepSeek-V3 每个 token 激活 8 个路由专家,每个专家 3 个 7168 × 2048 的矩阵,共 58 个 MoE 层。4 位量化(每个参数 4.5 位)时,每个 token 要从内存读多少 GB?CPU 内存带宽 300 GB/s(有效 70%)时,CPU 部分的解码速度上限是多少?
- 批大小为 64 时,DeepSeek-V3 的一个路由专家平均被多少个 token 用到?共享专家呢?由此解释卸载的优先级。
- 为什么”专家推迟”能提高解码速度?推迟太多会怎样?
- AMX 每核每周期 2,048 次 INT8 运算。一颗 56 核、2.0 GHz 的 CPU 理论峰值是多少 TOPS?slides 实测 INT8 超过 37 TOPS,是峰值的多少?
参考答案
- A100:15000 / 80 ≈ 187 美元 / GB、15000 / 2000 = 7.5 美元 / (GB/s);CPU 服务器:8000 / 512 ≈ 15.6 美元 / GB、8000 / 320 = 25 美元 / (GB/s)。KV 缓存(尤其是”可能以后用到”的那部分)需要的是容量,访问频率低、可以一次取一大段——每 GB 便宜 12 倍的内存正合适。
- 8 × 80 − 141 = 499 GB,× 0.9 ≈ 449 GB;449e9 / 327,680 ≈ 137 万个 token;÷ 8,590 ≈ 159 个请求。
- 轮流派发时,热门文档的请求会落到每一个实例上,每个实例都要存一份;8 个实例存了 8 份相同的块,相当于全局池的 1/8 容量。
- 4 × 200 Gb/s = 800 Gb/s = 100 GB/s,87%;8 × 400 Gb/s = 400 GB/s,190 / 400 = 47.5%。
- 决策依据的是”现在”的解码负载,而被接纳的请求要排队并预填充十几秒后才进入解码池。解码池满时一律拒绝,预填充池随之变空;解码池空了又大量接纳,这批请求十几秒后一起到达解码池使它再次满载——两个池的负载交替起伏、相位相反。更好的规则要知道:已接纳的请求各在何时进入解码池(预填充队列与预填充时间),以及解码池里的请求各在何时结束(输出长度或其分布),从而预测这个请求到达时解码池的负载。
- 8 × 3 × 7168 × 2048 × 58 ≈ 20.4B 参数;× 4.5 / 8 ≈ 11.5 GB;0.7 × 300 / 11.5 ≈ 18 token/秒。
- 64 × 8 / 256 = 2 个 token;共享专家(以及注意力)每个参数被 64 个 token 用到。路由专家的算术强度低 32 倍,最适合放在带宽低、容量大的 CPU 内存里就地计算;共享专家其次;注意力最后(MLA 的 KV 也在 GPU 上)。
- 不推迟时 CPU 与 GPU 交替工作,总有一方闲着;推迟的专家在 CPU 上计算的同时,GPU 可以开始下一层的注意力,两者重叠。推迟太多:更多专家的信息晚一层才进入残差流,准确率下降;而且 CPU 本身已经是瓶颈时,再推迟也没有更多可重叠的 GPU 工作。
- 56 × 2.0e9 × 2048 ≈ 229 TOPS;37 / 229 ≈ 16%——实际的矩阵乘受内存带宽、数据布局、AMX 的块配置等限制,远到不了峰值(这也说明 KTransformers 的内核优化空间在哪里)。
8. 延伸阅读 · Further reading
- Mooncake:Qin et al. (2025),FAST 最佳论文;代码 github.com/kvcache-ai/Mooncake。
- KTransformers:Chen et al. (2025),SOSP;代码 github.com/kvcache-ai/ktransformers。
- Splitwise:Patel et al. (2024)——按阶段选择不同代的 GPU。
- Fiddler:Kamahori et al. (2024)——CPU-GPU 协同的 MoE 推理;llama.cpp:CPU 上的量化推理。
- SGLang HiCache、NVIDIA Dynamo NIXL:分层 KV 缓存与传输库(第 26、27 讲)。
- Intel AMX:Intel 架构指令集扩展编程参考手册中的 AMX 章节。
9. 下一讲预告 · Next
Mooncake 存的是”文档的 KV”,Kimi 的用户常常把整本书、整份报告扔进上下文。另一条路是不把整份文档放进上下文,而是只取出与问题相关的几段——检索增强生成(RAG)。附加讲 A3 讲 RAG 的思想与系统代价,以及它的核心组件:在几百万、几十亿个向量里找最近邻的近似算法(IVF、乘积量化、HNSW)。