Featured image of post 大模型推理进入「显存工程」阶段:Kimi 和 GLM 的成本,不只在 token 单价

大模型推理进入「显存工程」阶段:Kimi 和 GLM 的成本,不只在 token 单价

Cloudflare 跑 Kimi 与 GLM 的公开实践说明,长上下文 Agent 的真实成本取决于权重、KV cache 与并发如何争抢显存;量化的关键不在统一压缩,而在按 prefill 和 decode 分开调度。

做 AI 编程工具的人,大概都经历过这种时刻:模型的价格表已经背得很熟,输入、输出、缓存命中都能算,实际一上长任务,体验却突然垮下来。不是账单先爆,而是排队变长、上下文被压缩,或者并发一高就得降级。

原因并不神秘。Agent(智能体)不像普通聊天那样一问一答就结束。它要读仓库、跑工具、接收日志、继续修改。每多走一步,都可能多留下一段需要被复用的状态。GPU 显存里除了模型权重,还得给 KV cache(键值缓存)和其他请求腾地方。用户看到的是按 token 计费,服务端要解决的却是这些 token 到底还能不能放得下。

Cloudflare 在 8 月 3 日写了一篇 Kimi 与 GLM 的部署复盘,信息量很大。Kimi K2.6 的生成阶段,他们把 KV cache 从 BF16 换成了 FP8;GLM 5.2 的生成阶段,则把权重从 FP8 压到 INT4。真正值得看的不只是这些名词,而是他们没有把量化当成一个统一选项:输入阶段和生成阶段,跑的是两套不同的精度策略。

先把边界交代清楚。下面的容量、吞吐和成本数据都来自 Cloudflare 的硬件、模型和测试条件,不能拿去当成别家服务或自己机器上的保证。它提供的价值更像一张展开的工程图:长上下文和高并发撞到一起时,显存究竟会在哪儿先不够用。

一张价格表看不到的三笔账

普通聊天请求处理完一段上下文、输出答案就结束了。即使显存很紧,用户未必能立刻察觉。

Agent 的状态会停留更久。它读过的文件、工具输出和历史对话要留在 KV cache 里;模型权重得始终驻留;同时进来的任务还要各自占用序列和 cache page。显存不够时,系统通常不会礼貌地提示“成本上升了”,而是出现等待、缩短上下文、降低并发,最后是 OOM(内存耗尽)。

这笔账可以先分成三块看:模型权重是固定底座,模型越大、精度越高,留给其他部分的余地越小;KV cache 会随着上下文和多轮调用增长;并发余量决定服务能不能同时接住更多人的任务。三者用的是同一批 GPU,并不存在谁可以完全忽略谁。

Cloudflare 官方图表:Kimi 的 KV cache 与显存优化

所以,支持 1M 上下文和在 1M 上下文下稳定接住一批 Agent 任务,差得很远。r/ClaudeAI 有用户抱怨两天、约 900K 上下文的会话不得不 compact(压缩上下文),这类帖子最多能说明长会话的摩擦确实存在,不能证明任何模型的性能。要解决这种摩擦,还是得回到运行时的显存分配。

Kimi:cache 小一半,系统才有地方周转

Cloudflare 为 Kimi K2.6 的 decode(解码、逐 token 生成)阶段换用了 FP8 e4m3 KV cache。它把原本的 BF16 缓存从 16 位降到 8 位,cache 体积大致少了一半。

文章里的结果很直观:可驻留上下文从约 68.6 万 tokens 增至约 137 万 tokens。这里的收益不只是聊天记录能拖得更长。每个活跃请求少占一些显存,服务才有机会接下更多请求,连续批处理(continuous batching)也才有可调度的空间。

代价也不是没有。Cloudflare 的 H200 解耦部署测试里,并发为 1 时,BF16 是 137 tok/s,FP8 是 125 tok/s;并发为 32 时,BF16 是 1,558 tok/s,FP8 是 1,489 tok/s。只盯着这些数,FP8 看上去像一次倒退。

转折发生在并发继续升高之后。并发 64 时,BF16 因显存不足已经 OOM,FP8 还能跑到 2,192 tok/s。按 Cloudflare 的计算,这个峰值比 BF16 的最高吞吐高约 41%,每个 token 的成本约低 30%。它们的评测也显示,FP8 和 BF16 KV cache 的质量差异难以分辨。

这不是在说 FP8 必然更好。低并发、短上下文、对单请求速度敏感的服务,未必能获得同样收益。Cloudflare 的案例至少说明了一点:当生成阶段真正卡在 cache 容量时,腾出显存比再挤一点单请求速度更有价值。

GLM:权重的精度也不用一刀切

Kimi 的难题主要是 cache,GLM 5.2 还要面对很重的模型权重。

Cloudflare 把 GLM 5.2 的权重从 FP8 压缩到 INT4。按文中数据,checkpoint 从 705GB 缩到 421GB,少了约 40%;在 8 路张量并行下,每张 GPU 用于权重的显存从约 88GB 降到约 52GB。多出来的空间,可以留给约 118 万 tokens 的 KV cache。

INT4 还改善了生成阶段的带宽压力。decode 时,模型每生成一个 token 都要反复读取权重,权重更小,显存带宽少受一些拖累。Cloudflare 的数据里,并发为 1 时,GLM decode 从 FP8 的 60 tok/s 提升到 INT4 的 92 tok/s;并发为 32 时,从 994 tok/s 提升到 1,267 tok/s。

