
1. 从模型优化器这个命名说起它到底在解决什么问题第一次看到 Model-Optimizer 这个名字很多人会下意识地把它归类成又一个调参工具或者训练加速库。但真正在模型部署和推理这条链路上摸爬滚打过的人会明白模型优化器要处理的核心矛盾从来不是让模型跑得更快这么简单而是在精度、延迟、显存、吞吐这四个互相拉扯的指标之间找到一个能落地的平衡点。我接触过不少团队训练阶段一切顺利模型在验证集上指标漂亮结果一到上线就傻眼单次推理延迟 800ms显存占用 12GB一张消费级卡根本放不下只能堆 A100。这时候才想起来做优化往往已经错过了最佳时机。Model-Optimizer 这类工具的价值就在于把优化这件事从事后补救变成贯穿全流程的工程动作。它适合谁三类人最该关注。第一类是做模型部署的工程师天天和推理服务、显存、QPS 打交道第二类是算法工程师模型训完了要交付得对最终的性能指标负责第三类是边缘端或端侧开发者算力和内存都是硬约束优化不是可选项而是必选项。如果你属于这三类中的任何一类那接下来的内容应该能帮你少走不少弯路。需要先明确一点模型优化不是单一技术而是一整套组合拳。量化、剪枝、蒸馏、算子融合、图优化、内存复用、KV Cache 管理……每一项单独拎出来都能写一本书。Model-Optimizer 这类框架的意义是把这些技术封装成可组合、可配置、可复现的流水线让你不用从零造轮子。下面我会按先想清楚再动手的顺序把这条链路拆开讲透。2. 优化之前必须先搞明白的四件事2.1 你的瓶颈到底在计算还是在访存这是最容易被跳过、却最影响优化收益的一步。很多人一上来就上量化结果发现延迟没降多少反而精度掉了。原因很简单如果瓶颈在访存带宽你把计算精度从 FP16 降到 INT8计算量是少了但数据搬运量没变延迟自然下不来。判断方法其实不复杂。先看模型的算术强度Arithmetic Intensity也就是每搬运 1 Byte 数据能做多少次浮点运算。大矩阵乘、卷积这类算子算术强度高属于计算密集型量化收益明显而 LayerNorm、Softmax、逐元素操作这类算术强度低属于访存密集型优化重点应该放在减少内存访问次数、算子融合上。我一般会用一个土办法快速定位把 batch size 从 1 逐步加到 32观察延迟变化。如果延迟几乎不随 batch 增长说明计算单元没吃满瓶颈大概率在访存或调度如果延迟随 batch 线性上涨那计算就是瓶颈量化、剪枝这类手段才有用武之地。2.2 精度损失的可接受边界在哪里优化必然带来精度损失问题是你能不能接受、能接受多少。这里有个经验值可以参考分类任务 Top-1 掉 0.5% 以内通常无感检测任务 mAP 掉 1% 以内可以接受而生成式任务的评估就复杂得多得看具体业务对生成质量的要求。关键在于建立一套自己的评估基线。不要只看一个总体指标要分场景、分数据切片去看。我见过量化后总体指标只掉 0.3%但在某些长尾类别上直接崩掉的案例。所以优化前后一定要跑同一套评测集并且把结果按维度拆开对比而不是只看一个平均数。2.3 目标硬件的特性决定了优化方向同一个模型部署在服务器 GPU、移动端 NPU、还是 CPU 上优化策略完全不同。服务器 GPU 显存大、算力强优化重点在吞吐和显存利用率移动端 NPU 往往对特定算子有硬件加速但对不支持的算子会回退到 CPU造成性能断崖CPU 上则要重点考虑指令集AVX2、AVX512和线程调度。所以动手前先把目标硬件的这几个参数查清楚支持的量化类型INT8/INT4/FP16、算子支持列表、内存带宽、是否有专用加速单元。这些信息决定了你哪些优化能做、哪些做了也白做。2.4 优化是迭代过程不是一次性动作最后这点是心态问题。很多人期望跑一遍优化脚本就拿到最优结果现实是一轮轮试出来的。每一轮改动一个变量测一次指标记录下来再决定下一步。这个过程枯燥但必要。我习惯用一张表格管理实验把配置、精度、延迟、显存四列记清楚避免改着改着忘了哪个配置效果最好。3. 量化收益最大但也最容易翻车的一环3.1 训练后量化与量化感知训练怎么选量化分两条路线。训练后量化PTQ是拿训好的模型直接量化成本低、上手快适合大多数场景量化感知训练QAT是在训练过程中模拟量化误差让模型提前适应精度通常更好但需要重新训练成本高。我的建议是先试 PTQ如果精度达标就直接用如果 PTQ 掉点严重再考虑 QAT。不要一上来就 QAT那是杀鸡用牛刀。PTQ 里又分动态量化和静态量化动态量化对激活值在推理时实时统计实现简单但延迟收益有限静态量化需要校准数据集提前统计激活分布收益更大但需要准备校准数据。校准数据的选择有讲究。不要随便拿几百条训练数据凑数校准集要能代表真实推理时的数据分布。我一般会从验证集里分层采样 500 到 1000 条覆盖各个类别和长度区间。校准集选得不好激活值的 min/max 范围估计偏差大量化误差会明显放大。3.2 逐张量量化与逐通道量化的取舍量化粒度直接影响精度。逐张量量化per-tensor对整个张量用一组 scale 和 zero-point实现简单、硬件友好逐通道量化per-channel对每个通道单独统计精度更好但实现复杂。对于权重我强烈建议用逐通道量化因为权重分布在不同通道间差异往往很大逐张量会损失很多信息。对于激活值逐张量通常就够了因为激活值的动态范围相对集中而且逐通道激活量化对硬件支持要求高很多推理引擎不支持。这里有个实操细节权重的逐通道量化维度要选对。卷积层一般按输出通道量化全连接层按输出维度量化。选错维度精度收益会大打折扣。3.3 混合精度不是所有层都该被量化一刀切地把所有层都量化成 INT8往往不是最优解。有些层对量化特别敏感比如第一层和最后一层、注意力机制里的某些投影层、LayerNorm 相关的计算。把这些层保留在高精度FP16 或 FP32其余层量化能在精度和性能之间取得更好的平衡。怎么找出敏感层可以用逐层敏感度分析每次只把一个层量化其余保持原精度测精度变化。变化大的就是敏感层。这个过程比较耗时但一次分析可以复用。Model-Optimizer 这类框架通常提供了敏感度分析的接口直接调用就行。3.4 量化踩坑实录那些文档不会告诉你的问题说几个我实际踩过的坑。第一个是校准时的 batch 组织方式。有些框架默认按单条校准有些按 batch 校准两者统计出的激活分布不一样。如果推理时是 batch 推理校准也应该用 batch否则分布对不上。第二个是量化后的算子融合顺序。量化算子和它前后的算子融合时如果顺序不对可能引入额外的反量化-量化开销反而变慢。这个得看具体推理引擎的图优化策略必要时手动调整融合规则。第三个是动态 shape 场景下的量化。如果模型支持变长输入量化时的 scale 是按固定 shape 统计的遇到超出范围的 shape 可能溢出。解决办法是统计时覆盖足够大的 shape 范围或者对超范围输入做特殊处理。4. 剪枝与蒸馏给模型瘦身的两种思路4.1 结构化剪枝与非结构化剪枝的本质区别剪枝的核心思想是去掉模型中不重要的参数或结构。非结构化剪枝是把单个权重置零理论上能大幅压缩模型但实际加速效果取决于硬件是否支持稀疏计算。很多 GPU 对稀疏矩阵的支持有限剪了也快不起来。结构化剪枝是直接去掉整个通道、整个注意力头剪完就是个小模型硬件友好加速效果实在。我的经验是面向部署的剪枝优先选结构化。非结构化剪枝更适合研究场景或者有专门稀疏加速硬件的场景。结构化剪枝里通道剪枝最常用注意力头剪枝在 Transformer 类模型上效果也不错。4.2 重要性评估怎么判断哪些结构可以剪剪枝的关键是判断重要性。常见的方法有几种基于权重范数L1/L2认为范数小的通道不重要基于激活值统计认为激活值小的通道贡献小基于梯度信息认为梯度小的通道对损失影响小。这几种方法各有局限。权重范数简单但忽略了激活分布激活统计更贴近实际但需要跑数据梯度信息最准但计算成本高。实践中我一般先用权重范数做粗筛再用激活统计做精筛两步走效率比较高。还有一个容易被忽略的点剪枝要考虑层与层之间的耦合。比如残差连接要求输入输出维度一致剪了某一层可能影响后续层的维度匹配。所以剪枝不是逐层独立操作要按块block来考虑保证结构一致性。4.3 蒸馏让小模型学会大模型的思维方式蒸馏是另一条路不剪原模型而是训一个小模型去模仿大模型的输出。这里的输出可以是 logits软标签也可以是中间层特征甚至是注意力分布。温度参数 T 是蒸馏里的关键超参。T 越大软标签分布越平滑小模型能学到更多暗知识T 太小软标签接近硬标签蒸馏退化成普通训练。一般 T 取 2 到 10 之间配合一个权重系数 α 平衡软标签损失和硬标签损失。蒸馏的坑在于容量差距。如果学生模型太小和老师差距太大学不动效果可能还不如直接训。所以学生模型的容量要选得合理一般参数量是老师的 1/4 到 1/10 比较合适。4.4 剪枝和蒸馏能不能一起用可以而且效果往往比单用好。典型流程是先剪枝得到一个中等大小的模型再以原模型为老师做蒸馏把剪枝损失的性能补回来。这个组合在工业界很常见尤其是对延迟敏感的场景。顺序上也有讲究。先剪后蒸比先蒸后剪更常见因为剪枝会改变模型结构蒸馏需要稳定的结构来对齐。如果先蒸后剪剪枝可能破坏蒸馏学到的知识。当然具体还得看任务没有绝对的最优顺序。5. 图优化与算子融合不损失精度的免费午餐5.1 算子融合为什么能同时降延迟和降显存算子融合是把多个小算子合并成一个大算子减少 kernel 启动次数和中间结果的显存读写。这是唯一一类几乎不损失精度、纯赚性能的优化所以优先级应该排在量化和剪枝之前。举个典型例子Conv BatchNorm ReLU 三个算子如果不融合中间结果要写回显存再读出来三次 kernel 启动融合后一个 kernel 搞定中间结果留在寄存器或共享内存里显存访问次数大幅减少。在访存密集的场景下这种融合能带来 20% 到 40% 的延迟下降。5.2 常见的融合模式与适用条件常见的融合模式有几类。逐元素融合把 Add、Mul、激活函数等逐元素操作合并归约融合把 Softmax、LayerNorm 里的多个步骤合并矩阵乘融合把 MatMul 和它前后的 bias add、激活合并。融合不是无条件的。有些融合会改变数值计算结果虽然理论上等价但浮点误差累积可能导致结果不一致。所以融合后一定要做数值对比确认误差在可接受范围内。另外融合后的算子如果太大可能超出硬件寄存器或共享内存限制反而变慢这时候要拆分。5.3 内存复用与原地操作除了算子融合内存复用也是重要的优化手段。核心思想是让生命周期不重叠的张量共享同一块显存。推理时很多中间张量用完就释放如果框架能分析出哪些张量可以复用就能显著降低峰值显存。原地操作in-place是另一种手段比如 ReLU 可以直接在输入张量上修改不额外分配输出。但原地操作有风险如果输入张量后续还要用就会被破坏。所以框架一般只在确认安全时才做原地优化手动优化时要特别小心。5.4 图优化在不同推理引擎上的差异不同推理引擎的图优化能力差别很大。有的引擎优化规则丰富能自动完成大部分融合有的引擎比较保守需要手动指定融合模式。选引擎时除了看性能也要看它的图优化能力是否匹配你的模型结构。我的一般做法是先用引擎自带的优化跑一遍看性能如果不够再手动介入调整融合规则或重写部分算子。不要一上来就手动优化那是最后的手段。6. 一套可复现的优化流水线该怎么搭6.1 从基线测量开始别急着改优化第一步永远是建立可靠的基线。在没做任何优化前把模型的延迟、吞吐、显存、精度全部测一遍记录下来。测量要规范固定输入 shape、固定 batch size、预热足够轮次、多次测量取稳定值。基线不牢后面所有对比都是空中楼阁。我见过太多人优化了半天结果发现基线测的时候没预热数据根本不可比。预热很重要尤其是 GPU 上前几次推理包含 kernel 编译、显存分配等开销不预热测出来的延迟偏高。6.2 优化顺序先图优化再量化最后剪枝蒸馏顺序很重要我推荐的顺序是图优化 → 量化 → 剪枝/蒸馏。图优化不损精度先做量化收益大但可能掉点其次剪枝蒸馏改动最大放最后。每做完一步都要重新测精度和性能确认收益和损失。如果某一步收益不明显或者损失太大就回退不要硬上。优化是加法也是减法该放弃的时候要果断。6.3 用配置管理实验避免改着改着忘了优化过程会产生大量实验配置管理不好很容易乱。我的做法是用一个 YAML 或 JSON 文件管理所有配置每次实验存一份文件名带上日期和关键参数。同时维护一张实验记录表记录每个配置的精度、延迟、显存和结论。这样做的好处是可复现。过一段时间回头看能清楚知道哪个配置效果最好、为什么好。团队协作时这份记录也是宝贵的知识资产。6.4 上线前的最后一道关真实数据验证实验室指标再好也要过真实数据这一关。上线前一定要用真实流量或接近真实的测试集跑一遍确认精度和性能都达标。真实数据的分布往往和验证集有差异量化、剪枝带来的精度损失在真实数据上可能被放大。我一般会做 A/B 对比优化前后的模型同时跑一段时间对比业务指标。如果业务指标没有明显下降才算真正通过。这一步不能省省了就是给自己埋雷。7. 那些年我在模型优化上踩过的坑7.1 量化后精度掉了但不知道掉在哪这是最常见的问题。量化后总体指标掉了一点但具体是哪些样本、哪些类别掉的不清楚。解决办法是做逐样本对比把优化前后对每个样本的预测结果都存下来找出预测发生变化的样本分析它们的共同特征。我做过一次这样的分析发现量化后出错的样本集中在输入长度特别长或特别短的两端。原因是校准集里这两种长度的样本太少激活值统计不准。补充校准数据后问题就解决了。所以精度掉了不要慌先定位再对症下药。7.2 显存没降反升的诡异现象有一次做完量化延迟降了但显存反而涨了。排查后发现是量化算子的实现问题某些推理引擎的量化算子会额外分配反量化缓冲区如果融合没做好这些缓冲区一直占着显存。解决办法是检查量化算子的融合情况确保量化-计算-反量化能融合成一个算子。如果引擎不支持可以考虑手动重写这部分。这个坑提醒我们优化效果要全面看不能只看延迟一个指标。7.3 多卡推理时的负载不均多卡部署时如果模型切分不合理可能出现某张卡忙死、某张卡闲死的情况。尤其是 Transformer 类模型注意力层的计算量和序列长度相关切分不当会导致负载严重不均。解决办法是按计算量而非参数量来切分或者用流水线并行让各卡交替工作。这个优化比较依赖具体框架的支持选框架时要留意它的并行策略是否灵活。7.4 优化后的模型换硬件就失效这是很现实的问题。在 A 硬件上优化得很好的模型换到 B 硬件上可能性能暴跌。原因是不同硬件对算子、量化类型、内存布局的支持不同。优化时如果用了硬件特有的指令或算子换硬件就废了。所以如果目标硬件可能变化优化时要尽量用通用方案或者准备好针对不同硬件的多套配置。可移植性和极致性能往往不可兼得要提前想清楚优先级。8. 关于 Model-Optimizer 这类工具我的几点真实体会用了这么多优化工具和框架我最大的体会是工具能帮你省力但不能替你思考。Model-Optimizer 这类框架把量化、剪枝、图优化封装得很好但每一步该不该做、做到什么程度、精度损失能不能接受这些判断只能你自己做。第二个体会是优化要趁早。不要等模型训完、要上线了才想起来优化。训练阶段就可以考虑用对量化友好的结构、控制模型大小、避免过于复杂的算子。这些前期决策对后期优化的难度影响巨大。第三个体会是别追求极致。优化到一定程度收益会递减而投入的时间成本急剧上升。找到满足业务需求的平衡点就收手把精力放到其他更有价值的事情上。我见过为了再降 5ms 延迟折腾两周的案例那两周的投入产出比实在不划算。最后说个实操建议建立自己的优化 checklist。把每次优化要检查的点列成清单比如校准集是否覆盖全面、敏感层是否保留高精度、融合是否完整、真实数据是否验证过。每次优化照着清单过一遍能避免很多低级错误。这个清单会随着你的经验不断丰富成为你最宝贵的个人资产。模型优化这条路没有银弹只有不断试错和积累。希望上面这些经验能帮你少踩几个坑更快找到适合自己场景的那套方案。