最新资讯
bloomberg.com Nvidia 加强东南亚芯片追踪以打击走私 thestack.technology 模型路由需求升温,Agent Router 推出开源替代方案 www.youtube.com Google DeepMind 的 Philipp Schmid:AI 同事需要具备的七个要素 unite.ai Cashfree 为 AI Agent 的托管结账加入 WebMCP 工具 dev.to 我们在 DolphinBench 上测试记忆检索:纯关键词搜索暴露了自身回归 dev.to 别再把 Agent 写成 while 循环,把它建模为状态机 analyticsindiamag.com 小语言模型可能重塑企业 AI 部署方式 bloomberg.com Rightmove 与 Scout24 借 AI 产品应对低迷房市并上调展望 stackoverflow.blog 欢迎来到芯片时代:半导体制造、AI 数据中心与芯片设计的未来 www.youtube.com AI Agent 总犯同样的错:CentralAgent AI 将记忆重构为经验系统 pub.towardsai.net Netflix 科学家建议重采样 LLM 评判:5 次仅将误差棒缩小 13% pub.towardsai.net Jev 作为 LLM 前的静默层:构建提示感知的模型路由器
多元动态
登录 注册
大模型 pub.towardsai.net · @Srini Dwarakanathan

开源权重LLM推理的延迟优化杠杆(第一部分)

原文 我的收藏

文章讨论LLM推理的延迟优化,强调解码是瓶颈,并介绍量化、投机解码、张量并行等技术,以及如何选择GPU和组合优化。

AI推荐理由 针对开源权重LLM推理的延迟优化,涵盖量化、投机解码等技术,内容具体,对工程实践有较高价值。

70

正文

