大模型推理优化:量化、压缩与安全验证
Cloudflare分享Kimi和GLM推理优化工程方案:KV缓存量化、模型权重压缩、完整性校验降低成本和延迟
Cloudflare分享Kimi和GLM推理优化工程方案:KV缓存量化、模型权重压缩、完整性校验降低成本和延迟
Workers AI 在靠近用户的 Cloudflare 数据中心里,使用 GPU 为全球一些最优秀的开放模型运行推理。其中能力最强、资源需求也最高的两个模型,是 Moonshot 的 Kimi K 系列和 Z.ai 的 GLM。它们都是支持长上下文的超大型混合专家模型(Mixture-of-Experts,MoE),使用体验非常出色。但受内存限制影响,想要高效地提供这些模型并不容易。
我们此前介绍过如何在 Workers AI 上为大型模型提供服务,也讨论过如何将推理的 prefill 和 decode 阶段分离,从每块 GPU 中榨取更多性能。本文将介绍在此基础上叠加的三项技术,它们可以帮助这些模型装入内存并保持高速运行:量化 KV cache、压缩模型权重,以及——由于前两项技术会让更多请求集中到共享硬件上——保护这些请求共同使用的 cache。这些优化让我们能够以更低的成本服务更多客户,同时不影响模型准确率。
我们的所有实验和生产流量均基于 SGLang 运行并完成基准测试。SGLang 是一个开源推理服务框架。我们发现,SGLang 提供了目前市场上最出色的性能,因此我们与 SGLang 团队密切合作,将补丁和新功能贡献到上游,让我们的成果也能惠及开源社区。
模型生成文本时,会把已经处理过的每个 token 对应的注意力键(K)和值(V),存储在一个名为 KV cache 的结构中。正是这个 cache,让模型能够延续一段很长的对话,而不必在生成每个新 token 时重新读取整个上下文。对于长上下文模型来说,KV cache 会迅速增长,因此最先耗尽 GPU 内存的通常不是模型权重,而是 KV cache。
默认情况下,cache 以 16 位精度(BF16)存储。我们改用 8 位浮点格式(FP8、e4m3),从而将其占用空间减半。在 Kimi K2.6 上,这使我们能够在内存中容纳的上下文从大约 68.6 万个 token 提升至约 137 万个,容量翻了一倍。
这里有必要准确说明收益究竟来自哪里,因为它并非源于原始速度的提升。量化 cache 会为每个 token 增加少量计算工作,因为 FP8 attention kernel 在读取数值时需要进行转换。它真正改变的是我们能够同时在内存中驻留多少个请求。以下数据来自采用 prefill/decode 分离架构的 H200 部署,测量 Kimi K2.6 的 decode 性能,并直接比较两种 attention kernel:
BF16 KV cache(tok/s)
在任意相同的并发级别下,BF16 的单 token 速度都会快几个百分点。但 BF16 在并发请求数达到 32 时便会耗尽 cache,无法再接纳第 33 个请求;FP8 则可以继续扩展到 64 个并发请求,吞吐量达到每秒 2,192 个 token,比 BF16 的峰值高出约 41%,每个 token 的成本则降低了约 30%。由于我们将 prefill 和 decode 作为独立的资源池运行,因此可以把这种优化用在收益最大的地方:prefill 受计算能力限制,而非内存限制,所以我们会在 prefill 阶段继续使用 BF16 cache,以保留其略高的吞吐量。
如果这种改变会影响模型回答,那么上述收益就毫无意义,因此我们进行了验证。在整套评测中,使用 FP8 和 BF16 cache 的结果没有可辨别的差异:
mcxams(内部基准测试)
KV cache 是 GPU 内存的一项主要需求,模型权重则是另一项。对于 GLM 5.2,我们在不损失准确率的情况下,将权重从 8 位浮点格式压缩为 4 位整数(INT4)。checkpoint 的大小从 705 GB 缩减至 421 GB,降幅约为 40%;在采用 8 路 tensor parallel 的部署中,每块 GPU 的内存占用也从大约 88 GB 降至 52 GB,从而在相同硬件上为约 118 万个 token 的 KV cache 腾出了空间。
在整套评测中,INT4 与 FP8 权重的结果没有可辨别的差异:
基准测试 / 能力
mcxams(内部基准测试)
更小的权重会让 decode 阶段变得更快,原因很明确:生成每个 token 时,都需要从 GPU 内存中流式读取模型权重,因此 decode 速度受内存带宽限制。需要搬运的数据越少,每个 token 就能越快生成。这种效果在低并发场景下最为明显,而此时单个请求的延迟也最为重要:
prefill 的情况则不同。它受计算能力限制,而且 INT4 权重必须先展开,模型才能用它们执行乘法运算,因此这一步额外操作反而会让 prefill 变慢。GLM 使用 FP8 时,prefill 吞吐量约为每秒 10,160 个 token;使用 INT4 时则为每秒 8,660 个 token。与 KV cache 一样,分离式架构让它成为一道选择题,而不再需要妥协:在更有优势的 decode 阶段使用 INT4,在更有优势的 prefill 阶段使用 FP8。在我们运行的每一项基准测试中,模型准确率与 FP8 模型之间的差距都不超过 0.8 分,其质量没有可辨别的差异。
上述两项技术产生了相同的效果:让更多请求可以同时共享一块 GPU 的内存。这正是提高效率的关键,但也意味着数百个请求会同时读写同一块物理 KV cache 中的页面。paged attention、continuous batching 和 cache reuse 等提升速度的机制,全都依赖绝对准确的记录与管理。在我们的请求规模下,即使错误概率只有十亿分之一,也会频繁暴露出来。
因此,我们构建了 KV cache 完整性检查,作为一层防御机制。其思路很直接:每个物理 cache 页面都会获得一个 tag,每当页面被重新分配时,这个 tag 就会改变;服务器则会记录每个请求预期使用哪些页面及其对应的 tag。在受支持的 decode 操作读取 cache 之前,系统会检查这些映射关系。如果出现任何不匹配,受影响的请求就会被中止,避免其从错误页面读取数据并将其返回。
一项安全检查能否真正上线,取决于它的成本。我们在一个中等规模的生产模型上进行了测量,配置为两个 prefill 实例和两个 decode 实例,输入长度为 8,192 个 token,输出长度为 1,000 个 token:
无论是吞吐量还是尾延迟,其成本都低于 1%;即便是 95% 置信区间的上限,也仍然接近 1%。为了降低计算开销,我们将验证作为独立的批量检查运行,而没有将其融合进 attention kernel;后者会在 GPU 线程组之间引入竞态条件。这项能力可按部署启用,默认执行路径使用没有可测量开销的 no-op tracker,因此不需要完整性检查的部署无须承担任何成本。
高效提供前沿模型服务,是一个不断变化的目标,这些便是我们为此持续进行的工作。我们正在把 FP8 KV cache 扩展到更多基础设施上,在 Blackwell(NVIDIA 的 GPU 架构)上验证 NVFP4 权重,并努力将完整性检查的成本降至几乎可以忽略,从而能够在所有环境中始终启用。这些优化将帮助我们继续以更低的成本、在保持相同准确率的同时,为更多客户提供支持。
如果你也热衷于将最优秀的开放模型装进 GPU,并为数百万开发者提供服务,欢迎加入我们。