但 INT4 并没有因此成为默认答案。到了 prefill(预填充、集中处理输入上下文)阶段,INT4 权重要先展开再参与运算,额外步骤反而不划算。Cloudflare 测得 GLM 的 FP8 prefill 约为 10,160 tok/s,INT4 为约 8,660 tok/s。

同一个模型、同一批硬件,在不同阶段给出的答案完全不同。把量化等级当作整套服务的永久开关,常常会把问题想得太简单。更该先问的是:这段链路眼下卡在显存容量、内存带宽,还是算力本身?

输入和生成,本来就不是同一种负载

prefill 和 decode 在前端都表现为“模型在回答”,底层负载却不同。

prefill 要处理用户输入、历史对话和工具结果,长输入带来的是大块计算。decode 则沿着已有状态逐 token 往下生成,权重读取和 KV cache 容量更容易成为限制。把它们混在一个资源池里,往往只能得到一份平均意义上的“还行”。

Cloudflare 的做法是让两段运行在独立资源池中。Kimi 的 prefill 继续保留 BF16 KV cache,以计算吞吐为先;decode 用 FP8,换取更多 cache 容量和并发。GLM 的 prefill 用 FP8 权重,避免 INT4 解压拖慢计算;decode 用 INT4,减轻读取权重时的带宽压力。

预填充与解码阶段的独立资源池

这并不是一份可以直接复制的配置清单。模型结构、GPU、输入长度和流量形态都可能让结论变化。但它把“要不要上 INT4”换成了一个更接近生产的问题:哪一段缺显存,哪一段缺计算,高峰期究竟是哪个资源先顶不住。

Cloudflare 官方图表:GLM 的量化与推理吞吐对比

不少推理服务在参数页上只给一种精度和一个最高吞吐。对于短请求,那样做也许足够。任务开始变长、工具调用开始变多时,prefill 与 decode 的差异会慢慢从实现细节变成用户体验。

多个请求共用 cache,不能只考虑吞吐

量化释放显存后,系统能够容纳更多请求。请求一多,KV cache 的复用、分页注意力(paged attention)和连续批处理就更频繁。此时除了容量,另一个问题会冒出来:当前请求读到的 cache,还是不是它自己的。

Cloudflare 为此加了 KV cache 完整性检查。每个物理 cache page 都带 tag,page 被重新分配时 tag 会变化;服务端为请求记录预期使用的 page 与 tag。decode 读取前先核对映射,发现不匹配就中止该请求,不让错误 page 的内容继续参与生成。

共享 KV cache 的标签校验与错误请求中止

这类机制听起来很底层,却会直接影响用户拿到的结果。更长的上下文和更高的并发,如果以混入错误状态为代价,就不算真正可用的能力。

Cloudflare 在一个中等规模生产模型上测试了该检查:两套 prefill、两套 decode,输入 8,192 tokens、输出 1,000 tokens。它报告的吞吐损失与 p95 延迟增幅都低于 1%。校验作为独立批处理执行,没有塞进 attention kernel;不启用时走 no-op 路径,也就没有可测开销。

大多数团队不需要照着实现一套 tag 机制,但该有相同的意识。只要开始为了吞吐复用状态,就要知道状态归谁、何时释放、出错后如何中止,以及这些事情能不能从日志里看出来。

别急着抄参数,先看自己的请求长什么样

看到 1M 上下文、INT4、FP8 或最高 tok/s,最自然的反应是去找同一份配置。真正上线前,更值得先回答几件很具体的事。

用户的输入通常有多长?长上下文是日常需求,还是少数重任务?高峰时更在意首 token 延迟、稳定并发,还是总吞吐?prefill 和 decode 分别吃掉多少时间和显存?量化以后,代码生成、工具调用、结构化输出和真实任务成功率有没有变化?cache 重用、请求中止和重试能不能被追踪?

这类问题不如“INT4 能省多少”好传播,却能防止团队把成本从 GPU 账单挪到更慢的请求、更多的重试和排查不出的线上问题里。

小团队不一定要自建推理集群,也可以拿这些问题去看服务商。长上下文下可承受多少并发、首 token 延迟怎样变化、流量高峰怎么降级、缓存怎么隔离、不同规格实际差异多大,这些信息往往比价格表更接近真实交付能力。

模型、Agent 与运行时,各自管一段

模型决定的是理解和生成的质量。它决定一个任务能走到什么上限,却不会替服务端安排显存。

Agent 把模型接到仓库、终端、浏览器或其他工具上,让推理变成连续行动。它带来了更多上下文,也带来了比聊天复杂得多的请求节奏。

推理运行时要处理的是两者之间的现实条件:权重怎么放,KV cache 怎么分,输入和生成要不要拆开,多个请求怎样共享状态,读错缓存时怎样止损。这里做得不好,再强的模型也可能只是在低并发演示里显得流畅。

Cloudflare 对 Kimi 和 GLM 的这次复盘,最有用的地方在于它没有只给出一组“更快”的数字。它把量化放进了整个运行过程里:哪一段受限于什么资源,为了释放空间付出了什么代价,又怎样避免共享状态带来错误。对准备把长上下文模型接进 Agent 工作流的人来说,这比一张单独的基准图更接近每天要遇到的问题。

参考来源

Cloudflare 文章用于核对 Kimi、GLM 的部署方法和测试条件;DeepSeek 与少数派内容只是国内长上下文和 Agent 需求的背景;Reddit 帖子反映的是单个社区用户的会话体验。它们都不能替代其他硬件、模型或推理服务上的独立测试。

RSS Feed 使用 Hugo 构建
主题 StackJimmy 设计