为什么推理比训练更重要
大家今天怎么样?(欢呼)好,今晚是推理专场。大家得兴奋起来!我一开始真不知道该怎么把“推理”画出来,所以就做了个万圣节主题,让它看起来更吓人——我三岁的孩子会说,是“吓人”那种吓人。这边是我太太。
那为什么要关注推理?我想,YC 在推理方面投了很多,也一直密切关注。我以前经营过一家 AI 公司,既训练模型,也做大量推理;推理始终是瓶颈。要在规模化的同时把推理做好很难,尤其还得避免销售成本(COGS)把利润吃光——有些软件行业的人可能不熟悉这个词。
过去十年,推理领域已经创造了 2200 亿美元的市值。今晚有三四家很棒的公司来分享。我们有 Together AI 的研究负责人 Dan Fu。
为什么推理重要?我喜欢比较训练 FLOPs 和推理 FLOPs。DeepSeek 是唯一一家会公布全部这类数据的公司。DeepSeek 报告说,训练 DeepSeek V3 大约用了 280 万 H800 小时;而它每天大约消耗 4.3 万 H800 小时用于推理。这是较早的数据,不是最近的数据,所以现在可能远不止这些。
即使按这些数字算,一年里用于该模型权重文件推理的 FLOPs 也大约是训练的 6 倍。如果假设一套权重文件有两年的有效寿命,那推理的总重要性就会达到训练的 12 倍。随着越来越多用户开始使用这套权重,AI 持续普及,推理只会变得越来越重要。
我写论文时也常想到这一点。比如在 NeurIPS 论文里比较不同模型,当然要尽量降低训练 FLOPs,但我们也应该把推理 FLOPs 看得重要 12 倍。Chinchilla 论文以及大多数 NeurIPS 论文的横轴通常只画训练 FLOPs,而且是等训练 FLOPs 比较;我们真正应该开始关注的是等推理 FLOPs 比较。
做 SaaS 的人也许不太关心 COGS 是什么意思,但对模型服务商来说,这真的很重要。昨天公布的一些数字让人吃惊:利润率居然可以这么高。这意味着 DeepSeek 的利润率达到 80%,原因之一就是他们在推理上做了大量创新。
推理到底为什么这么复杂?乍看只是调用 `model.forward`,似乎没什么难的;实际上难得多。给不熟悉大语言模型的朋友简单解释:系统收到一段提示,也就是一组 token ID,然后对初始提示运行 prefill。如果其中一部分已经缓存,就不该再重复运行 prefill。更好的是,如果数据还热存在 DRAM、Redis 缓存,甚至某处的 SSD 上,就能直接复用。还要做类似 LRU 的缓存管理,这已经能省下一大笔成本。之后才进入 decode 循环。
为什么推理比训练更重要(续)
接下来会用到一些术语。模型 FLOPs 利用率(MFU)是指训练或 prefill 时 GPU 实际被用到了多少。训练和 prefill 的 MFU 通常接近;假设是 50%,即使 Jensen Huang 承诺 H100 有 2 万亿 FP8 FLOPs,你实际也拿不到那么多,能拿到一半就不错了。decode 更差,可能只有 5%。所以必须谨慎看待这些指标。
Dan Fu 等人持续优化的关键指标包括:首 token 时间(完成 prefill 要多久)、每个输出 token 或每个 decode 步骤所需的时间,以及吞吐量——每 GPU 小时实际能生成多少 token。还要关注在给定服务等级下能够提供多少吞吐。
举个刚公布的 DC 数据:不算缓存命中时,prefill 吞吐是每张 GPU 每秒 6 万 token;算上缓存命中后,输入缓存命中率达到 96%,非常高。当然,这取决于流量:Agent 请求的输入缓存命中率会很好;而像我妈妈这样每次都新开 ChatGPT 对话,问天气或其他全新问题,就没有 KV 缓存可用,只能一遍遍重新做 prefill。
有缓存命中时,每张 GPU 吞吐达到每秒 150 万 token。首 token 时间约 400 毫秒,P99 约 1 秒。decode 吞吐则是每张 GPU 每秒 1.4 万 token。对比 prefill 缓存命中时的 150 万和 decode 的 1.4 万,就能看出 decode 确实是瓶颈,许多芯片创新正是为了加速它。
另一个很值得关注的指标是 KV 缓存保留策略。服务方为用户保留了 PB 级 KV 缓存数据,保留 72 小时,因此能实现很高的缓存命中率。
还有算术强度:从 DRAM 向 SRAM 搬运 4 字节数据时,针对这 4 字节做了多少 FLOPs?在 RNN 或扩散模型中,算术强度很高:输入一张图像,或一份噪声,然后对同一网络和权重反复计算;除非图像太大需要切块,否则不必反复回到 DRAM。LLM 的算术强度则相当低。Volo 来这里讲扩散 LLM 时就提出过这个观点。我实验室的 Herman 最近也发表了一个 next-concept model,算术强度同样高得多。
另外两个术语是模型带宽利用率和模型 FLOPs 利用率。购买 H100 时,标称峰值是 2 万亿 FP8 FLOPs;测试时到底能拿到多少?通常远低于峰值,MFU 就是实际获得的计算量。模型带宽利用率则看实际内存带宽:假设峰值带宽是每秒 1 TB,测试时平均实际用了多少?
为什么推理比训练更重要(续)
还有屋顶线分析(roofline analysis),也就是理论上最多能做到多好。上限取决于芯片每秒峰值 FLOPs,与每秒内存字节数乘以每字节计算量,两者中的较小值。
推理创新的三种类型
推理领域有很多创新。我把它们分成三类;不同人可能会争论分类边界,但这是我的看法。
第一类是模型创新。比如 MoE:若有 K 个专家,推理时可以把所有专家的计算摊薄,FLOPs 大致减少到原来的 1/K。状态空间模型(SSM)不必每层都做完整注意力,也许每五层或十层才做一次,因此可以减少推理计算。多头潜在注意力(MLA)则在序列维度压缩表示,减少 FLOPs。还有量化——现在甚至有 2 bit 模型——以及蒸馏:先得到一个能力很强的大模型,再把它蒸馏成满足需求的小模型,不一定非要部署大模型。
第二类是 kernel 和运行时创新,例如 RadixAttention、FlashAttention、PagedAttention。很多思路借鉴了经典操作系统和数据库理论:怎样让生产数据库更快?可以做缓存、前缀树或 radix tree,这就是 RadixAttention 的直觉。Tri Dao 提出了 GPU 分块的 FlashAttention,是一项重大创新。PagedAttention 与 RadixAttention 互斥,它采用虚拟内存分页和缓冲池的思路,把数据分页到 DRAM 中。
第三类是 harness 层创新。最简单的是路由,我们在 Focal 就做过。不是每个请求都需要送进最强、最昂贵的模型;可以先用小模型,再逐步升级,或在需要时调用更大的模型,这会节省很多 FLOPs。推测解码使用草稿模型先生成候选,再由目标模型验证。
我最喜欢的是递归语言模型:别把完整上下文都塞进 KV 缓存,而是让 LLM 自己决定什么时候需要什么内容。这样就能显著减少 KV 缓存用量。最后还有上下文压缩,这几乎是每套 harness 的必备功能。我们实验室的 Sabri 和 Dan Simran 做了一项很酷的创新,叫 cartridges。
如果想深入了解,我认为最好的两份讲座是 Percy 在 CS 336《从零构建 LLM》第 10 讲中的精彩内容,以及 Ryner Pope 和 Dwarkesh 的讲解,都非常棒。
我讲得够多了。接下来是全世界最懂这些问题的几位专家:Together AI 负责研究的 Dan Fu,他来自我在 Hazy 的实验室;Jeffrey Morgan,Ollama 的创始人兼 CEO;Luminal 的创始人兼 CEO Joe Fioti;还有 Liangsheng Yin(我想是这个名字)。
Dan Fu:一次推理请求的生命周期
太好了。谢谢大家邀请我,也谢谢 Francois 做了很棒的推理概述。今天我会更仔细地讲一个 token 的完整生命周期,也就是一次推理请求从 API 进入、到达数据中心、一路下沉到 kernel 并在 GPU 上执行,最后再把 token 返回给用户的过程。
这份演讲原本有六种加速方法,我删掉了一半,今天讲其中三种,有些 Francois 刚才也提到了。
为什么现在要关注推理?我们正处在一个非常令人兴奋的阶段,开源 AI 的规模前所未有。图表有点旧,但几个月前 Together 每月处理约 400 万亿个 token。当时 Google 也公布了 Gemini 的流量;我们这个小创业公司处理的量约为 Google 总流量的八分之一,很令人振奋。今年稍早时,OpenRouter 流经的 token 有一半以上来自开放模型。营销团队还提醒我,几周前有一天 Together 的 token 数也超过了 OpenAI。
开放模型发展的一个驱动力是便宜得多:质量几乎相同,很多情况下甚至一样或更好,价格却可能低到十分之一。开源模型进步很快,每天都有新进展。
今天我会谈谈如何提供这些模型服务,以及怎样生成更多 token。Together 经常思考如何让世界产生更多 token,并为所有需要的人提供更多 token。
Together 是一家 AI 原生云服务商。就像 AWS 不只租 CPU、提供计算,还提供 SQL 数据库、存储、REST API 等运行网络服务所需的东西,我们也在思考建设 AI 原生公司需要什么:预训练、微调、推理,以及供 Agent 尝试各种操作的沙箱。Together 正在打造一朵覆盖这些需求、尤其专注于推理的云。团队大约有 80 位研究人员,其中有许多博士;过去做过不少工作,现在聚焦推理和提升 GPU 性能。
我们也会研究不同工作负载的样子。比如代码工作负载的缓存命中率如何、两轮交互之间隔多久:你让 Claude Code、OpenCode 或 Cursor 构建某个东西后,会等多久再回复?响应需要多快?生成大量代码时需要多快?在响应时间和任务完成时间等 SLA 约束下,我们会针对这些部分做优化。
那么请求实际到来时会发生什么?假设你向某个 REST API 发出请求……
Dan Fu:一次推理请求的生命周期(续)
请求经过 Cloudflare、DNS 等互联网常规环节,最终到达一系列数据中心。假设有数千张 GPU,还有刚才 Francois 提到的 KV 缓存。第一步是请求级路由:决定把请求发送到哪个 GPU 副本。然后把人类可读的文本转换成模型能处理的数字,也就是 token。接着进入大批处理循环,包括 prefill 和 decode。最后得到输出 token,把它们转回人类可读文本,发回给用户。
先说请求和路由。数千张 GPU 会接收来自世界各地的请求,系统既要做负载均衡,也得考虑 KV 缓存。过去做数据库或生产 Web 服务时,只要看看哪台机器流量太大,然后轮询把请求发到别处就行了。但语言模型时代还有一件事:如果同一请求反复发到同一张 GPU,性能会更好,因为之前已经处理过一部分内容。
例如第一次代码请求可能需要处理整个代码库;后续请求就不必重复这部分工作。因此路由不只是跨数据中心和 GPU 平衡负载,还要把请求送到已经驻留相关 KV 缓存的位置。
接下来是 tokenization。听起来很简单,但也有不少复杂性,因为模型请求会带有工具调用。用户可能告诉模型:“你可以搜索文件系统、用 grep 查找内容、运行命令来构建和测试应用,或者搜索互联网。”模型本身只是由矩阵乘法和注意力模块构成的数学系统,它并不能真的搜索互联网或执行操作。请求会附上可用工具列表,由模型决定何时调用互联网或搜索功能。
这里有很多正确性问题需要处理。Jeff 稍后会谈如何从用户侧管理工具,但光是 tokenization 这一环就有不少复杂细节,必须让工具调用正确运行。
再往后是模型的核心调度循环。请求不断流入,系统会把它们组成批次,等待空闲 GPU 或计算周期,也可能要等之前的请求完成。调度决策决定总吞吐量:是让同一批 GPU 服务更多用户,还是优先给出非常迅速的响应?这有点像 Google 搜索里的 Gemini:第一条回复总是非常快,之后继续聊天就慢一些。这背后可能是不同的调度策略,甚至使用不同模型。
Dan Fu:一次推理请求的生命周期(续)
接下来是 prefill 和 decode。可以把 prefill 理解成提示处理:输入整个代码库后,模型要弄清代码里有什么、用户在问什么,并理解所有相关内容。这是计算密集型操作,GPU 负载很重,MFU 和算术强度都比较高。
第二阶段是模型每次生成一个或少数几个 token。每生成一个 token,都要把整个模型权重从 GPU 显存加载到计算单元。因此 decode 是内存密集型操作,与 prefill 很不一样。我们花很多时间研究怎样分别处理这两种工作负载、将它们拆开,或使用不同的并行策略和 kernel 提高效率。
最终,模型产生一串 token ID,将它们转成文字并流式返回给用户。看起来简单,但仍要决定何时释放 KV 缓存、保留多久,以及尽量让 token 在缓存里驻留多久。
在 Together,我们认为大约有六类方法可以加速推理。首先是 kernel,也就是 GPU 程序。模型最终都要在 GPU 上运行,因此可以优化注意力 kernel、MoE kernel,或 mega-kernel。其次是分离 prefill 和 decode:它们是不同工作负载,放在不同 GPU 上运行,安排方式会影响用户体验和整体吞吐。第三是并行策略。例如 Chimney K3 有 3 万亿参数,采用 FP4,每个参数半个字节,模型要占 1.5 TB;最好的 B200/B300 也只有约 280 GB 显存,所以必须把模型拆到多张 GPU 上。怎样拆就是并行问题。
还有数据中心内部的路由选择。最后两种更靠近模型层:推测解码让一个小模型先猜,大模型验证;像“1+1 等于几”这样的问题未必需要大模型,如果猜对了,这些 token 几乎就免费得到了。另一种是量化:大模型的权重每个参数到底要存多少 bit?
今天受时间限制,我会重点讲 kernel、并行策略和量化。Kernel 主要影响 prefill 与 decode 这两个核心计算阶段,也就是矩阵乘法、注意力等数学运算实际执行的地方。优化时会发现,有些模型组件相对容易,有些则难得多。
Dan Fu:一次推理请求的生命周期(续)
模型里各种 LayerNorm、RMSNorm 和零散的 softmax 操作,算术强度都很低。若每个操作单独写一个 kernel,FLOPs 利用率也很低。这就是为什么传统训练的端到端 FLOPs 利用率可能只有 50%,decode 时甚至只有 5%。过去的办法是检查模型的 forward pass,逐个寻找可优化之处,再交给高水平 kernel 工程师手工优化。很长一段时间里,行业都靠聪明人投入大量精力做这件事。
最近 Together 在尝试用 Agent 自动优化其中许多部分。这个内部项目暂时叫 Together Compiler;未来几周还会介绍,正式发布时可能改名,因为我前几天突然发现它其实并不是编译器。基本设想是:给定目标模型、目标硬件和真实流量,使用 Agent 优化内层计算循环。
关键是让循环由真实流量驱动。代码工作负载和聊天工作负载会以很不同的方式激活 kernel。我们发现,必须形成完整的端到端研究循环,观察生产环境中实际运行的内容并据此迭代。我们开始构建的有点像推理的递归自我改进(RSI)循环。
接下来谈如何优化并行方案。模型权重太大,无法装进单张 GPU;把模型切分到多张 GPU 上,就能获得更多计算力和带宽。常见方案包括张量并行:把矩阵乘法拆开,最后做类似 MapReduce 的归约;流水线并行:按层把模型分到不同 GPU;数据并行:让不同 GPU 处理不同序列,但每张卡都保留相同模型。
核心问题一直是 GPU 显存有多少、kernel 能否快速支持某种并行方案,以及硬件提供了哪些能力。近期很受关注、我们也投入很多的方向,是扩大单个高速互联域;这也是 Francois 先前提到 DeepSeek 每小时 38 美元成本的重要原因之一。
如果最近买过 GPU,可能听说过 Blackwell 和 GB 芯片。过去的 NVIDIA 芯片包括 Blackwell,一般只有 8 张 GPU 能通过高速带宽互相通信,因此模型通常最多切成 8 份。若切成 16 份,数据就要走慢得多的链路,推理服务会慢得无法接受。最近 NVIDIA 开始销售可把 72 张 GPU 连接起来的机架,互联带宽高得多。这样就可以把模型里的所有专家……
Dan Fu:一次推理请求的生命周期(续)
有了 72 张 GPU 的高速互联后,可以把各个专家分别放到不同 GPU 上。同一批 GPU 就能服务更大的 token 流量,算术强度也会提高:如果每张 GPU 上的专家都处理大量 token,计算就更像 GPU 擅长的大型矩阵乘法。
专家并行的演示几年前就有了,近期才逐渐变得可靠。这些 GB 机架很棒,但节点或 GPU 仍可能故障。若一个模型副本依赖 72 张 GPU,其中一张出故障而没有合适的恢复机制,就会损失 72 张 GPU 的算力。我们花了很多时间提升可靠性,让系统能抵御故障并平稳继续运行。
最后谈量化。算法本身不难找,相关论文有几百甚至几千篇,挑一种来用似乎很简单;但量化会直接影响用户体验和模型质量。模型可能以 BF16 训练,每个参数 16 bit、也就是 2 字节,因此 3 万亿参数要占 6 TB。机器学习计算本身有一定模糊性,不一定需要所有精度,也可能得到正确答案。我们知道能把 16 bit 缩成 8 bit 或 4 bit,同时保持不错的质量。真正重要的是,如何确保用户拿到合适的质量和体验。
Together 一方面要知道哪种量化适合硬件、能带来最高吞吐和每 GPU token 数;另一方面,用户正用模型构建公司、处理非常重要的事情。因此,在把模型交给用户前,我们会先在内部充分使用和测试。这样既能发现工具调用是否出问题——比如 Claude Code 突然不能搜索互联网,用户马上就会察觉——也能发现模型是否变笨、基准分数下降或端到端评测不理想。
我们一直运行一个 Flappy Bird 小循环,让模型快速尝试编写 Flappy Bird。如果量化出错,游戏里的小鸟突然不再拍翅膀,我们就知道要查原因并修复。核心是严格的评测闭环:基准测试、Agent 评测和内部试用。
Dan Fu:一次推理请求的生命周期(续)
算法优化和创新当然很多,但最终关键是严谨的评测循环,包括基准测试、Agent 评测和内部试用。
举个成功案例:我们和许多开放模型提供方深度合作,也帮 MiniMax 部署 M3,以及他们即将推出的 M3.1(我不确定本来能不能透露,不过现在大家都知道了)。MiniMax 当时在把模型量化到 NVFP4 时遇到困难。我们从 kernel、服务部署和实际体验角度看,认为这对 NVIDIA GPU 是合适的量化格式。图上左边淡紫色是原始 FP8 模型,中间热粉色是 MiniMax 自己的量化方法,右边橙色是我们的方案。我们的方案达到原模型的性能,能让 MiniMax 服务更多 token,帮助他们从训练模型走到盈利服务、获得收入,再去训练大家期待的下一个模型。这是我们用量化专长帮助核心模型研发团队的一个有趣案例。
总结一下请求如何流经系统:路由决定发给哪个副本和数据中心;tokenization 要确保工具调用等环节正确;核心队列、批处理和调度会安排请求;prefill 与 decode 往往在不同 GPU 上运行,使用不同 kernel 和并行方案。所有这些环节发挥作用后,GPU 才把 token 送回来,供编程、聊天以及其他用途。
如果你对开放模型感兴趣,或者 CFO 正催你说云端代码助手太贵、也许该试试开放模型,二维码里有 Together 的销售联系和招聘页面。感谢大家收听。
谢谢。我们还有几分钟提问,对吧?
Dan,谢谢你的演讲。我有两个问题。关于你们做的 NVFP4 量化,质量是怎么衡量的?用的是 GSM8K、困惑度、MMLU,还是和 MXFP8 比较?另一个问题是,什么互连技术让 Grace Blackwell 这一代芯片可以用网格形式连接超过 8 张 GPU?
关于量化质量,我们看三种公开基准,其中有些已经接近饱和,例如某项指标达到 90% 以上。若分数变化一个百分点或更多,就说明可能出了问题,模型在某些真实任务上会遇到困难。除了常规基准,我们也看每层的 KL 散度,检查激活值变化多少,还会跑端到端 Agent 流程。我们现在积累了数百个测试案例:每次有人报告模型出问题,就把它加入测试集。我们还持续跑 Flappy Bird 这样的 Agent 评测,并把它接入 Together Compiler,让模型优化自己的 kernel;如果它突然做不到了,我们就会调查。
Dan Fu:一次推理请求的生命周期(续)
(回答量化评测问题)我们会观察模型在公开基准上的变化、逐层激活值的 KL 散度,也会用成百上千个端到端测试案例和 Agent 循环评估。Flappy Bird 也被接入 Together Compiler,模型会优化自己的 kernel;如果它突然做不好,我们就知道需要排查。
另一个问题是,从 8 GPU 互连到 72 GPU 互连,这一代技术跨越是怎样实现的?
(介绍互连技术与个人使用体验;现场问题字幕较难辨认。)
我本人不是硬件工程师,从没设计或制造过硬件;最近最接近硬件的经历,是买了一个 Hugging Face 的微型设备。看机架会发现,每个托盘装四张 GPU,用很粗的线缆连到大型交换机,再把所有托盘这样连接起来,数据经过交换机后就能做归约等操作。至于从 8 张扩展到 72 张的具体技术跃迁,我并不熟悉,不过我很喜欢这套设备,也在使用它。
(后续问题涉及硬件测试方式,字幕语句破碎,无法可靠复原。)
我们会做公开基准测试,也会跑自己的 Agent 循环,以及介于两者之间的各种测试。
好,请把麦克风递过去。
关于图里的量化方案,你们是从头训练,还是引入量化后继续做了多个预训练周期?热粉色那条是没有训练、直接把数值转换成低精度吗?
有些量化方案要求模型训练完成后再训练一遍。我们不喜欢这样,因为除非你就是模型提供方、掌握完整训练集,否则很难做到;而且继续训练可能让模型忘掉一些能力。我们的方案完全不需要训练,是公开方法的组合,其中包括校准数据,也深入使用了我们几个月前发布的 Scale Search 论文。关键在于谨慎选择量化配方,并且非常仔细地评估。市面上有上百种免训练量化方法,重要的是选对组合、严谨验证。
谢谢。
好,我们得继续了。最后一个问题。
你对哪些模型架构最期待?例如 SSM、扩散语言模型(DLLM),或其他可能显著改善 decode 的架构?
Dan Fu:一次推理请求的生命周期(续)
有趣的是,我读博士时研究过 SSM 等架构,当时常听到“没人会用,这条路走不通,Transformer 会统治世界、带来 AGI”之类的话。几年后,这些技术已经进入大型模型。Kimi K3 有个叫 KDA 的结构,基本上属于 SSM 或线性注意力风格的层——这么说可能有争议——但它确实出现在最好的开放模型之一里。稀疏注意力也在使用;扩散语言模型则已经用在 speculative decoding 里。
我的学生最近对循环模型很感兴趣:让 token 多次经过同一组网络层,这样可以增加训练 FLOPs,却不增加权重数量。我们原以为这想法很奇怪、没人会用,结果发现 OpenAI 和 Anthropic 至少已经在用了。
现在是个非常令人兴奋的时期。如果你提出一个好的架构想法,并花力气证明它有效,它可能很快就会进入 GPT-6 或 GPT-7。反馈和产生影响的周期现在非常短。
谢谢你,Dan。
Jeff Morgan:开源模型的 token 并非都一样
大家好,我是 Jeff,Ollama 的联合创始人兼 CEO。今天想从更宏观的角度谈谈,为什么开源模型生成的 token 并不都一样,以及应用开发者该如何评估不同服务商的质量。现在推理公司已经不少,未来可能有几百甚至几千家。
Ollama 是一个 2023 年发布的开源项目,用来在本地运行开放模型。那时最受欢迎的模型,比如 Llama,体量较小,可以跑在一张 H100 上、笔记本电脑上或小型服务器上。项目一直想为开放模型提供类似 OpenAI 和 Anthropic 的开发者体验。后来模型越来越大,今年年初 Kimi、GLM 和 MiniMax 等发布了 5000 亿到 1 万亿参数的大模型,于是我们推出 Ollama Cloud,把本地开发体验搬到云端。今年这项服务发展很快,已成为美国和欧洲规模最大的独立开放模型云服务之一。
我们一直在思考如何让开发者跨模型、跨服务商获得良好体验。与传统推理服务商不同,我们关注及时提供最新模型、确保速度和可靠性。很多内部机制都在 Dan 刚才讲的路由器里。可靠性和尽早接入模型尤其重要,因为不同服务商擅长部署不同模型。
我们的架构也和很多 Ollama 客户相似。Fortune 500 企业中有很大一部分部署了 Ollama。和那些因为成本、控制权或其他原因从闭源模型转向开放模型的团队交流后,我们发现大家遇到的问题很相似。理想情况下,通过组合多个服务商可以兼得所长。服务商的定义也很宽:同一家服务商可能在不同地区、不同硬件上有不同部署,由不同团队使用不同推理引擎。
但把多个服务商组合起来会遇到一个核心问题:每家服务商运行模型的方式都不一样。这其实也有好处,因为不同团队擅长不同的性能优化。有些服务商用特定硬件;我听说最近甚至有一家推理服务商把 Mac mini 部署在世界各地。最终客户关注几个维度:成本、智能程度、速度,以及服务区域和隐私。跨服务商路由时,一家服务商在某个维度表现糟糕,就可能拖累整体体验。
Jeff Morgan:开源模型的 token 并非都一样(续)
如果某一家服务商在这四项标准中的一项表现差,客户体验就会被拉到最低共同水平。原因可能是模型精度太低、过度量化、硬件故障,或使用了不同版本的权重。
工具调用尤其容易出问题。表面上看只是解析 JSON 和字符串,实际要处理工具调用失败恢复、不同工具的参数名与 schema 校验,还要确保 tokenizer 层的解析正确。不同服务商可能采用不同采样方式;推理引擎也很复杂,可以修改很多细节,例如自定义 kernel、KV cache 精度。某些差异只会在很特殊的场景暴露,比如超长上下文。甚至会发生很荒唐的情况:接口标着一个模型,实际运行的却是另一个模型,很难察觉,因为它们看起来都像友善、愿意帮忙的助手。
服务栈里很多环节都可能出错。面向多个地区和服务商的大量客户时,定位问题很棘手。我为今天的演讲梳理了行业已经做过的研究,发现这并不是新问题。大家常比较开放模型和闭源模型之间的差距,但对于同一个开放模型,最差服务商和最佳服务商之间的差距,可能比开放模型和闭源模型之间的差距还大。这问题相当严重。像 Together 这样的优秀伙伴提供的体验,可能与另一家服务商的同一模型完全不同。
这和 OpenAI、Anthropic 带动 token 需求的世界很不一样。使用闭源服务时,大家通常期待无论通过什么入口访问,都能得到一致体验;开源模型并非如此,服务差异可能比开放模型与闭源模型的性能差异还大。2024 年有篇论文测试了 31 个 Llama 接口,也发现同一模型的不同部署表现差异很大:有些 Llama 部署的表现甚至更接近 GPT-3.5,而不是号称完全相同的另一个 Llama 部署。
这个问题在编程 Agent 和其他 Agent 工作负载里更严重,因为它们上下文很长、执行周期也长,往往连续调用多次。某次响应不准确,错误就会层层叠加。一个看起来不复杂、需要 15 步的编程任务,如果每一步有 10% 概率偏离预期,最后整体可能有 79% 的概率出错,体验自然会很糟。
Jeff Morgan:开源模型的 token 并非都一样(续)
对 Agent 而言,任务越难,问题越严重。怎样监控和检查推理接口?显然不可能把所有 token 都读一遍,尤其每张 GPU 每秒就能处理 160 万个 token。最直接的办法是跑评测,但这也是最昂贵、最费时的办法。Artificial Analysis 会定期在不同服务商上跑基准并排名。比如图里的 Kimi K3,大多数服务商都做得不错,但也有一些明显落后。基准能发现糟糕的量化等问题,不过运行成本高,无法持续做。
另一个办法是像 Moonshot 那样发布工具调用验证器和排行榜。Moonshot 曾受不了不同服务商对 Gemini 模型工具调用的处理差异,于是推出 Gemini K2 工具验证器和服务商排行榜,推动大家竞相提高工具调用准确率。模型开发者提供测试工具,能让使用者更正确地部署模型。
我们也在考虑分布测试:比较参考权重模型和服务商 API 输出的分布,衡量两者差距。它通常很便宜,也许每项测试约 1 美元;但它未必抓得到复杂问题,例如糟糕的量化,也不一定能解释问题原因。全面评测套件更容易定位具体测试,但需要运行参考模型,成本会增加。
还可以比较 log probability(对数概率)。只需发一个 token 的请求,取得下一个 token 的概率分布并和基线比较,就能便宜地观察服务商是否发生漂移。比如是否迁移了硬件、升级了推理引擎。论文案例发现不同端点存在大量变化,能识别服务栈悄悄发生的改变。推理引擎(如 vLLM、SGLang)会持续更新,用这种方式监控有助于维持客户体验一致。不过不少 API 不开放 log probs;而且它只能发现相对过去的漂移,若一开始就服务错了就帮不上忙。
Jeff Morgan:开源模型的 token 并非都一样(续)
很多路由器现在会在不保留请求数据的情况下做一些检查:统计有多少工具调用通过、多少出错、是否发生工具调用错误,以及请求形态如何随时间变化。不同服务商的输出长度可能不同。观察请求外形就能发现问题,例如 DeepSeek 服务曾出现模型陷入无限循环。可以逐个请求保留一个运行分数持续监控,OpenRouter 的 Exacto 等做法也有类似思路。
我们的目标是让开放模型也有 OpenAI 和 Anthropic 那样稳定的体验。闭源实验室非常重视服务质量;去年 Anthropic 曾有一个 TPU kernel 小 bug,可能导致模型质量问题,足以引发一次完整的故障回顾。开放生态也需要这样的质量保障。一个方向是模型实验室共享更完整的运行栈。现在通常只是把权重放到 Hugging Face 或 Ollama,再附上示例代码,但那可能并不是实验室实际部署的服务栈,而是应用团队另外写的示例。
DeepSeek 昨天发布了自己的推理栈 DeepInfer,可以把 DeepSeek 权重放在自己的 GPU 上运行,希望达到每 GPU 小时 38 美元的成本。统一运行栈能帮助新兴服务商更有把握地正确部署模型。越来越多实验室也会在发布前与 Dan 团队这样的专家合作做好量化,让自家 API 与公开开放模型在量化方式上更一致;这不同于过去模型发布后由没有训练数据的人事后量化,只为把模型塞进 MacBook 等设备。
也可以通过较底层的 API 访问模型:把工具调用放进统一的 harness,而不是交给每家服务商分别处理,就能提高一致性和准确度。推理过程和思考内容的提取也是如此。LLM 质量监控对关键应用至关重要,创业公司在这方面有机会。一篇我很喜欢的论文还指出,现代 NVIDIA GPU 都有可信执行环境,可以证明当前运行的权重和软件;由此生成指纹,确认模型是否按正确方式服务。这个想法还比较前沿,但很有意思。
开放模型正在到处部署,我们需要评估质量,确保用户真正拿到好模型和好 token。谢谢大家。
Jeff Morgan:开源模型的 token 并非都一样(续)
在长时间、多轮 Agent 任务中,你怎样设定 prefill 的质量评测间隔?如何比较工具调用与长上下文?比如 decode 48 或 64 步后,是接纳 API 工具调用,还是优先处理运行中上下文的 prefill?
我不确定自己是否最适合回答调度接纳问题。若你指的是我那张图,思路是发一个单 token 提示,测输出的 log probs,再与基线比较,持续监测变化。这并不针对某个特定上下文长度。可以用越来越长的提示做同样测试,观察长度增加时 log probs 偏离多少。部分服务商会直接限制上下文窗口;尤其超过 20 万 token 后,可以检查下一个 token 的准确性是否仍与参考模型或过去的结果一致。这是一种无需跑完整评测的简洁方法,不过我对相关论文细节并不都熟悉。
如果公开测试越来越多,量化团队会不会针对评测“爬坡”,只优化测试分数,却没有保留模型质量?怎么避免?
当大量服务商争夺最低 token 价格时,确实可能只针对某些流量模式优化。我们会与客户一起设计稳定运行的一组测试,贴合他们具体的使用场景。这些测试依赖客户自己的数据或流量,不公开,服务商不容易针对它们作弊。这样可以发现某家服务商在特定客户场景下没有达到应有表现。质量问题通常也是客户先报告,因此这种做法能把反馈闭环补起来。
我刚接触 Llama 时,大家用本地模型;后来都转向云端。今天随着 Flint 和 Richard Socher 的 Recursive 发布,又回到了本地模型。你怎么看 Ollama 的未来?
现在本地运行模型的方法很多,也有不同推理引擎,例如 Apple Silicon 上的 MLX。
还有 Calibri,可以在本地运行 Qwen 3.5 MoE,直接从磁盘提供服务,很酷。
Jeff Morgan:开源模型的 token 并非都一样(续)
本地推理方式确实很多。我们谈到的所有问题同样适用于本地模型服务,无论是桌面设备、桌边的 DGX Spark、新出的 M5 Ultra,还是企业 GPU 数据中心。问题不仅在服务商,也在你选择的模型服务技术栈;你需要可靠测试它。
我们很高兴成为 Recursive 的首发合作伙伴,Flint 这个本地模型令人振奋。不过,不论是云端服务商把 token 返回给你,还是你自己运行推理引擎、每周更新一次,本质上都是同一个质量问题。开放模型的现实有点像西部荒野:模型可定制、可修改、可量化;几乎每个模型都能从 Ollama 或 Hugging Face 找到二十种左右的量化版本。难点是如何评测。线上服务不能每次都跑完整基准,还需要更轻量的持续测试,因此本地模型同样必须重视这件事。
谢谢大家。Ollama 的未来可能是人们混合使用本地和云端模型。新模型在本地编程方面很强。过去许多最好、最难的编程任务只能交给今年兴起的云端模型;现在,一些超强本地模型可以在 MacBook 上运行。路由问题将从云服务商之间的路由,扩展到本地与云端之间的路由。谢谢大家。
Joe Fioti:用搜索编译模型,而非依赖启发式
大家好,我叫 Joe,是 Luminal 的联合创始人兼 CEO。我们是一家编译器公司,这听起来有点特别,但接下来会解释原因。编译器是整个系统栈的关键部分,它决定 GPU FLOPs 或 GPU 小时能转换成多少 token。编译器做得好不好,决定你亏钱、赚钱,还是赚很多钱。
我们做的编译器基于一种很新、很特别的技术,叫等式饱和(equality saturation)。我们认为它是将模型高效编译到多种硬件上的正确方法。我认为 NVIDIA 值 4 万亿美元,很大程度上得益于 CUDA 软件生态完善。把模型映射到复杂硬件上是个非常难、至今还没真正解决的问题。我们的做法是充分利用搜索:在编译时进行大量搜索,这样不用维护传统编译器里成堆复杂的改写规则和启发式方法,也不必每出一个新模型就维护庞大的 kernel 库。
我们以很小的共享编译器核心为基础,针对不同数据中心推理 ASIC 构建后端,支持 NVIDIA 和 AMD GPU、TPU、Trainium 以及各种推理 ASIC。我们每月大约运行 80 到 90 万亿个 token。我们不是 Together,但团队只有 8 个人,总有一天会赶上。
今天主要讲我们如何看待编译器,介绍一种不同于典型 MLIR 编译器栈的方法,以及它为什么适合 LLM、扩散模型、生物模型等机器学习应用。我会介绍支撑等式饱和的 egglog 引擎、等式饱和的含义、怎样设计中间表示(IR)来适配不同硬件并充分利用硬件,以及如何扩大搜索规模。
我们观察各种神经网络和深度学习应用后发现,它们并没有那么复杂,本质上是稠密线性代数,而且可用的稠密线性代数操作种类不多。我们把模型归约到大约 14 或 15 个原始操作,比如加、乘、求和等。这样可以把 PyTorch 的各种操作分解为很精简的一组操作,不会丢信息。它并非图灵完备,但我喜欢称它为“PyTorch 完备”:只要模型可以用 PyTorch 表示,我们就能导入并编译到支持的后端。比如矩阵乘法甚至不是我们的原语,我们会把它分解成广播乘法再加求和归约。PyTorch 有大约 2000 种操作,新模型又很复杂,硬件操作也很多;用这种中间层可以限制映射复杂度。
Joe Fioti:用搜索编译模型,而非依赖启发式(续)
不要让所有 PyTorch 操作和所有硬件操作彼此直接映射;中间需要一个瓶颈层,把 PyTorch 操作统一映射到原语,再从原语映射到底层硬件操作。我们的 RISC 风格原语集合就承担这个角色。
编译器领域有个 1990 年代的术语叫“超优化”(superoptimization),当时除了学术研究并没有真正普及。核心思想是搜索某个程序所有可能的形式,再通过成本函数挑选最佳形式。这样编译器工程师就不必事先知道如何把给定程序降到特定硬件上。可能的映射方式呈指数级增长;传统公司因此需要不断扩大编译团队,团队规模会随要支持的应用、模型架构、后端和数据类型急剧膨胀,甚至可能需要 500 到 1000 名工程师,结果编译器仍不完美。
我们希望编写很小、原子的重写规则,描述哪些表达式彼此等价,再让搜索决定何时使用哪条规则,而不是由人写死规则顺序。等式饱和正好能做到:定义等式重写规则,构建搜索空间,再遍历搜索空间。
我们的 IR 是计算图,也就是有向无环图(DAG),包含加法、乘法及它们之间的依赖关系。我们使用 e-graph。普通重写规则会在图里匹配一个模式并用新表达式替换,旧信息会被丢弃,因此必须确信这条规则正确。e-graph 则以非破坏方式应用重写规则:把等式右侧的信息也加入图中,同时保留等式两边、变换前后的表达式。
我们按各种可能顺序持续应用所有重写规则,直到无法再增加信息。此时 e-graph 达到“饱和”。之后从中抽取许多具体计算图,把它们编译成目标硬件上的可执行程序,实际运行并计时,目标就是最小化运行时间。这是一个直接的流程。
图上左边的例子可以看作表达式 A×2÷2:根节点表示整个表达式,向下的节点代表除法两边。应用规则后,图不断扩展,例如 A×2 等价于 A 左移一位。继续应用规则……
Joe Fioti:用搜索编译模型,而非依赖启发式(续)
饱和图会发现 A×2÷2 等价于 A,因此可以简化表达式,不必事先写一条专门匹配该模式的启发式规则。我们的重写规则很简单,用 Lisp 语法编写,因为所用引擎的作者喜欢 Lisp。比如交换律 x+y=y+x;不过浮点数上这未必严格成立,IEEE 浮点的结合律、交换律都比较棘手。另一个规则是常量折叠:如果编译时已知 a+b,就直接算出来,从程序里删掉这段运行时计算。
核心原语 IR 在所有后端共享,但我们希望编译到 TPU、Trainium 和 GPU。每种硬件都提供一组实现好的操作,可能在不同抽象层级。GPU 的 Tensor Core MMA 就是一种操作,从 SRAM 读取输入并把结果写回 SRAM。我们会刻画新的硬件后端,并定义它的操作如何等价于编译器已知的操作,再写少量重写规则;这些等价关系会与已有规则组合。因此,即便新硬件和现有后端差异很大,接入它也相对省力,不必养一支庞大编译器团队维护复杂改写。
硬件本身是分层的:你可能编程单个线程、一个 warp、一个 thread block(大致控制一个 GPU 核心/SM),也可能编程整张 GPU,甚至整台节点。我们的 IR 是多层级的,能明确表示这些层级,并接纳社区或供应商库在不同层级实现的操作。等式饱和能把它们不同的语义连接起来,描述什么等于什么,再让引擎搜索替换。
Joe Fioti:用搜索编译模型,而非依赖启发式(续)
例如,cuBLAS 有从 CPU 调用的主机级操作,负责完整矩阵乘法。NVIDIA 的 CUTLASS、cuBLAS DX,以及 Hazy Research 的 ThunderKit,则提供 thread block 层级操作,一次编程一个 GPU 核心。编译器能理解不同层级的操作,所以可以把低层子图组合成 mega-kernel。一次 forward pass 可以由普通 kernel 和 mega-kernel 混合实现。Mega-kernel 很酷,但并非总是最佳方案,尤其模型很大时。
定义搜索空间后,还要判断程序 A 是否优于程序 B,也就是需要成本模型或适应度函数。要针对现代 GPU 建立准确成本模型非常困难,需要许多博士级工作。小公司不可能给每种目标硬件都做出精准成本模型。按照“苦涩的教训”,最好的成本模型是不做成本模型:直接在目标硬件上运行程序,测量时间。这个办法听起来笨,却很有效;程序员觉得无益的搜索变换,真实 GPU 测出来可能反而更快。
当然无需跑完所有搜索空间。可以用 roofline 等方法估计子程序下限,提前剪掉已知不可能更快的部分,但总体上我们尽量在真实硬件上测量。演示视频展示了系统生成 kernel 的过程。顺便宣传一下:我们这个编译器公司罕见地解决了盈利问题,许多编译器公司都没找到赚钱方式。我们的云运行在多种异构硬件上,每月处理约 8000 万亿 token 和数百万张图像。通用编译器不仅能运行主流模型,也能支持蛋白质折叠、生物模型、图像模型等各类模型。公司现在 8 人,正在快速扩张、积极招聘。我们用特别的编译技术把不同硬件变成可替代的通用算力;欢迎访问 Luminal 官网。
Joe Fioti:用搜索编译模型,而非依赖启发式(续)
我喜欢你们 RISC 风格的方法。针对机器学习工作负载,你们做了哪些适配?浮点数里的结合律和交换律很微妙,但机器学习似乎可以接受不同运算顺序。你们怎样把这一点放进成本模型或语言设计?
结合律和交换律仍然重要,因为它们会影响数值精度。树形求和与顺序求和结果会不同,数值精度错误确实会影响输出 token 质量,所以我们会明确建模。另一方面,重写规则有时也能利用硬件上输入 A 和输入 B 的不同实现方式。例如 NVIDIA Tensor Core 可能要求输入 A 来自 SRAM,而输入 B 来自另一种内存空间。
直接在实际硬件运行似乎很困难:如果是整个模型,成本不现实;如果只测单个 kernel,又怎样建模竞争?另外你们扩大了搜索空间,搜索怎么扩展?
这其实是两个问题。完整模型 forward pass 和一次 profiling 迭代通常不到 10 毫秒,因此一秒能跑约一千次,仍然很快。搜索空间确实很大,我们用遗传算法等常规搜索方法。以后可以尝试 MuZero 这类学习引导的搜索,但目前还不需要。我们只搜索整个空间的 1% 的 1%,但不追求全局最优,只要找到接近全局最优、比如达到 99% 性能的局部最优,难度就小很多。
编译时间是明确接受的取舍:推理客户只要运行更快,就不太在意编译时间。一个编译产物可能服务数百万张 GPU;如果编译一天能换来 1%、5% 或 10% 的运行时提升,就值得。通常可以设置一小时或十小时的编译预算,直到收益递减;搜索往往能较好扩展,但最终也会遇到边际收益降低。
你们会用实际推理流量的 profile 引导搜索吗?
我们尽量使用贴近真实的输入。因为自己经营云服务,我们知道客户关心的张量形状,也大致知道运行时会输入什么形状和数据分布。只要重写规则正确,程序结果就正确;用行业真实的张量形状计时,也能得到相当准确的性能数据。
Joe Fioti:用搜索编译模型,而非依赖启发式(续)
不同模型架构映射到不同硬件时,调试很困难,尤其要找出哪个层的算子降级出了问题。Luminal 怎么解决?
通用调试一直都很难。我们使用 PyTorch 提供的工具给高层操作打标签,并在编译器中跟踪这些元数据;也使用标准 PyTorch profiler 找出瓶颈。等式饱和和 egglog 还有个好处:如果输出程序错了,可以要求它给出从输入程序到输出程序的证明,也就是列出应用过的重写链条,然后很快找出无效规则。
我很喜欢这种设计。不支持的操作通常可以回退到 CPU,不过你们会把操作展开,而编译器一般想融合操作;这会造成多少延迟影响?
我们确实会做融合。先把操作展开成核心原语 IR;降低到硬件时,编译器会搜索不同形式,最后也通常会得到融合操作。我们会用 roofline 直觉判断:如果某个 kernel 在 DRAM 中搬运的数据比另一种方案多一个数量级,那大概不理想。中间表示会展开操作,随后搜索再找到模式并重新融合。
你提到语言并非图灵完备,这意味着不受 Rice 定理限制。你们在哪一层利用这一点?
没错,这也是早期的重要发现。1990 年代超优化没有成功,部分原因是试图用于 C 这类通用语言。C 是图灵完备的,可编译形式几乎无穷,推理非常困难。我们编译的只是稠密线性代数程序,范围远比任意程序窄;它可以表示 PyTorch,却不是图灵完备。我们可以分析……
Joe Fioti:用搜索编译模型,而非依赖启发式(续)
我们能分析不同内存空间之间到底搬运了多少字节,据此推导 roofline 性能上限,不必先运行模型。所以可以大量提前剪枝,只需相对于完整搜索空间运行少量 profiling。
谢谢。你们的搜索空间会包含量化、推测解码和并行策略吗?
通常不会。我们主要负责 forward pass:给定 forward pass 计算图,把它编译好。vLLM 和 SGLang 等推理引擎已经很好地支持推测解码,我们可以直接使用。我们认为主要收益来自处理复杂并行拓扑和 forward pass 本身,其他创新留给推理引擎,因此不会搜索到那一层。
谢谢 Joe。
Liangsheng Yin:SGLang 与 Agent 时代的内存
大家好,我是 Leon Shaw,担任 SGLang 和 RadixArk 的总裁。(字幕里的自我介绍姓名与节目章节所列的 Liangsheng Yin 不一致,可能是语音识别错误。)很荣幸受邀。我原以为这是读论文的俱乐部,大家会集中讨论一篇论文;Francois 刚才讲了很多技术,而不只是一篇论文。我原本准备了一些 SGLang 原始论文、开源项目和当前优化的内容,后来又加了几页,现在就开始。
这个故事与 Agent 工作负载有关,可以追溯到 2023 年底。当时开放模型主要就是 Llama,人们还在猜 Agent 工作负载会是什么样。我们预想会有工具调用、并行子 Agent,类似现在的云端编程助手。比如你在 Cloud Code 里启动一个子 Agent,多个 Agent 会共享同一个 KV 池中的大型上下文。监控各自结果时,你输入的提示可能很短,却会多次进入引擎、再多次离开。那时引擎还不能高效复用共享前缀,所以我们提出 RadixAttention,让它自动复用共享前缀,只计算新的后缀。
我们提出 RadixAttention,把所有 Agent 的上下文纳入引擎内的内存管理系统,像树一样组织,内部叫 Radix Tree。图里的例子是共享一个长系统提示:一个 Agent 做认证,一个做审查,它们基于同样提示分别执行不同任务。内存有限时,某个 Agent 的后缀可能被淘汰。我们的调度和核心设计都围绕这棵 Radix Tree 展开。
左侧图展示 Agent 的前缀保护。需要腾出内存时,我们淘汰未使用的叶节点。调度和淘汰算法可以根据工作负载及需求调整。
Liangsheng Yin:SGLang 与 Agent 时代的内存(续)
Agent 会交错地向引擎发送提示。如果能重新排序,就可以按缓存友好的顺序批处理、复用上下文 A,而不是让 A 和 B 交错处理后冒着缓存被淘汰的风险。
这就是 SGLang 成为服务引擎的过程:原始论文提出在内存管理系统中构建 Radix Tree;到 2024 年中,我们把它发展成通用的大语言模型推理引擎,并发布 0.2 版本,支持 Llama 8B、Llama 405B 的在线和离线服务。
批处理、内存管理和淘汰都需要给等待请求排序并设置优先级。GPU 推理越来越快,但 CPU 效率没有同步提升。传统调度会先准备批次一、运行批次一、取回数据,再准备批次二,导致 GPU 空转。GPU 较慢时空转通常可接受,约在 10% 以内;GPU 越快,CPU 造成的空泡就越明显。
因此我们设计了重叠调度:把设备到主机的同步延后一个周期,避免关键路径上的阻塞操作;同时提前准备下一批。批次一运行时就发起批次二,不让 GPU 等待。现在很多新引擎都采用类似机制,包括 DeepSeek 新发布的推理引擎。Hopper 上相比普通调度吞吐约提升 1.1 到 1.5 倍;到了 Blackwell,在 GB 配置下有时可达到两倍。
Agent 和缓存的故事还在继续,因为 GPU 内存始终有限……
Liangsheng Yin:SGLang 与 Agent 时代的内存(续)
使用长上下文时,用户可能几分钟、几小时甚至几天后才继续发送下一轮提示,因此要找到地方保存之前的前缀。于是我们引入分层缓存,这是许多引擎常见的技术:把 GPU 显存、主机内存和内部存储组织成 L1、L2、L3 缓存。每个 token 可以在不同层级,按策略管理,以提高缓存命中率、缩短从 L2 到 L1 或从 L3 到 L2 的加载时间。我们的实验中,这使 TRFT 降低了 56%。
传统 Transformer 在长上下文和高效部署方面不够理想,模型架构正在不断创新,例如滑动窗口注意力,以及保存 recurrent state、memory state 或 KDA 状态的结构。它们逐 token 把信息写进固定形状的状态。看似只需给不同层增加不同内存池,形成混合存储和计算,但并不简单,因为还要考虑不同缓存之间如何共享。
比如想在位置 10 命中缓存,完整注意力池需要匹配完整 KV token;如果滑动窗口大小为 4,就至少还需保留位置 7 到 10 的四个 token。若只保留到位置 8,就无法命中,因为滑动窗口要重新完整计算。想从位置 10 共享前缀,也必须恰好保留位置 10 的 memory/KDA 状态。若分开管理不同内存池,高效共享缓存就非常困难。
缓存命中率从 95% 提高到 99%,成本可降低五倍,而不是只省 5%,因为推理计算量会变成原来的四分之一。
Liangsheng Yin:SGLang 与 Agent 时代的内存(续)
以前 Radix Tree 是独立实现的,没有考虑底层不同内存池,因此会遇到兼容性和灵活性问题。要保护历史、锁定前缀节点,也需要在完整注意力层、滑动窗口层和循环层之间协调,各组件得遵守协议满足外部策略。
因此我们引入统一 Radix Tree。我们不再把这些组件视为互不相关的独立部分,而是基于完整 token 构建语义 token 树。无论架构如何变化,完整 token 至少目前始终存在;其他 token 状态仍由各组件内部维护。统一 Radix Tree 作为控制器和协调者,帮助每个组件实现最佳缓存匹配效率。各组件保留自己的匹配、淘汰和内存规则,但都能与统一树配合,处理边界情况,避免内存泄漏或浪费。
另外还有个我没放在幻灯片里的问题:完整 token、窗口 token 和循环状态三类存储,在不同用户和工作负载中的比例差异很大。有人上下文只有 4K,有人用 128K,还有人始终使用 100 万 token。后一类需要完整 token 池,而滑动窗口可能只需要最近 128 个 token。不同工作负载的比例不同,不能固定预留内存比例。资源有限、又要支持多种负载时,必须用统一方式管理所有底层内存池。
Liangsheng Yin:SGLang 与 Agent 时代的内存(续)
除统一 Radix Tree 外,我们还提出统一内存池,以服务不同工作负载。过去按预先算出的固定比例分配内存;现在只分配一整块物理内存,不给 4K 上下文池或滑动窗口 KV 池设固定上限,而是按字节细分,让不同池从物理内存两端按实际使用情况增长。上下文很长,就给完整 token 池更多内存;上下文较短,就把更多内存给循环状态和窗口 KV。
但许多 kernel 和后端要求数据在物理内存中连续。提前分配和淘汰会在 GPU 物理内存里留下空洞,而这些空闲区域可能无法重用,因为会遇到不同内存池的边界。
为此我们引入 compaction(压缩整理):重新组织物理内存中的碎片,用低延迟内存拷贝 kernel 把数据紧凑排列,再重新映射内存页 ID。用户看到的虚拟页 ID 不变,只改变底层映射,因此整个服务工作负载更灵活。
从服务引擎开始,我们也把 Miles 推理引入训练循环。XLA 和 Miles 主要由 Red Hat AI 贡献:XLA 负责 rollout,是 Miles 强化学习训练的合适后端;Miles 支持完全异步执行,让生成和训练持续推进。
我们从 RadixAttention 起步,逐渐发展成开源推理引擎、Miles、XLA 和扩散模型支持,并做了很多工作来推动开源 AI 基础设施。接下来几个月将举办 XLA 峰会,会有不少嘉宾演讲,欢迎扫描二维码报名。
Liangsheng Yin:SGLang 与 Agent 时代的内存(续)
以上就是我的演讲。有什么问题吗?(掌声)