为运行超大语言模型奠定基础
原文:Building the foundation for running extra-large language models Source: https://blog.cloudflare.com/high-performance-llms/
2026-04-16
一个 agent 需要由一个大型语言模型驱动。几周前,我们宣布 Workers AI 正式进入托管像 Moonshot 的 Kimi K2.5 这样大型开源模型的赛道。从那时起,我们让 Kimi K2.5 快了 3 倍,还有更多模型添加正在路上。这些模型是我们这周发布的许多 agentic 产品、harness 和工具的支柱。
托管 AI 模型是一个有趣的挑战:它需要在软件和非常、非常昂贵的硬件之间精妙地平衡。在 Cloudflare,我们擅长通过聪明的软件工程从硬件中榨出每一点效率。这是一篇关于我们如何为运行超大语言模型奠定基础的深入介绍。
硬件配置
正如我们在之前的 Kimi K2.5 博客文章中提到的,我们使用各种硬件配置以最佳地服务模型。许多硬件配置取决于用户发送给模型的输入和输出大小。例如,如果你正在使用一个模型写同人小说,你可能给它几个小提示(输入 token),而要求它生成几页内容(输出 token)。
相反,如果你在做摘要任务,你可能发送数十万的输入 token,但只生成一个几千输出 token 的小摘要。面对这些对立的用例,你必须做一个选择——你应该调整模型配置使它处理输入 token 更快,还是生成输出 token 更快?
当我们在 Workers AI 上推出大型语言模型时,我们知道大多数用例将用于 agent。对于 agent,你发送大量输入 token。它从一个大的系统提示、所有工具、MCP 开始。第一个用户提示之后,这个上下文持续增长。来自用户的每个新提示都向模型发送一个请求,该请求由之前所说的一切组成——所有以前的用户提示、assistant 消息、生成的代码等等。对于 Workers AI 来说,这意味着我们必须聚焦于两件事:快速的输入 token 处理和快速的工具调用。
Prefill decode (PD) disaggregation
我们用来改善性能和效率的一个硬件配置是 disaggregated prefill。处理一个 LLM 请求有两个阶段:prefill,处理输入 token 并填充 KV cache;decode,生成输出 token。Prefill 通常是计算受限的,而 decode 是内存受限的。这意味着每个阶段使用的 GPU 部分不同,而且因为 prefill 总是在 decode 之前进行,所以这两个阶段会相互阻塞。最终,这意味着如果我们在单个机器上同时进行 prefill 和 decode,就没有高效地利用所有的 GPU 算力。
通过 prefill decode disaggregation,每个阶段运行单独的推理服务器。首先,一个请求被发送到 prefill 阶段,执行 prefill 并将其存储在 KV cache 中。然后同样的请求被发送到 decode 服务器,带有关于如何从 prefill 服务器传输 KV cache 并开始 decode 的信息。这有许多优势,因为它允许服务器为它们正在执行的角色独立调优、按更多输入密集或输出密集的流量进行扩展,甚至运行在异构硬件上。
这个架构需要一个相对复杂的负载均衡器才能实现。除了如上所述路由请求之外,它还必须重写 decode 服务器的响应(包括流式 SSE)以包含来自 prefill 服务器的信息(如 cached token)。让事情更复杂的是,不同的推理服务器需要不同的信息来发起 KV cache 传输。我们扩展了这一点以实现 token-aware 负载均衡,其中有一池 prefill 和 decode endpoint,负载均衡器估算池中每个 endpoint 在飞行的 prefill 或 decode token 数量,并尝试均匀地分散这些负载。
在我们公开模型发布之后,我们的输入/输出模式再次发生了剧烈变化。我们花时间分析了我们的新使用模式,然后调整配置以适应客户的用例。
下面是我们将流量切到新的 PD disaggregated 架构后,p90 Time to First Token 下降的图,同时请求量增加,使用相同数量的 GPU。我们看到尾部延迟方差有显著改善。
类似地,p90 时间每 token 从约 100ms 高方差降到 20-30ms,intertoken 延迟提升了 3 倍。
Prompt Caching
由于 agentic 用例通常具有长上下文,我们针对高效的 prompt caching 进行了优化,以避免在每一轮重新计算输入 tensor。我们利用一个名为 x-session-affinity 的 header,帮助请求路由到之前已经有计算好的输入 tensor 的正确区域。我们在关于在 Workers AI 上推出大型 LLM 的原始博客文章中写过这个。我们在流行的 agent harness 比如 OpenCode 中添加了 session affinity header,在那里我们注意到总吞吐量显著增加。我们用户在 prompt caching 上的小差异可以累积成运行一个模型所需的额外 GPU 倍数。虽然我们内部有 KV-aware 路由,我们也依靠客户端发送 x-session-affinity 来明确指出 prompt caching。我们通过提供折扣的 cached token 来激励使用该 header。我们强烈鼓励用户利用 prompt caching 以获得更快的推理和更便宜的价格。
我们与我们最重的内部用户合作以采用此 header。结果是输入 token 缓存命中率在峰值时段从 60% 增加到 80%。这显著增加了我们能处理的请求吞吐量,同时为像 OpenCode 或 AI 代码评审这样交互式或时间敏感的会话提供更好的性能。
KV-cache 优化
由于我们现在服务更大的模型,一个实例可能跨越多个 GPU。这意味着我们必须找到一种高效的方式在 GPU 之间共享 KV cache。KV cache 是来自 prefill(会话中提示词的结果)的所有输入 tensor 存储的地方,最初存放在 GPU 的 VRAM 中。每个 GPU 都有固定的 VRAM 大小,但如果你的模型实例需要多个 GPU,就需要一种方式让 KV cache 跨 GPU 存在并相互通信。为了在 Kimi 上实现这一点,我们利用了 Moonshot AI 的 Mooncake Transfer Engine 和 Mooncake Store。
Mooncake 的 Transfer Engine 是一个高性能数据传输框架。它支持不同的 Remote Direct Memory Access(RDMA)协议,如 NVLink 和 NVMe over Fabric,这能在不涉及 CPU 的情况下实现内存到内存的直接数据传输。它提高了跨多个 GPU 机器传输数据的速度,这在多 GPU 和多节点配置的模型中特别重要。
当与 LMCache 或 SGLang HiCache 配对时,缓存在集群中的所有节点之间共享,允许一个 prefill 节点识别并重用之前请求中最初在不同节点上 prefill 的缓存。这消除了集群内对会话感知路由的需要,并允许我们更均匀地负载均衡流量。Mooncake Store 还允许我们将缓存扩展到 GPU VRAM 之外,利用 NVMe 存储。这扩展了会话保留在缓存中的时间,提高了我们的缓存命中率,使我们能够处理更多流量并为用户提供更好的性能。
Speculative decoding
LLM 通过基于之前的 token 预测序列中下一个 token 来工作。在朴素实现中,模型只预测下一个 n 个 token,但实际上我们可以让它在模型的一次前向传递中预测下一个 n+1, n+2… 个 token。这种流行的技术被称为 speculative decoding,我们在之前关于 Workers AI 的文章中写过。
通过 speculative decoding,我们利用一个较小的 LLM(draft 模型)生成几个候选 token 供目标模型选择。然后目标模型只需在一次前向传递中从一个小的候选 token 池中选择。验证 token 比使用更大的目标模型生成 token 更快、计算上更便宜。然而,质量仍然得到维持,因为目标模型最终必须接受或拒绝 draft token。
在 agentic 用例中,speculative decoding 真的很出彩,因为模型需要生成的工具调用和结构化输出量大。一个工具调用在很大程度上是可预测的——你知道会有一个名字、描述,并且包裹在一个 JSON 信封中。
为了在 Kimi K2.5 上实现这一点,我们利用 NVIDIA 的 EAGLE-3(Extrapolation Algorithm for Greater Language-model Efficiency)draft 模型。调优 speculative decoding 的杠杆包括要生成的未来 token 数量。结果是,我们能够在加快每秒 token 吞吐量的同时实现高质量推理。
Infire:我们的专有推理引擎
正如我们在 2025 Birthday Week 期间宣布的,Cloudflare 有一个专有推理引擎 Infire,它使机器学习模型更快。Infire 是一个用 Rust 写的推理引擎,旨在支持 Cloudflare 在分布式全球网络上的独特推理挑战。我们扩展了 Infire 对我们计划运行的这一新类大型语言模型的支持,这意味着我们必须构建一些新功能才能让它工作。
多 GPU 支持
像 Kimi K2.5 这样的大型语言模型有超过 1 万亿参数,即约 560GB 的模型权重。一个典型的 H100 大约有 80GB 的 VRAM,而模型权重需要被加载到 GPU 内存中才能运行。这意味着像 Kimi K2.5 这样的模型至少需要 8 块 H100 才能将模型加载到内存并运行——这还不包括 KV Cache 所需的额外 VRAM,KV Cache 包括你的上下文窗口。
自最初推出 Infire 以来,我们必须添加多 GPU 支持,让推理引擎能够在多个 GPU 上以 pipeline-parallel 或 tensor-parallel 模式运行,同时也支持 expert-parallelism。
对于 pipeline parallelism,Infire 试图正确地负载均衡 pipeline 的所有阶段,以防止一个阶段的 GPU 在其他阶段执行时空闲。另一方面,对于 tensor parallelism,Infire 优化了减少跨 GPU 通信,使其尽可能快。对于大多数模型,同时利用 pipeline parallelism 和 tensor parallelism 提供了吞吐量和延迟的最佳平衡。
更低的内存开销
虽然已经比 vLLM 拥有更低的 GPU 内存开销,我们进一步优化了 Infire,收紧了像 activation 这样的内部状态所需的内存。目前 Infire 能够在仅两块 H200 GPU 上运行 Llama 4 Scout,KV-cache 还有超过 56 GiB 剩余,足以容纳超过 1.2m token。Infire 也能在 8 块 H100 GPU 上运行 Kimi K2.5(是的就是 H100),KV-cache 还有超过 30 GiB 可用。在这两种情况下,你甚至连 vLLM 都启动不了。
更快的冷启动
在添加多 GPU 支持的同时,我们识别出额外的机会来改进启动时间。即使对最大的模型,如 Kimi K2.5,Infire 也可以在 20 秒内开始服务请求。加载时间仅受驱动器速度限制。
最大化我们的硬件以获得更快的吞吐量
投资我们的专有推理引擎使我们能够在不受约束的系统上获得最高 20% 更高的每秒 token 吞吐量,也使我们能够使用更低端的硬件运行最新的模型,在那里以前完全不可行。
旅程没有结束
机器学习社区每周都有新技术、研究和模型出现。我们持续优化我们的技术栈,以为客户提供高质量、高性能的推理,同时高效地运行我们的 GPU。如果这些听起来对你来说是有趣的挑战 —— 我们正在招聘!