本节摘要:大模型端侧优化绕不开三堵墙——权重内存、KV 缓存增长、解码带宽。本节讲清权重压缩到八比特与四比特的机制与代价、预填充与解码两阶段的延迟结构,以及提示缓存与批量调度的收益来源。
5.1 节把流水线跑通了,但默认配置离设备极限还有数倍距离。大模型的优化地图与第 4 章同源不同路:还是「省内存、省计算」,但对象从一次前向变成了一个持续生长的循环。本节把三堵墙逐个拆解,每堵墙给出工具与代价。
第一堵是权重内存。参数量乘以每参数字节数就是模型的常驻内存下限:十八亿参数的模型 FP16 装下要三点六 GB,还没算激活与缓存。内存墙决定「能不能装」,是一切的前提。
第二堵是 KV 缓存增长。解码时每个历史词的注意力键值都要留着,缓存随序列线性生长。长上下文场景里,缓存体积能追上权重本身,把「装得下」变成「跑不久」。
第三堵是解码带宽。逐词解码阶段,每出一个词都要把全部权重从内存过一遍——算力往往闲着,内存带宽先打满。这解释了一个反直觉的现象:解码速度与设备算力的相关性,弱于它与内存带宽的相关性。三堵墙相互咬合:压权重腾出的内存余量,正是长上下文缓存的生存空间。
第 4 章的量化是「激活与权重一起压」,大模型的主流做法更聚焦:只压权重(weight compression),激活保持高精度。原因在于大模型激活分布常有离群值,压激活的风险收益比不划算;而权重占内存的大头,压它直接拆第一堵墙。NNCF 的权重压缩接口支持对称与非对称方案、逐通道刻度,四比特与八比特一键可切:
import openvino as ov import nncf model = ov.Core().read_model("llm-ir.xml") compressed = nncf.compress_weights( model, preset=nncf.CompressWeightsMode.INT4_SYM, # 或 INT8,体积与精度权衡 ratio=0.9, # 九成权重参与四比特 group_size=128, ) ov.save_model(compressed, "llm-ir-int4.xml")
经验区间:INT8 压缩对生成质量几乎无感,体积减半;INT4 体积再减半,多数对话场景质量可接受,但长文写作与代码生成这类对语言精度敏感的任务要用业务样本评测后再定。混合策略是常用的折中——ratio 控制四比特的权重占比,敏感层留在八比特,与 4.4 节「排除敏感层」是同一个思想在新场景的应用。
生成时间由两段构成,性质完全不同。预填充阶段处理完整输入提示,一次大规模并行计算,算力密集,时长近似与输入长度成正比;解码阶段逐词生成,每词一次权重扫描,带宽密集,时长与输出长度成正比。用户感知的「首字延迟」主要是预填充,「打字速度」是解码吞吐。两段的优化手段也不同:预填充靠算力与提示缓存,解码靠带宽与压缩。
这张时序图还藏着一项关键优化:多轮对话时,第二轮的提示前缀与第一轮相同——把上一轮的 KV 缓存按前缀复用,预填充只剩增量部分,首字延迟断崖式下降。5.1 节 start_chat 圈定的对话状态,管理的正是这件事。这也是提示词工程在部署侧的一个推论:把稳定的系统指令放前面、易变的内容放后面,前缀缓存才能吃到最大比例。
服务端大模型的看家本领是连续批量调度——把多个请求的解码步拼在一起喂满设备。端侧场景要冷静得多:边缘盒子同时服务的用户个位数,批量收益有限,反而推高首字延迟与内存峰值。端侧的默认答案是批量为一、独占设备、用前缀缓存与权重压缩把单请求路径做到极致。真正的多路场景(网关式部署)才值得打开批量,并用 7.1 节的工具实测批量粒度对首字延迟的影响。
第二堵墙值得给出具体的计算式,让「缓存会长大」变成可预算的数字。缓存体积约等于「层数乘以每层键值张量数乘以序列长度乘以隐藏维度乘以每元素字节数再乘以二(键与值各一份)」。拿一个典型的小尺寸模型心算:层数二十八、隐藏维两千、上下文四千词、十六位浮点,缓存约零点四 GB——模型权重压缩后一点二 GB,缓存追到权重的三分之一。上下文拉到一万六千词,缓存反超权重。这笔账的工程含义有三条:上下文长度是按内存定价的,不是越长越好;缓存配额要在部署设计里显式声明(5.3 节的预留就是它);压缓存精度的手段(键值缓存自身的低位宽量化)是进阶选项,代价要单独评测。预算先行,才不会被「长对话越跑越慢、突然内存耗尽」偷袭。
前缀复用是首字延迟的大头,另有两个杠杆值得知道。其一,提示压缩:系统指令里冗长的规则、示例,能用摘要与结构化改写压掉三到五成词元,预填充耗时同比例下降——提示词工程的收益直接落在延迟账上,这是「稳定内容前置、精简内容瘦身」的第二重理由。其二,分档上下文:简单问答用短上下文档,长文档任务才切长档,两档各配缓存配额——把「上下文长度」从全局配置变成会话参数,内存与延迟两头受益。三个杠杆(前缀复用、提示压缩、分档上下文)合起来,能把多轮场景的平均首字延迟压到朴素部署的一半以下,且全部是零训练成本的部署侧动作。
聊了很多性能,补质量验收。生成模型的「精度」没有单一指标,验收要三层:任务层用业务基准集(与 5.3 节一致,人工评级或自动评分),看压缩前后可用率变化;能力层抽一组能力探针(长文改写、代码生成、指令跟随各若干题),敏感任务对压缩最诚实的暴露点;分布层对比压缩前后输出的词汇多样性——分布骤然收窄意味着多样性受损,即使任务得分没掉也是警告。三层合议的结论才可信。还要立一条采样纪律:验收用固定随机种子跑两到三遍,质量结论建立在多份输出的合议上,单次生成的好坏有运气成分——这是生成类负载与判别式模型验收最大的方法论差异。
三堵墙话题收尾,回答三个高频追问。追问一:INT4 压缩后的模型,输出质量用什么快速体检?三个动作——固定题目对比(二十条业务典型题新旧各跑一遍人工对比)、长文连续性检查(千词以上续写看是否跑题复读)、指令跟随抽查(多约束指令看遵循度);十分钟出结论,适合升级压缩配置后的日常检查。追问二:解码速率达不到预期,第一查什么?查内存带宽的占用基线——同机还有其他服务在吃带宽时,解码速率首当其冲;带宽是共享资源,独占性比算力更难保证。追问三:上下文长度业务上必须两万词,内存装不下怎么办?分层应对——先试键值缓存低位宽(省四成缓存内存),不够再滑窗截断加摘要压缩提示,最后才是换更大内存设备;三招的精度代价递增,按顺序试。三个追问都指向同一件事:三堵墙的每一条都有「先便宜后昂贵」的处置序列,按序列走,多数预算内可解。
技术拼图齐了。下一节进入完整项目复盘:一台边缘盒子、一个七亿参数级模型、从选型到上线的全过程——看本章与全书的方法如何拧成一次交付。