量化SEO案例深度评测:排名与流量提升策略
如何衡量推理性能
评估LLM推理速度时,需从四个核心指标切入,它们共同决定模型服务的真实表现。
第一个是首个Token响应时间(TTFT),即用户提交查询后,到第一个输出字符出现所耗的时长。实时交互场景下这个指标至关重要——响应必须足够快;离线任务中其优先级则相对较低。TTFT主要由模型处理输入提示及生成第一个token所耗费的时间决定。
第二个是每个输出Token的时间(TPOT),指系统生成单个输出token所需的时长。它直接映射用户感知的“生成速度”。举例来说,若TPOT为100毫秒/token,则每秒可生成10个token,相当于每分钟约450个词——这已超过一般人的阅读速度。
第三个是延迟,即模型完整生成一次响应所消耗的总时间。延迟可通过前两个指标计算:延迟 = TTFT + (TPOT × 需生成的token数量)。
第四个是吞吐量,衡量推理服务器每秒能为所有用户和请求生成多少个输出token。该指标决定了系统的整体服务容量。
这些指标帮助我们评估并优化模型处理请求时的效率。理想状态是:最快的首个token响应、最高的吞吐量、以及最快的每个输出token时间——简言之,希望模型在服务尽可能多用户的同时,仍能快速生成文本。
但这里存在一个值得关注的权衡:吞吐量与每个输出token的时间彼此矛盾。若同时处理16个用户的查询,吞吐量会远高于串行执行,但每个用户感受到的生成速度会变慢。取舍取决于你的业务场景。
从总体推理延迟目标出发,以下几点经验值得采纳:
- 输出长度主导总体响应延迟:估算平均延迟时,通常可用预期或最大输出token长度乘以模型整体的平均每个输出token时间。
- 输入长度对性能影响有限,但对硬件要求至关重要:以MPT模型为例,增加512个输入token带来的延迟增长,远低于生成8个额外输出token的代价。但支持长输入会显著提升模型服务的难度。例如,我们推荐使用A100-80GB(或更新型号)来服务最大上下文长度为2048 token的MPT-7B。
- 总体延迟与模型大小呈次线性关系:在相同硬件上,更大的模型运行更慢,但速度差异并不按参数量比例放大。实测数据显示,MPT-30B的延迟约为MPT-7B的2.5倍,Llama2-70B的延迟约为Llama2-13B的2倍。
经常有客户询问平均推理延迟是多少。我们的建议是,在确定具体延迟目标(例如“每个token必须低于20毫秒”)之前,务必先花时间明确预期的输入长度和期望的输出长度。
LLM推理的挑战
优化LLM推理时可借助一些通用技术:
- 算子融合(Operator Fusion):将相邻算子合并,通常能减少中间变量和内存操作,从而降低延迟。
- 量化:用更少的比特数压缩激活值和权重值。
- 压缩:如稀疏化或知识蒸馏。
- 并行化(Parallelization):对于大模型,可在多个设备上实施张量并行或流水线并行。
除此之外,Transformer还有独特优化点,KV缓存便是典型例子。仅解码器的Transformer中,注意力机制计算效率不高。每个token都会关注之前见过的所有token,因此每生成一个新token,就需重复计算大量相同的值。例如生成第N个token时,第(N-1)个token会关注第(N-2)个、第(N-3)个……直到第1个token。待生成第(N+1)个token时,又需重走一遍流程。KV缓存的做法就是将这些中间键/值保存下来,后续直接复用,避免重复计算。
内存带宽是关键
LLM中的计算主要由矩阵乘法操作主导,而小尺寸操作在大多数硬件上的瓶颈往往是内存带宽。在自回归生成token时,激活矩阵的一个维度(由批量大小和序列中的token数量决定)在小批量条件下很小。这意味着,速度取决于我们能多快从GPU内存将模型参数加载到本地缓存/寄存器,而非在加载数据上能计算得多快。因此,推理硬件中可用及实际达到的内存带宽,比峰值计算性能更能预测token的生成速度。
推理硬件的利用率直接关联服务成本。GPU昂贵,必须尽可能避免闲置。共享推理服务通过合并多个用户的工作负载,填补单个请求的空隙,批量处理重叠的请求,从而降低成本。对于Llama2-70B这类大模型,只有在大批量时才能实现较好的成本/性能比。这就要求推理服务系统能支撑大批量运行。但大批量意味着更大的KV缓存,进而增加服务模型所需的GPU数量。这里存在一个拉锯战,共享服务运营商需进行成本权衡并实施系统优化。
模型带宽利用率(MBU)
那么,LLM推理服务究竟如何优化?
前面提到,尤其在解码阶段,小批量LLM推理受限于模型参数从设备内存加载到计算单元的速度。内存带宽决定了数据移动的速度。为衡量底层硬件的实际利用效率,我们引入一个新指标——模型带宽利用率(Model Bandwidth Utilization,MBU)。
MBU的定义:实际内存带宽 / 峰值内存带宽。其中实际内存带宽 = (总模型参数大小 + KV缓存大小) / TPOT。
举例:一个7B参数模型以16位精度运行,TPOT为14ms,那它在14ms内需移动14GB的参数,相当于1TB/s的带宽使用。若机器峰值带宽为2TB/s,则MBU为50%。为简化,本例忽略了KV缓存大小——它在小批量、短序列时影响不大。MBU接近100%,说明推理系统高效利用了可用内存带宽。另外,MBU还能帮我们在标准化框架下比较不同的推理系统(硬件+软件)。MBU是对模型Flops利用率(MFU)的补充,后者在计算受限场景中更为重要。
图1在类似roofline的图表中展示了MBU的含义。橙色阴影区域的实线表示若内存带宽完全饱和(100%),可能达到的最大吞吐量。但实际中,小批量(白点)时的性能会低于这个上限——低多少,就是MBU的衡量标准。在大批量(黄色区域)时,系统转为计算受限,实际吞吐量作为峰值可能吞吐量的一部分来测量,这就是模型Flops利用率(MFU)。
MBU和MFU共同决定了在给定硬件设置下,推理速度还有多大的提升空间。图2显示了我们基于TensorRT-LLM的推理服务在不同张量并行度下测得的MBU表现。当传输大块连续内存时,可以达到峰值内存带宽利用率。像MPT-7B这样较小的模型分布在多个GPU上时,MBU会偏低,因为每个GPU上移动的内存块变小了。
图3展示了在NVIDIA H100 GPU上,不同张量并行度和Tensor大小下的MBU实测数据。随着批量增大,MBU会下降。但GPU扩展得越多,这种下降的相对幅度就越不明显。还有一点值得注意:选择内存带宽更大的硬件,可以用更少的GPU来提升性能。以批量大小为1时为例,2块H100-80GB上可跑出高达60%的MBU,而4块A100-40GB上只有55%(见图2)。
基准测试结果
延迟
我们测试了MPT-7B和Llama2-70B在不同Tensor并行度下的首个token响应时间(TTFT)和每个输出token时间(TPOT)。随着输入提示不断增长,生成第一个token所需的时间在总延迟中占比越来越大。在多个GPU之间做张量并行,有助于减少这部分延迟。
不过,与模型训练不同,增加更多GPU对推理延迟的改善存在明显的边际递减效应。例如Llama2-70B,从小批量时4块GPU增加到8块,延迟仅降低了0.7倍。原因有二:一是更高的并行度会拉低MBU(前面已讨论),二是张量并行会引入GPU节点间的通信开销。
在更大的批量下,更高的Tensor并行度反而能带来更显著的延迟降低。图4展示了MPT-7B每个输出token时间的变化情况。批量大小为1时,从2块GPU增加到4块仅降低了约12%的延迟;但在批量大小为16时,4块GPU的延迟比2块低了33%。这与之前的观察一致:批量16时,更高Tensor并行度下的MBU相对减少较小。
图5是Llama2-70B的类似结果,不过从4块到8块的相对改进没那么明显。我们还比较了两种不同硬件上的GPU扩展效果。H100-80GB的内存带宽是A100-40GB的2.15倍,可以看到,在批量大小为1时,4块GPU的延迟降低了36%,批量16时降低了52%。
吞吐量
通过批处理请求,我们可以在吞吐量和每个token的时间之间做权衡。在GPU评估期间把查询分组,相比顺序处理,能提高吞吐量,但每个查询的完成时间会更长(忽略排队效应)。
批处理推理请求主要有几种常见技术:
- 静态批处理(Static batching):客户端把多个Prompt打包进一个请求,等批次中所有序列都完成后再返回响应。我们的推理服务支持这种方式,但不强制要求。
- 动态批处理(Dynamic batching):请求在服务器内部即时批量处理。通常表现不如静态批处理,但如果请求响应短或长度一致,可以接近最优。当请求参数不同时,效果就不太理想了。
- 连续批处理(Continuous batching):请求到达时一起批量处理,这个概念出自那篇优秀的论文ORCA,是目前最先进的方法。它不是等批次中所有序列完成,而是在迭代级别就把序列组合到一起,吞吐量可以比动态批处理高出10到20倍。
图6:三种LLM服务的批处理方式。批处理是提高推理效率的有效手段。
通常来说,连续批处理是共享服务的最佳选择,但某些场景下其他方法可能更合适。比如在低QPS环境中,动态批处理可能优于连续批处理。在一些简单的批处理框架里,实现底层GPU优化反而更容易。对于离线批量推理任务,静态批处理可以避免额外开销,实现更高的吞吐量。
批量大小
批处理的效果高度依赖于请求的流量模式。不过,我们可以通过用统一请求做静态批处理基准测试,来摸清它的性能上限。
延迟权衡
请求延迟会随批量大小增加而增长。例如,在一张NVIDIA A100 GPU上,如果我们将批量设为64来最大化吞吐量,延迟会增加4倍,但吞吐量会增加14倍。共享推理服务通常会选择一个平衡点。自己拥有模型的用户,应该根据应用需求来决定延迟/吞吐量的取舍。有些应用,比如聊天机器人,低延迟快速响应的优先级最高。而另一些场景,比如批量处理非结构化的PDF文件,我们可能愿意牺牲单个文档的处理速度,来换取整个任务的并行高效。
图7展示了7B模型的吞吐量-延迟曲线。曲线上每条线,都是通过从1到256逐步增加批量大小得到的。这能帮助判断:在满足不同延迟限制的前提下,批量可以增大到什么程度。回想一下前面的roofline图,你会发现实际测量结果与理论预期是一致的。当批量增大到一定程度,进入计算受限区域后,每次翻倍批量只会增加延迟,而不会再贡献吞吐量提升。
在使用并行处理时,了解底层硬件细节非常重要。并非所有云平台上的8x A100实例都相同。有些服务器在所有GPU之间拥有高带宽连接,而另一些则把GPU成对连接,成对之间的带宽较低。这可能会引入瓶颈,导致实际性能与上述曲线出现显著偏离。
优化案例研究:量化
量化是减少LLM推理硬件需求的一种常用手段。在推理过程中降低模型权重和激活值的精度,能显著减少硬件资源需求。比如,从16位权重切换到8位权重,在内存受限的环境中(例如在A100上运行Llama2-70B)可以省掉一半的GPU。降到4位权重,则能让推理在消费级硬件上跑起来(比如在Macbook上跑Llama2-70B)。
不过经验告诉我们,量化的实施需要格外谨慎。简单的量化技术可能导致模型质量大幅下降。量化的影响也因模型架构(如MPT vs Llama)和模型大小而异。
在试验量化这类技术时,建议使用像Mosaic Eval Gauntlet这样的LLM质量基准来评估整体推理系统的质量,而不仅仅是孤立地看模型本身的质量。此外,深入的系统优化也很重要。特别是,量化可以让KV缓存变得更高效。
前文提到,在自回归token生成中,注意力层的过去键/值(KV)会被缓存,而不是每一步都重新计算。KV缓存的大小取决于一次处理的序列数量和这些序列的长度。在生成下一个token的每次迭代中,新的KV项会被添加到现有缓存里,随着新token不断生成,缓存会越来越大。因此,有效管理KV缓存内存对于良好的推理性能至关重要。
Llama2模型使用了一种叫分组查询注意力(GQA)的注意力变体。需要注意的是,当KV头的数量为1时,GQA就等同于多查询注意力(MQA)。GQA通过共享键/值来帮助减小KV缓存大小。KV缓存大小的计算公式是:batch_size × seqlen × (d_model / n_heads) × n_layers × 2 (K和V) × 2 (每个Float16的字节数) × n_kv_heads
表3显示了在序列长度为1024 token时,不同批量下GQA的KV缓存大小。作为对比,Llama2-70B模型本身的参数大小是140 GB(Float16)。除了GQA/MQA之外,KV缓存的量化是另一种减小缓存大小的技术,我们正在积极评估它对生成质量的影响。
如前所述,小批量下的LLM token生成属于GPU内存带宽受限问题——生成速度取决于模型参数从GPU内存搬到片上缓存有多快。把模型权重从FP16(2字节)转换成INT8(1字节)或INT4(0.5字节),需要搬运的数据更少,token生成自然更快。但量化也可能对模型的生成质量带来负面影响。
结论与关键建议
上面讨论的每个因素,都影响着我们构建和部署模型的方式。我们正是基于这些结果,从硬件类型、软件栈、模型架构和典型使用模式出发,做出数据驱动的决策。以下是我们在实践中总结出的一些建议:
- 先明确你的优化目标:到底是要交互性能?吞吐量最大化?还是成本最小化?这些目标之间存在可预测的权衡关系。
- 关注延迟的构成:对交互式应用来说,首个token的响应时间决定了服务的响应速度,而每个输出token的时间决定了用户感受到的“流畅度”。
- 内存带宽是关键:生成第一个token通常是计算受限的,而后续的解码过程是内存受限操作。由于LLM推理大多在内存受限的环境下运行,MBU就成了一个很有用的优化指标,可以用来比较不同推理系统的效率。
- 批处理至关重要:同时处理多个请求,是实现高吞吐量和有效利用昂贵GPU的核心。对共享在线服务来说,连续批处理是不可或缺的;而离线批量推理任务则可以通过更简单的批处理技术达到较高吞吐量。
- 深入优化:标准的推理优化技术(如算子融合、权重量化)对LLM很重要,但探索更深层的系统优化同样关键,尤其是那些能改善内存利用率的做法——KV缓存量化就是一个例子。
- 硬件配置要匹配:部署硬件的选择应根据模型类型和预期工作负载来决定。举例来说,扩展到多个GPU时,MPT-7B这样的小模型,其MBU下降速度比Llama2-70B快得多。性能随Tensor并行度提高也往往是次线性增长。但如果流量高,或者用户愿意为额外的低延迟买单,即便对较小的模型,采用更高的Tensor并行度也可能是有意义的。
- 让数据说话:理论理解很重要,但我们始终建议要实测端到端的服务性能。推理部署实际效果低于预期的原因有很多:MBU可能因为软件效率低下而意外偏低;不同云提供商之间的硬件差异也可能带来意外(我们就曾在两个云提供商的8x A100服务器之间观察到2倍的延迟差异)。
参考:LLM Inference Performance Engineering: Best Practices | Databricks Blog(https://www.databricks.com/blog/llm-inference-performance-engineering-best-practices)