人工智能 机器学习 数据科学 软件开发 软件工程 开放权重LLM推理的延迟优化杠杆:第1部分 Srini Dwarakanathan 22分钟阅读 · 2026年8月31日 -- 听 分享 索引 引言 为什么解码是瓶颈 指标 设置 量化 推测解码 张量并行 选择GPU 叠加杠杆 结论 参考文献 我的其他文章 引言 在面向用户的产品中服务大型语言模型,首先是一个延迟问题,然后才是其他问题。一个回答正确但需要十秒的模型在聊天框、编码助手或语音代理中是不可用的。与训练运行不同,推理延迟在每次请求时都会付出代价,而且是永久的。因此,一旦模型对任务足够好,工程工作就转向另一个问题:我们如何让它在我们实际能获得的硬件上更快响应,而不改变它说什么? 最后一点很重要。服务LLM时有两个值得跟踪的轴,精确知道一个更改实际移动哪个轴是大部分重点: 延迟:单个请求端到端需要多长时间。这是等待用户感受到的。 吞吐量:同一硬件每秒可以服务多少请求。这是账单反映的。 按回车或点击查看全尺寸图片 SageMaker LLM延迟杠杆。使用Gemini AI生成的图像。 这些杠杆中的每一个都是通过服务开放权重模型解锁的。当您通过封闭的托管API消费模型时,延迟是提供商给您的任何值:您不能更改权重的数值精度、附加推测性草稿头、将模型分割到您选择的GPU上,或将其移动到更快的硬件。使用开放权重模型,您拥有整个服务栈,因此每个都成为您可以实际转动的旋钮。这是本文的前提:开放权重使推理延迟成为您可以解决的工程问题,而不是交给您的数字。 本文的其余部分介绍了减少LLM推理延迟的杠杆、每个杠杆背后的机制、如何启用它,以及测量时它实际带来了什么。杠杆是权重量化、推测解码、张量并行和硬件选择。每个都以一般方式描述,但数字来自具体设置:Qwen3–8B,阿里巴巴的开放权重(Apache-2.0)模型,在AWS SageMaker上服务,在下面的设置部分描述。这些技术都不是Qwen3–8B特有的;它们适用于任何开放权重模型,机制和每个结果的方向对更大的模型不变。这里使用8B模型主要是出于实际原因:对于像Kimi K2或GLM-4.6这样的前沿开放模型所需的更大实例的GPU容量在AWS上难以获得,因此一个能舒适地放在可用硬件上的模型使杠杆易于隔离和测量。在更大的模型上绝对延迟会不同,但哪个杠杆移动哪个轴不会。 两个范围说明。首先,模型质量不在本文档范围内。这些杠杆中的几个,尤其是量化,原则上可以改变模型的输出,生产采用决策必须衡量这一点。这里我们搁置这个问题,将每个配置纯粹视为延迟工件;衡量质量影响是它自己的练习(参见推理工程,§5.1.3,了解如何做)。其次,本文假设熟悉Transformer推理和GPU的基础知识。如需复习底层概念,如GPU架构、数字格式和推理引擎,Philip Kiely的《推理工程》(Baseten Books)是一个极好的参考,并在各处引用。Medium文章《LLM推理手册2026》是这些基础的另一个良好入门,更短且免费可访问。 为什么解码是瓶颈 要推理哪个杠杆有帮助,有助于理解模型生成响应时时间实际花在哪里。LLM分两个不同的阶段回答请求,它们具有完全不同的性能特征。 预填充是第一阶段。模型在单次前向传递中读取整个提示,每个令牌,并产生第一个输出令牌。因为整个提示同时可用,这次传递高度并行:GPU有大量矩阵工作要做,可以让其计算单元保持忙碌。预填充是计算密集型的。其成本随提示长度扩展,并决定首令牌时间(TTFT)。 解码是第二阶段,也是实际生成响应的地方。模型一次产生一个令牌,每个令牌需要自己的前向传递,依赖于之前的所有令牌。生成256个令牌的答案意味着256次顺序前向传递。每次传递必须从GPU内存中读取模型的整个权重集,以产生单个令牌的计算量。这是关键的不对称性:每次传递的算术量很小,但移动的字节数巨大,即整个权重矩阵加上不断增长的KV缓存。因此,解码受内存带宽限制,而不是计算限制。GPU在每一步的大部分时间都在等待内存,而不是计算。 正式版本是ops:byte比率(或算术强度):GPU每从内存读取一个字节可以执行一定数量的浮点运算,如果内核每字节执行的操作少于该比率,则受内存带宽限制而不是计算限制(推理工程,§2.4)。单流解码远低于该比率,因此它完全是内存受限的。 这个单一事实,即解码受内存带宽限制,是本文其余部分所依赖的心智模型。它预测,在运行任何东西之前,哪些杠杆应该有效: 任何每令牌移动更少字节的东西(更小的权重)应该加速 直接解码。 任何每次前向传递产生更多令牌的方法(推测解码)都应该加速解码,因为瓶颈是内存受限的传递次数,而不是每次传递中的计算量。 任何增加内存带宽的方法(更高带宽的GPU,或将模型拆分到更多GPU上)都应该加速解码。 任何只减少计算量的方法几乎不会影响解码延迟,因为计算不是限制因素。 测量结果证实了这一点。在本工作中使用的基线上,Qwen3–8B在四个NVIDIA L4 GPU上以FP16运行,将提示从72个令牌增长到1,608个令牌仅增加了约0.35秒(预填充便宜且受计算限制),而将输出从256个令牌增长到1,024个令牌几乎线性地增加了延迟,大约4倍。输出长度而非输入长度驱动延迟,这正是解码受限模型所预测的。 指标 由于延迟不是一个单一数字,本文通篇使用几个术语(推理工程,§1.4): 按回车或点击查看全尺寸图片 LLM推理延迟和吞吐量指标。图片由Gemini AI生成。 本文中的每个配置都针对同一组指标报告,以相同方式测量,因此可以直接比较各种杠杆。 设置:SageMaker上的Qwen3–8B 模型。每个配置都服务Qwen3–8B,这是一个由阿里巴巴根据Apache-2.0许可证发布的80亿参数开放权重模型。由于权重是开放的,同一个模型可以以不同的数值精度(FP16、FP8、AWQ INT4)加载,与推测性草稿头配对,并在GPU之间移动,而无需改变其本质,这正是允许下面的杠杆针对共同参考进行测量的原因。FP16基线使用SageMaker JumpStart工件;INT4传递使用预量化的Qwen/Qwen3-8B-AWQ检查点;推测解码传递附加了训练好的RedHatAI/Qwen3-8B-speculator.eagle3 EAGLE头。验证器权重在所有三种情况下都是相同的8B模型。 硬件。使用了三种SageMaker实例类型,均为Ada一代(sm_89)NVIDIA GPU,因此数值格式和内核具有可比性: 按回车或点击查看全尺寸图片 用于基准测试的SageMaker GPU实例。图片由Gemini AI生成。 服务引擎。模型通过vLLM提供服务,使用SageMaker的DJL-LMI容器。vLLM是一个广泛使用的开源推理引擎,用于在GPU上服务LLM,设计用于高吞吐量,并支持本文依赖的优化,包括量化和推测解码;SageMaker的DJL-LMI容器将其打包在托管端点后面(推理工程,§4.3.1)。推理引擎在所有配置中保持不变,因此它永远不会成为混淆变量。每次传递之间唯一改变的是正在测试的杠杆。vLLM默认使用连续批处理,值得精确说明它的作用,因为它移动了引言中的两个轴。 静态批处理等待固定大小的批次填满后才运行推理,这使最早的请求排队等待。连续批处理(也称为在途或令牌级批处理)则一次操作一个解码步骤。一旦有插槽释放,它就将新请求交换到正在运行的批次中,因此请求在下一步开始,而不是等待批次组装。减少排队时间意味着连续批处理相对于静态或动态批处理降低了延迟并提高了吞吐量;这是对它们的严格改进,而不是权衡(推理工程,§7.2.1)。 权衡存在于下一层,即批次大小。随着并发性上升,每个解码步骤中会有更多序列。由于该步骤受内存带宽限制,并且无论有多少序列共享它都必须读取完整的权重矩阵,因此打包更多序列会提高总吞吐量。但它们现在竞争相同的带宽,因此每个单独请求的P50和尾部延迟都会增加。这就是引言中的延迟与吞吐量紧张关系,具体化:“增加批次大小将产生更高的整体吞吐量,但每个用户的延迟将变得更糟”(推理工程,§7.2.1)。这就是为什么下面的每个配置都报告两次,一次是并发1时的单请求延迟,一次是并发扫描,这样每个杠杆的单流效应就不会与批处理效应混淆。 工作负载。查询集是180个真实、经过过滤的ShareGPT提示:自包含的任务,迫使模型读取输入并生成响应。提示按输入长度分组到桶中,每个桶的输出长度固定,以便可以分别读取预填充和解码成本: 按回车或点击查看全尺寸图片 按令牌长度划分的基准工作负载桶。图片由Gemini AI生成。 每次传递的测量方式。每个配置部署到自己的SageMaker端点,使用固定测试工具进行基准测试,然后拆除。单请求数字在并发1时获取;并发扫描驱动real_medium桶在1、2、4、8和16个并发请求下。所有延迟都是端到端请求时间(秒),除非另有说明,TM95是丢弃最慢5%样本后的平均值。报告中的传递之间的差异一次只改变一件事,无论是精度、草稿头、GPU数量还是实例类型,因此每个测量差异都可以归因于它隔离的单个杠杆。 量化:更小的权重移动更少的字节 第一个杠杆直接来自心智模型。解码每次令牌从GPU内存中读取整个权重矩阵,因此该矩阵中的字节数设定了令牌生成速度的硬性下限。缩小权重,每个解码步骤移动更少的字节,因此在带宽受限的路径上完成得更快。这就是整个机制,也是为什么量化权重是最直接的延迟杠杆。 Qwen3–8B大约有80亿个参数。以FP16存储,解码每次令牌必须流式传输约16 GB的权重。两种量化格式可以减少这一点: FP8将每个权重存储为8位而不是16位,约8 GB,字节减半。vLLM可以即时执行此操作,因此不需要单独的检查点;这是一个单一的服务标志(OPTION_QUANTIZE=fp8)。 AWQ INT4将每个权重存储为4位,计入AWQ保留的组缩放后约5.5 GB,仍约为FP16的三分之一。AWQ仅量化大型矩阵乘法权重,并保持一些张量以更高精度(主要是令牌嵌入和输出矩阵,加上归一化权重),并且每128个量化权重组还携带一个小的FP16缩放和零点,因此权重为5.5 GB而不是4 GB。这不是即时的:它使用预校准的检查点(Qwen/Qwen3-8B-AWQ),通过Marlin INT4内核(OPTION_QUANTIZE=awq_marlin)服务,该内核在Ada GPU上足够快地反量化4位权重,使字节节省实际上转化为速度,而不是被反量化开销消耗。(推理工程,§5.1.1涵盖了这些数值格式。) 两者都在与FP16基线相同的4× L4机器(TP=4)上测量,因此唯一改变的是权重的精度。结果与字节数紧密相关: 按回车或点击查看全尺寸图片 权重量化延迟和吞吐量结果。图片由Gemini AI生成。 FP8将权重字节减半,并将中位延迟降低约三分之一(从4.88秒降至3.23秒),同时将解码吞吐量从约52提高到约80令牌/秒,大约是字节比预测的1.5倍。INT4相对于FP8再次将字节减半,并迈出了又一大步:real_medium P50降至2.21秒(比FP8低32%,比FP16基线低55%),约116令牌/秒。节省出现在每个桶上,并且在长输出real_decode桶上最大,其中解码主导请求,这正是带宽杠杆应该最有帮助的地方。 在您的收件箱中获取Srini Dwarakanathan的故事 免费加入Medium以获取此作者的最新动态。 订阅 订阅 记住我以便更快登录 有一个值得提及的反向趋势。FP8赢得了首令牌延迟,尽管INT4赢得了之后的一切:TTFT为FP8的66毫秒,而INT4为90毫秒。预填充受计算限制,而非带宽限制,AWQ反量化步骤(将存储的4位权重转换回矩阵乘法单元实际可以相乘的更高精度)为第一次并行传递增加了一点计算。FP8避免了这一点,因为Ada GPU具有原生FP8张量核心支持,因此8位权重直接馈送到矩阵乘法,无需转换;没有等效的原生4位矩阵乘法,因此INT4总是支付反量化成本。因此FP8开始打印的时间稍早,而INT4完成整个响应的时间更早。对于流式UI,首令牌是感觉到的时刻,这是一个真实但很小的考虑;对于总延迟,INT4是明显的赢家。 排名在负载下也成立。在16个并发请求时,吞吐量顺序为FP16的1.74、FP8的2.42和INT4的3.25请求/秒:相同的减半字节优势降低了单请求延迟,也允许更多序列共享每个带宽受限的解码步骤,因此INT4比FP8维持约三分之一的吞吐量,且尾部更紧。更小的权重同时帮助两个轴。这是本文中一个杠杆几乎免费的一个干净案例。 从引言中带有一个警告:这些只是延迟和吞吐量数字。FP8尤其是INT4改变了存储的权重,它们是否改变模型所说的内容是单独的测量(推理工程,§5.1.3),生产采用必须在信任加速之前运行。 推测解码:每次前向传递更多令牌 权重量化杠杆使每个解码步骤更便宜。推测解码攻击心智模型中的另一个术语:内存受限步骤的数量。如果解码缓慢是因为需要一次完整的权重读取前向传递来产生一个令牌,那么每次传递产生多个令牌是另一种加速方式。 诀窍是让廉价的东西猜测接下来的几个令牌,然后让真实模型检查它们。草稿提出,例如,四个令牌;8B目标运行一次前向传递,同时验证所有四个,并保留最长的正确前缀。当猜测良好时,一次昂贵的传递产生几个令牌而不是一个,有效解码率上升到权重带宽上限允许之上。当猜测不佳时,被拒绝的令牌被丢弃,你为无物支付了一点额外费用。因此整个杠杆的成败取决于接受率,即猜测正确的频率,这就是区分下面三种方法的原因(推理工程,§5.2)。 N-gram推测(无草稿)。最简单的方案根本没有草稿模型:它通过将最近的上下文与同一请求中已经看到的文本(即提示加上到目前为止生成的令牌)匹配来提出延续(提示查找),这很便宜,并且在输出重复输入或自身响应中的文本时效果很好,例如在摘要、代码编辑或提取中。在FP8 4× L4基线上,添加n-gram(OPTION_SPECULATIVE_CONFIG={"method":"ngram","num_speculative_tokens":5,...})使短和中桶大致持平,但在长输出real_decode桶上,它将P50从12.69秒降至约10.1秒(下降20%),并将有效解码率推至约115令牌/秒,高于FP8权重单独维持的约80,这是每次传递多个令牌的明显迹象。缺点是双重的。接受是双峰的,因此延迟方差扩大;并且在负载下会受损,因为一旦GPU繁忙,验证计算与连续批处理竞争,因此超过约两个并发请求后,延迟和吞吐量都低于纯FP8。N-gram是低QPS、重复输出的单流胜利,应在并发下关闭(推理工程,§5.2.4)。 单独的草稿模型,以及一个陷阱。更通用的方案使用一个小型真实模型作为起草者:Qwen3–0.6B提出,8B验证。由于真实模型可以提出任何延续,而不仅仅是提示中回显的文本,因此预计它会在n-gram持平的桶上有所帮助。相反,它在4× L4机器上产生了2.7倍的回归:real_medium P50为8.82秒,而FP8为3.23秒,解码吞吐量约为30令牌/秒,而约为80,每个桶都更差。原因不是推测解码本身,而是这个vLLM构建如何分片它:它强制草稿的张量并行度等于目标的,因此0.6B草稿在TP=4下运行。0.6B模型从跨四个GPU拆分中得不到任何好处,但现在它在每个推测步骤支付张量并行全归约,并且接受率不足以摊销这一点。修复方法是在TP=1下运行草稿,但在此构建上只有使目标TP=1(单个L4)才有可能,在那里相同的草稿模型配置翻转成巨大胜利(在同一机器上比FP8低33%到46%),确认回归完全是由于强制的草稿并行。完整的单GPU数字属于张量并行部分。这里的教训是,草稿模型的开销是真实的,如果服务堆栈分片不当,可能会淹没其好处。 训练好的草稿头(EAGLE3),获胜者。最好的结果来自EAGLE3:一个针对目标训练并融合到其中的小型草稿“头”,而不是附加的独立模型。EAGLE通过重用目标自身的内部状态工作:一个小的训练层采用目标已经计算的隐藏状态特征,并自回归地预测接下来的几个令牌,然后目标在单次传递中验证。由于该头是在目标自身的表示上训练的,而不是独立模型,其猜测更频繁地命中,EAGLE3通过从目标的多个层(而不仅仅是最后一层)提取特征进一步提高接受率(推理工程,§5.2.3)。由于它是融合的,它不受破坏独立草稿的草稿TP保护的影响,并且在相同的4× L4机器上以TP=4干净运行。堆叠在FP8上(SPEC={"method":"eagle3","model":"RedHatAI/Qwen3-8B-speculator.eagle3","num_speculative_tokens":3}),它是研究中迄今为止最快的单请求配置: 按回车或点击查看全尺寸图片 FP8加EAGLE3推测解码结果。图片由Gemini AI生成。 256输出桶的最小延迟降至约1.35秒,这是非常高接受率的标志:训练好的头提出的令牌被目标保留。它还在解码桶上击败了INT4权重(6.30秒对8.45秒,160对116令牌/秒),尽管INT4具有更小的权重,因为EAGLE3在完全精度速度的传递之上每次传递产生多个令牌。与n-gram和独立草稿不同,它在负载下优雅地退化:在16个并发请求时,它保持约4.55秒P50,2.77请求/秒,具有竞争力,而不是在并发2之后崩溃。 推测解码仍然让位的一个地方是负载下的原始吞吐量:INT4在并发16时维持3.25请求/秒,而EAGLE3为2.77,因为随着批处理填满GPU,每请求令牌节省逐渐减少。这指向明显的举措:EAGLE3是解码步骤计数杠杆,权重量化是每步字节杠杆,因此它们是正交的,应该组合。堆叠部分将回到这一点。 张量并行:拆分模型稀释了胜利 到目前为止,每个结果都生活在4× L4机器上,跨所有四个GPU张量并行服务。张量并行(TP)本身是心智模型预测的杠杆之一:将模型拆分到更多GPU上增加内存带宽,解码受带宽限制,因此更多GPU应该意味着更快的解码。本节保持精度固定,改变GPU数量,比较相同权重在单个L4(TP=1)与四个(TP=4)上的情况,以查看拆分实际价值(推理工程,§5.4.1)。 TP通过将每层的权重矩阵切成碎片,每个GPU一个。每个GPU持有四分之一的权重,每个解码步骤流式传输四分之一的字节,因此四个GPU为单个请求带来大约四倍的总带宽。代价是碎片必须重新组合:每层以全归约结束,这是跨GPU的通信步骤,TP=1从不支付。因此拆分增加了带宽,但也增加了固定的每步开销,该开销随GPU数量增长,并且不会随着权重变小而缩小。 保持精度固定,从单个L4到四个是大的延迟胜利,但不是带宽计数建议的干净4倍: 按回车或点击查看全尺寸图片 张量并行扩展,一个与四个GPU。图片由Gemini AI生成。 收益是真实的但次线性,部分被每层全归约消耗,部分因为单个L4在持续解码下带宽极度匮乏,其尾部变得脆弱(1× L4 FP8解码桶的P99为91秒,中位数为39秒,有几个请求严重停滞)。四个GPU既降低了中位数,也稳定了尾部。 更有趣的效果是在其他杠杆上。比较每个规模下INT4相对于FP8的胜利: 在1× L4上,INT4在P50上比FP8好42%,在令牌/秒上好74%。 在4× L4上,相同的交换仅值32%和47%。 量化在单个GPU上帮助更大。原因正是全归约:在单个L4上,解码纯粹受带宽限制,INT4的减半字节优势充分显示,但在四个GPU上,每个步骤还支付固定的通信成本,量化无法减少,因此移动更少权重字节的相对好处被稀释。张量并行和权重量化都针对带宽,它们部分重叠,因此堆叠它们不会简单地将百分比相加。 张量并行还决定了哪种推测解码方案甚至可行,这是前面推迟数字的回报。独立的0.6B草稿在4× L4上回归了2.7倍,因为这个vLLM构建强制草稿为TP=4,使其在每次推测步骤支付全归约,而模型太小无法从拆分中受益。将目标降至单个L4,以便草稿可以在TP=1下运行,相同的配置翻转成胜利:FP8与草稿在TP=1下real_medium P50为6.66秒,而单L4 FP8基线为9.89秒,改善33%。训练好的EAGLE3头在相同的单个GPU上表现更好,为5.62秒(比FP8低43%),因为它融合到目标中,在任何TP下都不会产生单独的草稿全归约。在单个L4上的排名从FP8的9.89秒,到草稿TP1的6.66秒,到EAGLE3的5.62秒,大致与INT4的5.70秒持平。这反映了4× L4排名,但只有在草稿摆脱张量并行惩罚之后。 最后,TP=1不仅仅是慢选项;它是不同轴上的不同点。单个L4是四分之一的GPU,INT4在该单卡上维持约45令牌/秒,接近FP16四GPU基线的约52,而硬件只有四分之一。TP=4是当单请求延迟重要时拉动的杠杆;TP=1与INT4是当每令牌成本重要时拉动的杠杆。它们之间的选择是延迟与美元,与贯穿本文其余部分的延迟与吞吐量权衡不同。 选择GPU:更快的内存是最干净的杠杆 到目前为止,每个杠杆都改变了软件:精度、解码方案、GPU数量。最后一个杠杆改变GPU本身,这是最直接的。解码受带宽限制,因此具有更多内存带宽的GPU加速解码,而无需触及权重、配置或模型所做的任何事情。除了下面的卡之外,部署没有任何改变(推理工程,§3.2)。 L40S与L4一样,是Ada一代(sm_89)GPU,因此相同的数值格式和内核不变运行,但它的内存带宽大约是两倍。为了隔离硬件效果,将迄今为止构建的最快配置(AWQ INT4权重加EAGLE3头,下一节涵盖的堆栈)从4× L4机器移动到4× L40S机器(ml.g6e.12xlarge),两者均为TP=4,其他不变: 按回车或点击查看全尺寸图片 冠军配置在L4与L40S上。图片由Gemini AI生成。 移动将real_medium P50降低了39%,解码桶降低了41%,吞吐量从207上升到361令牌/秒(增长74%)。这接近带宽比建议的约2倍,但不是全部:并非解码步骤的每个部分都是内存读取(全归约和算术不会变快),输入密集的real_long桶携带更多受计算限制的预填充,扩展较少(35%),而解码主导的桶扩展更多。杠杆在模型预测的地方帮助最大:工作负载越受解码限制,越接近完整的2倍。所有三个256输出桶降至一秒以下,TTFT降至64毫秒(研究中测量的最低值),负载下的吞吐量是任何配置中最好的。 与本文开头的FP8 4× L4起点(3.23秒,约80令牌/秒)相比,相同硬件的软件杠杆加上此硬件移动达到0.95秒,延迟降低71%,解码吞吐量约4.5倍。 两个实际警告保持诚实。首先,更快的内存不是免费的:L40S实例每小时成本高于L4,因此延迟胜利必须与更高的每小时费率权衡,这是这个仅延迟研究不做的成本比较,但生产决策必须做。其次,更快的卡更稀缺:g6e容量在尝试的第一个区域根本不可用,端点必须在其他地方启动。“我们实际能得到的硬件”,从引言中,是一个真正的约束:最快的GPU只有在你能分配它时才有帮助。 堆叠杠杆 杠杆一次呈现一个,以便每个可以隔离测量,但它们值得单独测量的原因是它们可以组合。回顾每个杠杆在解码步骤中实际针对什么: 权重量化减少每次前向传递读取的字节数。 推测解码减少每个产生的令牌的前向传递次数。 更快的硬件减少读取每个字节的时间。 这些是同一成本中的三个独立项。缩小一个不会消耗其他项,因此堆叠它们会相乘而不是简单相加,这就是为什么最快的配置是组合,而不是任何单个杠杆。 第一个堆栈在相同的4× L4机器上组合了两个最佳单流软件杠杆:AWQ INT4权重(最便宜的传递)与EAGLE3头(最少的传递)。推测解码与权重精度正交,因为EAGLE头只是针对更便宜的目标验证,因此它们可以组合在一起,结果是L4上最快的配置: INT4 + EAGLE3,4× L4:real_medium P50 1.57秒,解码5.37秒,约207令牌/秒,TTFT 95毫秒。 这比FP8上的EAGLE3低24%(INT4权重加速每个目标和验证传递),比INT4单独低29%(EAGLE3在每次传递上增加多个令牌)。关键是,它没有n-gram和独立草稿的负载惩罚:在16个并发请求时,它保持约3.24请求/秒,基本上是INT4自身的吞吐量,因此推测解码层购买单流胜利而没有吞吐量回归。它同时以正确的方式移动两个轴。 添加上一节的硬件杠杆是最后的乘法。完整的进展,每行只改变一件事: 从上面一行,讲述了文章的全部故事: 按回车或点击查看全尺寸图片 堆叠的杠杆,从基线到冠军的进展。图片由Gemini AI生成。 从FP16基线到冠军,延迟降低了81%(从4.88秒降至0.95秒),解码吞吐量大约提高了7倍(从约52到约361个令牌/秒),这是由四个独立的更改构建而成,每个更改都有贡献,且没有一个相互抵消。 结论 服务一个开放权重模型给你一个可控的栈,本文中的每个延迟杠杆都是这种控制解锁的:权重的精度、解码方案、GPU数量以及GPU本身。使它们可预测的单一思想是解码受内存带宽限制。一旦有了这个心智模型,每个杠杆只是移动更少字节、减少遍历次数或更快读取字节的不同方式,测量结果几乎每次都符合预测。 它们并非都作用于同一轴,知道哪个是实际技能。权重量化和更快的硬件降低了单请求延迟并提高了吞吐量,几乎是免费的胜利。投机解码是一个单流延迟杠杆,其吞吐量收益在负载下会减弱,在n-gram和独立草稿形式下,在并发下变得有害;只有融合的EAGLE3头既赢得了单流又保持了批处理。张量并行用GPU换取延迟,并与其他杠杆交互,稀释了量化的优势,并决定了哪些草稿方案可行。而KV缓存精度,如果在这里测量,将是一个内存杠杆而非延迟杠杆。一个杠杆只有在你知道了它移动哪个数字时才有用。 两个最后的警告。第一个是从一开始就搁置的:这些是延迟和吞吐量的产物,不是质量结果。量化和投机解码原则上可以改变模型的输出,在代表性集上(推理工程,§5.1.3)将答案与FP16基线进行比较之前,不应采用任何配置。第二个是最快的配置只与其硬件的可用性一样:容量,而不仅仅是延迟,决定了你实际能交付什么。但有了开放权重模型和带宽受限的心智模型,推理延迟不再是固定成本,而变成了一组旋钮。堆叠起来,这些旋钮将Qwen3–8B从4.88秒的基线响应降至不到一秒。 参考文献 Philip Kiely的《推理工程》 Chi Wang和Peiheng Wu的《动手实践LLM服务与优化》 《LLM推理手册2026》 ShareGPT数据集 我的其他文章 用于生产RAG的OpenSearch优化 用于生产RAG的OpenSearch优化,第2部分:词汇检索 代理推理部署:从散文技能到部署端点
查看原文(中文正文为 AI 翻译)
Artificial Intelligence Machine Learning Data Science Software Development Software Engineering Latency Optimization Levers for Open-Weight LLM Inference: Part-1 Srini Dwarakanathan 22 min read · Aug 31, 2026 -- Listen Share Index Introduction Why decode is the bottleneck The Metrics The Setup Quantization Speculative Decoding Tensor Parallelism Choosing the GPU Stacking the Levers Conclusion References My Other Articles Introduction Serving a large language model in a user-facing product is a latency problem before it is anything else. A model that answers correctly but takes ten seconds to do so is unusable in a chat box, a coding assistant, or a voice agent. And unlike a training run, inference latency is paid on every single request, forever. So once a model is good enough for the task, the engineering effort moves to a different question: how do we make it respond faster, on the hardware we can actually get, without changing what it says? That last clause matters. There are two axes worth tracking when serving an LLM, and being precise about which one a change actually moves is most of the point: Latency. How long a single request takes end to end. This is what a waiting user feels. Throughput. How many requests the same hardware can serve per second. This is what the bill reflects. Press enter or click to view image in full size SageMaker LLM latency levers. Image generated using Gemini AI. Every one of these levers is unlocked by serving an open-weight model. When you consume a model through a closed, hosted API, latency is whatever the provider gives you: you cannot change the numeric precision of the weights, attach a speculative draft head, split the model across GPUs of your choosing, or move it to faster hardware. With an open-weight model you own the entire serving stack, so each of these becomes a knob you can actually turn. That is the premise of this article: open weights are what make inference latency an engineering problem you can solve, rather than a number you are handed. The rest of this article walks through the levers that reduce LLM inference latency, the mechanism behind each one, how to turn it on, and what it actually bought when measured. The levers are weight quantization, speculative decoding, tensor parallelism, and hardware selection. Each is described in a general way, but the numbers come from a concrete setup: Qwen3–8B, an open-weight (Apache-2.0) model from Alibaba, served on AWS SageMaker, described in the setup section below. None of these techniques are specific to Qwen3–8B; they apply to any open-weight model, and the mechanisms and the direction of each result carry over unchanged to larger models. An 8B model is used here mainly for practical reasons: GPU capacity for the much larger instances that frontier open models like Kimi K2 or GLM-4.6 would require was hard to obtain on AWS, so a model that fits comfortably on available hardware makes the levers easy to isolate and measure. The absolute latencies would differ on a bigger model, but which lever moves which axis would not. Two scoping notes. First, model quality is out of scope for this document. Several of these levers, quantization especially, can in principle change what the model outputs, and a production adoption decision must measure that. Here we hold the question aside and treat each configuration purely as a latency artifact; measuring quality impact is its own exercise (see Inference Engineering, §5.1.3, for how one would do it). Second, this article assumes familiarity with the basics of transformer inference and GPUs. For a refresher on the underlying concepts, such as GPU architecture, number formats, and inference engines, Philip Kiely’s Inference Engineering (Baseten Books) is an excellent reference and is cited throughout by section. The Medium article LLM Inference Handbook 2026 is another good primer on these fundamentals, a shorter and freely accessible companion. Why decode is the bottleneck To reason about which lever helps, it helps to understand where the time actually goes when a model generates a response. An LLM answers a request in two distinct phases, and they have completely different performance characteristics. Prefill is the first phase. The model reads the entire prompt, every token of it, in a single forward pass, and produces the first output token. Because the whole prompt is available at once, this pass is highly parallel: the GPU has a large matrix of work to do and can keep its compute units busy. Prefill is compute-bound. Its cost scales with prompt length, and it determines the time to first token (TTFT). Decode is the second phase, and it is where responses are actually generated. The model produces one token at a time, and each token requires its own forward pass that depends on all the tokens before it. Generating a 256-token answer means 256 sequential forward passes. Each of those passes must read the model’s entire set of weights out of GPU memory to produce a single token’s worth of computation. This is the key asymmetry: the arithmetic done per pass is tiny, but the bytes moved are enormous, namely the whole weight matrix plus the growing KV cache. Decode is therefore memory-bandwidth-bound, not compute-bound. The GPU spends most of each step waiting on memory, not computing. The formal version of this is the ops:byte ratio (or arithmetic intensity): a GPU can do some number of floating-point operations per byte it reads from memory, and if a kernel does fewer operations per byte than that ratio, it is limited by memory bandwidth rather than compute (Inference Engineering, §2.4). Single-stream decode sits far below the ratio, so it is squarely memory-bound. This single fact, that decode is memory-bandwidth-bound, is the mental model the rest of the article hangs on. It predicts, before running anything, which levers should work: Anything that moves fewer bytes per token (smaller weights) should speed up decode directly. Anything that produces more tokens per forward pass (speculative decoding) should speed up decode, because the bottleneck is the number of memory-bound passes, not the compute in each one. Anything that adds memory bandwidth (a higher-bandwidth GPU, or splitting the model across more GPUs) should speed up decode. Anything that only reduces compute should barely move decode latency at all, because compute is not the constraint. The measurements bear this out. On the baseline used in this work, Qwen3–8B in FP16 on four NVIDIA L4 GPUs, growing the prompt from 72 to 1,608 tokens added only about 0.35 seconds (prefill is cheap and compute-bound), while growing the output from 256 to 1,024 tokens scaled latency almost linearly, roughly 4x. Output length, not input length, drives latency, exactly as the decode-bound model predicts. The Metrics Because latency is not a single number, a few terms are used throughout (Inference Engineering, §1.4): Press enter or click to view image in full size LLM inference latency and throughput metrics. Image generated using Gemini AI. Every configuration in this article is reported against the same set of these metrics, measured the same way, so the levers can be compared directly. The setup: Qwen3–8B on SageMaker The model. Every configuration serves Qwen3–8B, an 8-billion-parameter open-weight model released by Alibaba under the Apache-2.0 license. Because the weights are open, the same model can be loaded in different numeric precisions (FP16, FP8, AWQ INT4), paired with a speculative draft head, and moved between GPUs without any change to what it is, which is exactly what lets the levers below be measured against a common reference. The FP16 baseline uses the SageMaker JumpStart artifact; the INT4 passes use the pre-quantized Qwen/Qwen3-8B-AWQ checkpoint; the speculative-decoding passes attach the trained RedHatAI/Qwen3-8B-speculator.eagle3 EAGLE head. The verifier weights are the same 8B model in all three. The hardware. Three SageMaker instance types are used, all Ada-generation (sm_89) NVIDIA GPUs so the number formats and kernels are comparable: Press enter or click to view image in full size SageMaker GPU instances used for benchmarks. Image generated using Gemini AI. The serving engine. The model is served with vLLM, through SageMaker’s DJL-LMI container. vLLM is a widely used open-source inference engine for serving LLMs on GPUs, designed for high throughput and supporting the optimizations this article relies on, including quantization and speculative decoding; SageMaker’s DJL-LMI container packages it behind a managed endpoint (Inference Engineering, §4.3.1). The inference engine is held fixed across every configuration so that it is never a confounding variable. The only things that change between passes are the levers under test. vLLM uses continuous batching by default, and it is worth being precise about what that does, because it moves both of the axes from the introduction. Static batching waits for a fixed-size batch to fill before it runs inference, which leaves the earliest requests sitting in a queue. Continuous batching (also called in-flight, or token-level, batching) instead operates one decode step at a time. It swaps a new request into the running batch as soon as a slot frees up, so a request begins on the next step instead of waiting for a batch to be assembled. Cutting that queue time means continuous batching lowers latency and raises throughput relative to static or dynamic batching; it is a strict improvement over them, not a tradeoff (Inference Engineering, §7.2.1). The tradeoff lives one level down, in batch size. As concurrency rises, more sequences ride along in each decode step. Because that step is memory-bandwidth-bound and must read the full weight matrix regardless of how many sequences share it, packing more of them in raises aggregate throughput. But they now contend for the same bandwidth, so each individual request’s P50 and tail latency grow. This is the latency-versus-throughput tension from the introduction, made concrete: “increasing the batch size will produce more throughput overall, but each user’s latency will get worse” (Inference Engineering, §7.2.1). It is why every configuration below is reported twice, once as single-request latency at concurrency 1 and once as a concurrency sweep, so the single-stream effect of each lever is never conflated with this batching effect. The workload. The query set is 180 real, filtered ShareGPT prompts: self-contained tasks that force the model to read the input and generate a response. Prompts are grouped into buckets by input length, with output length fixed per bucket so that prefill cost and decode cost can be read separately: Press enter or click to view image in full size Benchmark workload buckets by token length. Image generated using Gemini AI. How each pass is measured. Every configuration is deployed to its own SageMaker endpoint, benchmarked with a fixed harness, and torn down. Single-request numbers are taken at concurrency 1; the concurrency sweep drives the real_medium bucket at 1, 2, 4, 8, and 16 concurrent requests. All latencies are end-to-end request time in seconds unless noted, and TM95 is the mean after dropping the slowest 5% of samples. Reported deltas between passes only change one thing at a time, whether precision, draft head, GPU count, or instance type, so each measured difference can be attributed to the single lever it isolates. Quantization: Smaller weights move fewer bytes The first lever follows straight from the mental model. Decode reads the entire weight matrix out of GPU memory once per token, so the number of bytes in that matrix sets a hard floor on how fast a token can be produced. Shrink the weights and every decode step moves fewer bytes, so on a bandwidth-bound path it finishes sooner. That is the whole mechanism, and it is why quantizing the weights is the most direct latency lever available. Qwen3–8B has roughly 8 billion parameters. Stored in FP16 that is about 16 GB of weights that decode must stream every token. Two quantization formats reduce that: FP8 stores each weight in 8 bits instead of 16, about 8 GB, half the bytes. vLLM can do this on the fly, so no separate checkpoint is needed; it is a single serving flag (OPTION_QUANTIZE=fp8). AWQ INT4 stores each weight in 4 bits, roughly 5.5 GB once the group scales AWQ keeps are counted, still about a third of FP16. AWQ only quantizes the large matmul weights and keeps some tensors at higher precision (chiefly the token-embedding and output matrices, plus the normalization weights), and every group of 128 quantized weights also carries a small FP16 scale and zero-point and hence the wieghts are 5.5 GB and not 4 GB. This one is not on the fly: it uses a pre-calibrated checkpoint (Qwen/Qwen3-8B-AWQ) served with the Marlin INT4 kernel (OPTION_QUANTIZE=awq_marlin), which dequantizes the 4-bit weights fast enough on Ada GPUs that the byte savings actually convert to speed rather than being eaten by dequant overhead. (Inference Engineering, §5.1.1, covers these number formats.) Both are measured on the same 4× L4 box (TP=4) as the FP16 baseline, so the only thing changing is the precision of the weights. The results track the byte counts closely: Press enter or click to view image in full size Weight quantization latency and throughput results. Image generated using Gemini AI. FP8 halves the weight bytes and cuts median latency by about a third (from 4.88 to 3.23 s) while lifting decode throughput from about 52 to about 80 tokens/sec, roughly the 1.5x the byte ratio predicts. INT4 halves the bytes again relative to FP8 and takes another large step: real_medium P50 falls to 2.21 s (32% below FP8, 55% below the FP16 baseline) at about 116 tokens/sec. The saving shows up on every bucket, and it is largest on the long-output real_decode bucket where decode dominates the request, exactly where a bandwidth lever should help most. Get Srini Dwarakanathan’s stories in your inbox Join Medium for free to get updates from this writer. Subscribe Subscribe Remember me for faster sign in There is one counter-current worth naming. FP8 wins first-token latency, even though INT4 wins everything after it: TTFT is 66 ms for FP8 versus 90 ms for INT4. Prefill is compute-bound, not bandwidth-bound, and the AWQ dequant step (converting the stored 4-bit weights back to a higher precision the matmul units can actually multiply in) adds a little compute to that first parallel pass. FP8 avoids this because Ada GPUs have native FP8 tensor-core support, so the 8-bit weights feed the matmul directly with no conversion; there is no equivalent native 4-bit matmul, so INT4 always pays the dequant. So FP8 starts printing marginally sooner, while INT4 finishes the whole response sooner. For a streaming UI where the first token is the felt moment this is a real, if small, consideration; for total latency INT4 is the clear winner. The ranking also holds under load. At 16 concurrent requests the throughput ordering is FP16 at 1.74, FP8 at 2.42, and INT4 at 3.25 requests/sec: the same half-the-bytes advantage that lowers single-request latency also lets more sequences share each bandwidth-bound decode step, so INT4 sustains about a third more throughput than FP8 with a tighter tail. Smaller weights help both axes at once. This is the one clean case in this article where a lever is nearly free. One caveat carried from the introduction: these are latency and throughput numbers only. FP8 and especially INT4 change the stored weights, and whether they change what the model says is a separate measurement (Inference Engineering, §5.1.3) that a production adoption must run before trusting the speedup. Speculative Decoding: More tokens per forward pass The weight-quantization lever makes each decode step cheaper. Speculative decoding attacks the other term in the mental model: the number of memory-bound steps. If decode is slow because it takes one full weight-reading forward pass to produce one token, then producing several tokens per pass is the other way to go faster. The trick is to let something cheap guess the next few tokens, and then have the real model check them. A draft proposes, say, four tokens; the 8B target runs a single forward pass that verifies all four at once and keeps the longest correct prefix. When the guesses are good, one expensive target pass yields several tokens instead of one, and the effective decode rate climbs above what the weight-bandwidth ceiling would otherwise allow. When the guesses are bad, the rejected tokens are thrown away and you have paid a little extra for nothing. So the whole lever lives or dies on acceptance rate, how often the guesses are right, and that is what separates the three approaches below (Inference Engineering, §5.2). N-gram speculation (draft-free). The simplest scheme has no draft model at all: it proposes continuations by matching the recent context against text already seen so far in the same request, meaning the prompt plus the tokens generated up to this point (prompt-lookup), which is cheap and works well when the output repeats text from the input or from earlier in its own response, as in summarization, code edits, or extraction. On the FP8 4× L4 baseline, adding n-gram (OPTION_SPECULATIVE_CONFIG={"method":"ngram","num_speculative_tokens":5,...}) leaves the short and medium buckets roughly flat, but on the long-output real_decode bucket it cuts P50 from 12.69 to about 10.1 s (a 20% drop) and pushes the effective decode rate to about 115 tokens/sec, above the roughly 80 the FP8 weights alone can sustain, which is the tell-tale sign that multiple tokens are landing per pass. The catch is twofold. Acceptance is bimodal, so latency variance widens; and it hurts under load, because the verification compute competes with continuous batching once the GPU is busy, so past about two concurrent requests both latency and throughput fall below plain FP8. N-gram is a low-QPS, repetitive-output single-stream win, to be turned off under concurrency (Inference Engineering, §5.2.4). A separate draft model, and a trap. The more general scheme uses a small real model as the drafter: Qwen3–0.6B proposes, the 8B verifies. Because a real model can propose any continuation, not just text echoed from the prompt, it was expected to help the buckets where n-gram was flat. Instead it produced a 2.7× regression on the 4× L4 box: real_medium P50 of 8.82 s versus FP8’s 3.23, and decode throughput of about 30 tokens/sec versus about 80, worse on every bucket. The cause is not speculative decoding itself but how this vLLM build shards it: it forces the draft’s tensor-parallel degree to equal the target’s, so the 0.6B draft was run at TP=4. A 0.6B model gains nothing from being split across four GPUs, but it now pays a tensor-parallel all-reduce on every speculative step, and acceptance is not high enough to amortize that. The fix, running the draft at TP=1, is only possible on this build by making the target TP=1 too (a single L4), and there the same draft-model configuration flips to a large win (33% to 46% below FP8 on the same box), confirming that the regression was entirely the forced draft parallelism. The full single-GPU numbers belong to the tensor-parallelism section. The lesson here is that a draft model’s overhead is real and can swamp its benefit if the serving stack shards it badly. A trained draft head (EAGLE3), the one that wins. The best result comes from EAGLE3: a small draft “head” trained against the target and fused into it, rather than a separate model bolted on. EAGLE works by reusing the target’s own internal state: a small trained layer takes the hidden-state features the target already computes and predicts the next few tokens from them autoregressively, which the target then verifies in a single pass. Because that head is trained on the target’s own representations rather than being an independent model, its guesses land far more often, and EAGLE3 raises acceptance further by drawing on features from several layers of the target rather than just the last (Inference Engineering, §5.2.3). Because it is fused, it is not subject to the draft-TP guard that wrecked the standalone draft, and it runs cleanly at TP=4 on the same 4× L4 box. Stacked on FP8 (SPEC={"method":"eagle3","model":"RedHatAI/Qwen3-8B-speculator.eagle3","num_speculative_tokens":3}), it is the fastest single-request configuration in the study up to this point: Press enter or click to view image in full size FP8 plus EAGLE3 speculative decoding results. Image generated using Gemini AI. The min latency on the 256-output buckets drops to about 1.35 s, the signature of very high acceptance: the trained head proposes tokens the target keeps. It also beats INT4 weights on the decode bucket (6.30 vs 8.45 s, 160 vs 116 tok/s) despite INT4 having the smaller weights, because EAGLE3 is producing multiple tokens per pass on top of a full-precision-speed pass. And unlike n-gram and the standalone draft, it degrades gracefully under load: at 16 concurrent requests it holds about 4.55 s P50 at 2.77 requests/sec, competitive rather than collapsing past concurrency 2. The one place spec decode still cedes ground is raw throughput under load: INT4 sustains 3.25 requests/sec at concurrency 16 versus EAGLE3’s 2.77, because the per-request token savings erode as batching fills the GPU. That points at the obvious move: EAGLE3 is a decode-step-count lever and weight quantization is a bytes-per-step lever, so they are orthogonal and should compose. The stacking section returns to exactly that. Tensor Parallelism: Splitting the model dilutes the win Every result so far has lived on the 4× L4 box, served tensor-parallel across all four GPUs. Tensor parallelism (TP) is itself one of the levers the mental model predicts: splitting the model across more GPUs adds memory bandwidth, and decode is bandwidth-bound, so more GPUs should mean faster decode. This section holds the precision fixed and changes the GPU count instead, comparing the same weights on one L4 (TP=1) against four (TP=4), to see what the split is actually worth (Inference Engineering, §5.4.1). TP works by cutting each layer’s weight matrices into shards, one per GPU. Each GPU holds a quarter of the weights and streams a quarter of the bytes per decode step, so four of them bring roughly four times the aggregate bandwidth to bear on a single request. The cost is that the shards have to be recombined: every layer ends with an all-reduce, a communication step across the GPUs that TP=1 never pays. So the split adds bandwidth but also adds a fixed per-step overhead that grows with GPU count and does not shrink when the weights get smaller. Holding precision fixed, going from one L4 to four is a large latency win, just not the clean 4× the bandwidth count suggests: Press enter or click to view image in full size Tensor parallelism scaling, one vs four GPUs. Image generated using Gemini AI. The gain is real but sub-linear, eaten partly by the per-layer all-reduce and partly by the fact that a single L4 under sustained decode is so bandwidth-starved that its tail becomes fragile (the 1× L4 FP8 decode bucket had a P99 of 91 s against a 39 s median, with a couple of requests stalling badly). Four GPUs both lower the median and stabilize the tail. The more interesting effect is on the other levers. Compare the INT4-over-FP8 win at each scale: On 1× L4, INT4 beats FP8 by 42% on P50 and 74% on tokens/sec. On 4× L4, the same swap is worth only 32% and 47%. Quantization helps more on a single GPU. The reason is exactly the all-reduce: on one L4 decode is purely bandwidth-bound and INT4’s half-the-bytes advantage shows in full, but on four GPUs each step also pays a fixed communication cost that quantization cannot reduce, so the relative benefit of moving fewer weight bytes is diluted. Tensor parallelism and weight quantization both target bandwidth, and they partly overlap, so stacking them does not simply add their percentages. Tensor parallelism also decides which speculative-decoding scheme is even viable, which is the payoff for the numbers deferred earlier. The standalone 0.6B draft regressed 2.7× on 4× L4 because this vLLM build forced the draft to TP=4, making it pay an all-reduce on every speculative step for a model far too small to benefit from the split. Drop the target to a single L4 so the draft can run at TP=1, and the same configuration flips to a win: FP8 with the draft at TP=1 comes in at real_medium P50 6.66 s versus the single-L4 FP8 baseline’s 9.89, a 33% improvement. A trained EAGLE3 head does better still on the same single GPU at 5.62 s (43% below FP8), because it is fused into the target and never incurs a separate draft all-reduce at any TP. The ranking on one L4 runs from FP8 at 9.89 s, to draft-TP1 at 6.66 s, to EAGLE3 at 5.62 s, roughly tied with INT4 at 5.70 s. That mirrors the 4× L4 ranking, but only once the draft is freed from the tensor-parallel penalty. Finally, TP=1 is not merely the slow option; it is a different point on a different axis. A single L4 is one quarter of the GPUs, and INT4 on that one card sustains about 45 tokens/sec, close to the FP16 four-GPU baseline’s roughly 52 on a quarter of the hardware. TP=4 is the lever you pull when single-request latency is what matters; TP=1 with INT4 is the lever you pull when cost per token is. The choice between them is latency versus dollars, a distinct trade from the latency-versus-throughput one that runs through the rest of this article. Choosing the GPU: Faster memory is the cleanest lever Every lever so far changed the software: the precision, the decoding scheme, the number of GPUs. The last lever changes the GPU itself, and it is the most direct of all. Decode is bandwidth-bound, so a GPU with more memory bandwidth speeds up decode without touching the weights, the config, or anything the model does. Nothing about the deployment changes except the card underneath it (Inference Engineering, §3.2). The L40S is, like the L4, an Ada-generation (sm_89) GPU, so the same number formats and kernels run unchanged, but it has roughly twice the memory bandwidth. To isolate the hardware effect, the fastest configuration built so far (AWQ INT4 weights plus an EAGLE3 head, the stack the next section covers) is moved from the 4× L4 box to a 4× L40S box (ml.g6e.12xlarge), TP=4 on both, with nothing else changed: Press enter or click to view image in full size Champion config on L4 versus L40S. Image generated using Gemini AI. The move cuts real_medium P50 by 39% and the decode bucket by 41%, where throughput climbs from 207 to 361 tokens/sec (a 74% gain). That is most of the way to the roughly 2× the bandwidth ratio would suggest, but not all of it: not every part of a decode step is a memory read (the all-reduce and the arithmetic do not get faster), and the input-heavy real_long bucket, which carries more compute-bound prefill, scales less (35%) than the decode-dominated buckets. The lever helps exactly where the model says it should: the more decode-bound the workload, the closer to the full 2× it gets. All three 256-output buckets drop below one second, TTFT falls to 64 ms (the lowest measured anywhere in the study), and throughput under load is the best of any configuration. Measured against the FP8 4× L4 starting point this article opened from (3.23 s, about 80 tok/s), the same-hardware software levers plus this hardware move land at 0.95 s, a 71% latency reduction with roughly 4.5× the decode throughput. Two practical caveats keep this honest. First, faster memory is not free: L40S instances cost more per hour than L4, so the latency win has to be weighed against the higher hourly rate, a cost comparison this latency-only study does not make but a production decision must. Second, the faster cards are scarcer: the g6e capacity simply was not available in the first region tried, and the endpoint had to be brought up elsewhere. “The hardware we can actually get,” from the introduction, is a real constraint: the fastest GPU only helps if you can allocate it. Stacking the levers The levers have been presented one at a time so that each could be measured in isolation, but the reason they were worth measuring separately is that they compose. Look back at what each one actually targets in the decode step: Weight quantization reduces the bytes read per forward pass. Speculative decoding reduces the number of forward passes per token produced. Faster hardware reduces the time to read each byte. These are three independent terms in the same cost. Shrinking one does not use up the others, so stacking them multiplies rather than merely adds, which is why the fastest configurations are combinations, not any single lever. The first stack combines the two best single-stream software levers on the same 4× L4 box: AWQ INT4 weights (cheapest passes) with an EAGLE3 head (fewest passes). Spec decode is orthogonal to weight precision, since the EAGLE head simply verifies against a cheaper target, so they slot together, and the result is the fastest configuration on L4: INT4 + EAGLE3, 4× L4: real_medium P50 1.57 s, decode 5.37 s at about 207 tok/s, TTFT 95 ms. That is 24% below EAGLE3 on FP8 (the INT4 weights speed up every target and verify pass) and 29% below INT4 alone (EAGLE3 adds multiple tokens per pass on top). Crucially, it does this without the load penalty that sank n-gram and the standalone draft: at 16 concurrent requests it holds about 3.24 requests/sec, essentially INT4’s own throughput, so the spec-decode layer buys the single-stream win with no throughput regression. It moves both axes the right way at once. Adding the hardware lever from the previous section is the final multiplication. The complete progression, each row changing exactly one thing from the row above, tells the whole story of the article: Press enter or click to view image in full size Stacked levers, baseline to champion progression. Image generated using Gemini AI. From the FP16 baseline to the champion, that is an 81% latency reduction (4.88 s down to 0.95 s) and roughly 7× the decode throughput (about 52 to about 361 tokens/sec), built from four independent changes that each contributed and none of which cancelled the others. Conclusion Serving an open-weight model gives you a stack you control, and every latency lever in this article is something that control unlocks: the precision of the weights, the decoding scheme, the number of GPUs, and the GPU itself. The single idea that made them predictable is that decode is memory-bandwidth-bound. Once that is the mental model, each lever is just a different way of moving fewer bytes, taking fewer passes, or reading bytes faster, and the measurements followed the prediction almost every time. They did not all move the same axis, and knowing which is the actual skill. Weight quantization and faster hardware lowered single-request latency and raised throughput, nearly free wins. Speculative decoding was a single-stream latency lever whose throughput benefit eroded under load, and in the n-gram and standalone-draft forms it turned actively harmful under concurrency; only a fused EAGLE3 head both won single-stream and held up batched. Tensor parallelism traded GPUs for latency and interacted with the other levers, diluting quantization’s edge and dictating which draft schemes were even viable. And KV-cache precision, had it been measured here, would have been a memory lever rather than a latency one. A lever is only useful once you know which number it moves. Two closing cautions. The first is the one held aside from the start: these are latency and throughput artifacts, not quality results. Quantization and speculative decoding can in principle change what the model outputs, and no configuration here should be adopted before its answers are measured against the FP16 baseline on a representative set (Inference Engineering, §5.1.3). The second is that the fastest configuration is only as available as its hardware: capacity, not just latency, decides what you can actually ship. But with an open-weight model and a bandwidth-bound mental model, inference latency stops being a fixed cost and becomes a set of knobs. Stacked, those knobs took Qwen3–8B from a 4.88-second baseline response to under a second. References Inference Engineering by Philip Kiely Hands-On LLM Serving and Optimization by Chi Wang and Peiheng Wu LLM Inference Handbook 2026 ShareGPT Datasets My Other Articles OpenSearch Optimizations for Production RAG OpenSearch Optimizations for Production RAG, Part 2: Lexical Retrieval Agentic Inference Deployment: From Prose Skills to Deployed Endpoints

来源报道 · 1 篇 · 以下链接均前往原始媒体

Srini Dwarakanathan 开源权重LLM推理的延迟优化杠杆(第一部分) 09-07 · 原文发布
← 返回精选动态 原文

更多内容