推理加速与模型压缩
模型量化为什么能加速推理?从计算和内存带宽角度分析。¶
模型量化是将神经网络中的浮点参数(通常是 FP32)转换为低精度的整数(如 INT8、INT4)表示,从而在推理时使用低精度整数运算代替浮点运算。其加速推理的收益主要来自两个方面:
计算层面
-
更高效的算力:现代 CPU 和 GPU 都提供了针对低精度整数运算的专用指令集(如 x86 的 VNNI、ARM 的 NEON、NVIDIA GPU 的 Tensor Core),能在单位时钟周期内执行更多整数乘加运算。例如,NVIDIA A100 的 INT8 Tensor Core 的理论峰值可达 624 TOPS,而 FP32 仅 19.5 TFLOPS,相差约 32 倍。
-
减少运算量:INT8 乘法比 FP32 乘法消耗更少的逻辑单元和能量,同样面积可以放置更多计算单元,吞吐量更高。
-
融合操作:量化后的模型更容易进行算子融合,例如将卷积+偏置+激活+量化统一为单一整数操作,进一步减少 kernel 启动开销。
内存带宽层面
-
模型体积缩小:FP32 权重占 4 字节,INT8 权重占 1 字节,模型文件大小减少至约 1/4。当模型无法完全装入缓存时,从内存加载权重成为瓶颈。量化后,相同数量的权重要传输的字节数大幅减少,有效提升了内存带宽利用率。
-
缓存利用效率:更小的权重可以更长时间地驻留在 L2/L3 缓存中,减少对 DRAM 的访问。对于 memory-bound 的推理任务(如小 batch 下的全连接层、循环层),这是主要的加速来源。
-
激活值量化:如果同时量化激活值,中间特征图也变为低精度,显著减少每一层的写入和下一层的读取数据量,进一步降低带宽压力。
因此,即使单次整数运算时间不显著低于浮点,带宽节省和计算密度的提高共同实现了端到端加速。

对称量化与非对称量化的公式分别是什么?有何区别?¶

对称量化 假设原始浮点值关于零点对称分布,零点固定为 0,不使用 zz。
- 浮点到整数:


非对称量化
允许零点偏移,更灵活地匹配实际数据分布。
- 确定尺度 s 和零点 z:

量化公式:

裁剪后,反量化:

区别
-
对称量化计算更简单,因为零点为 0,在矩阵乘法中可消去零点的项,硬件实现更高效。但要求数据分布大致对称,否则会浪费量化范围。
-
非对称量化可以精确表示偏移分布(例如激活值经过 ReLU 后均为非负),充分利用量化区间,通常精度更高,但零点引入额外计算开销(如卷积中需要考虑零点补偿)。
-
实际中,权重通常是对称分布的,适合对称量化;激活值常常是非负的,倾向于非对称量化。
训练后量化(PTQ)与量化感知训练(QAT)的核心不同是什么?各在什么场景下使用?¶
训练后量化 (Post-Training Quantization, PTQ)
在已训练好的 FP32 模型上,直接插入量化/反量化节点,通过少量无标签校准数据(或无需数据)统计权重和激活的数值范围,确定量化参数(尺度、零点),然后完成量化。不需要重新训练。
-
优点:快速、无训练成本,适合快速部署。
-
缺点:对于激活值波动大、模型敏感的场景,精度损失可能较大。
-
适用场景:已有 FP32 模型,需要快速转成 INT8 进行推理加速;计算资源有限无法进行再训练;相对简单的网络或精度要求不那么苛刻的任务。
量化感知训练 (Quantization-Aware Training, QAT)
在训练过程中模拟量化误差:前向传播时对权重和激活进行伪量化(量化-反量化),让网络适应量化带来的信息损失;反向传播使用直通估计器 (STE) 更新原始浮点权重。最终训练完成后,再导出真正量化的模型。
-
优点:显著恢复甚至完全弥补量化精度损失,通常可以实现接近 FP32 的准确率。
-
缺点:需要完整的训练流程和标记数据,耗时更长。
-
适用场景:对精度要求极高(如分类、检测),模型较复杂、对量化敏感,或者极低位宽(如 INT4)时必须使用 QAT 以保持性能。
核心不同:PTQ 是一次性校准,QAT 是模拟量化误差下的训练。PTQ 方便快捷,QAT 精度高但成本高。
什么是逐张量量化和逐通道量化?为什么逐通道量化精度更高?¶
量化可以以不同的粒度进行,主要体现在尺度因子 ss 的计算范围。
- 逐张量量化 (Per-tensor quantization):对整个权重张量或激活张量,使用同一个尺度和零点。例如,一个卷积层所有输出通道共享一个 s。实现简单,对应硬件友好,但忽略了不同通道的数值分布差异。

逐通道精度更高的原因
不同输出通道的权重分布可能差异显著:某些通道的权值幅度大,某些较小。使用同一尺度时,幅度大的通道会被正确表示,但幅度小的通道的很多值会被量化为 0 或损失精度(因为量化步长相对于其幅度太大)。逐通道量化允许每个通道用自己的尺度,精细地匹配其范围,保留了更多小权重通道的信息。这在深度可分离卷积、Transformer 等结构中尤为重要,因为这些网络不同通道间的尺度差异巨大。实验表明,逐通道量化可将精度损失从数个百分点降低到几乎无损。
代价是计算复杂度略增:硬件需要支持每个输出通道不同的尺度,在进行卷积时需按通道分别应用尺度,现在多数推理引擎(如 TensorRT)已支持。
8 位量化中,权重和激活值的量化方案通常是怎样的?¶
在 INT8 推理中,典型的方案是权重量化+激活量化。
权重量化

-
对于全连接层,可使用逐张量对称量化。
-
量化后的权重以 INT8 存储,反量化时乘尺度。
激活量化
-
激活值取决于输入数据,需要动态获取范围。使用一批校准数据(通常 100-1000 张图)运行推理,收集每个激活张量的统计信息(如最大值、最小值、直方图)。
-
常见方法:

- 激活值通常是非负的(如 ReLU 后),更适合非对称量化,零点用于补偿偏移。
矩阵乘法融合

现代推理引擎(TensorRT, OpenVINO)自动化了这些过程。
LLM.int8() 的混合精度量化分解是怎么做的?为何要对离群值进行特殊处理?¶
LLM.int8() 是专门针对大语言模型(LLM)推理的量化方法,由 Dettmers 等提出。它观察到 Transformer 的激活值中存在离群值(outliers):极少数特征维度(如 0.1%)的数值远大于其他维度,这些离群值对量化精度破坏极大。
混合精度量化分解

由于 FP16 部分占比极小,额外开销很低,但完全避免了离群值造成的巨大量化误差,使 8 位量化在大模型上的准确率达到与 FP16 几乎一致的水平。
为何离群值要特殊处理
离群值的绝对值可能是其他值的 100 倍以上。如果用统一的尺度量化,离群值会撑大尺度,导致正常值在量化后严重失真(分辨率极低);如果截断离群值,则会丢失关键信息,因为这些离群值往往对应于重要的 token 位置(如分隔符、标点)。因此,混合精度是解决这一矛盾的优雅方案。
GPTQ 如何进行权重量化?它基于的 OBQ 算法思路是什么?¶
GPTQ (Frantar et al., 2022) 是一种用于大规模生成预训练 Transformer (GPT) 的权重量化方法,可以在数小时内完成 175B 模型的 3/4 位量化,精度损失很小。
OBQ 算法基础
GPTQ 基于最优脑量化(Optimal Brain Quantizer, OBQ)的思想。OBQ 将权重量化看作逐权重的剪枝问题:每次量化一个权重,并更新剩余未量化的权重来补偿该权重量化造成的输出误差。

GPTQ 的改进
-
针对 Transformer 的超大层,GPTQ 不做逐元素贪心,而是采用逐块量化:将权重矩阵划分为若干块,逐块处理。块内所有权重同时量化,然后基于 Hessian 对块外未量化的权重进行补偿更新。
-
利用 Hessian 的结构性,通过 Cholesky 分解高效计算补偿。
-
重新排序(reorder)技巧:在量化前根据 Hessian 信息对权重列重排,使同一块内的权重有相似的量化难度,提升性能。
-
支持极低位宽(4bit、3bit)并配合分组量化(group-wise quantization)以降低误差。
最终,GPTQ 能够快速量化超大规模语言模型,且只需使用少量校准数据。
AWQ 如何根据激活值分布对重要权重进行保护,而不需要反向传播?¶
AWQ (Activation-aware Weight Quantization) 观察到:虽然权重中只有少部分对应高激活值的通道对输出至关重要,但直接按权重显著性或激活值显著性进行保护会导致过拟合或开销大。AWQ 提出一种简单而有效的方法:根据激活值分布对重要权重通道进行缩放保护。
核心思想

优势
-
不需要重训练或梯度计算,仅需要一小批校准数据来确定缩放因子,速度快。
-
与混合精度分解不同,AWQ 仍然保持所有计算在 INT8/INT4 整数域,不引入 FP16 计算单元,硬件效率极高。
-
在多种 LLM 上取得了与 GPTQ 相当甚至更好的精度,同时实现更简单。
SmoothQuant 的核心思想是什么?它如何平滑激活值离群点?¶
SmoothQuant (Xiao et al., 2023) 针对大语言模型激活值中存在的离群值,提出一种权重-激活平滑技术,消除激活离群值,从而使得激活值易于量化。
核心思想
在 LLM 中,离群值常集中在某些特征通道,导致激活的某些通道数值极大。对激活直接量化会很困难。SmoothQuant 通过一个数学等价的变换,将激活的量化难度迁移到权重上,实现“平滑”。

效果
SmoothQuant 使得对激活值的量化变得容易,在 W8A8(权重 8bit、激活 8bit)设置下,无需复杂的混合精度,即可实现大语言模型的近乎无损量化。极大简化了推理实现,已经集成到多个部署框架中。
如何评估量化模型的精度损失?有哪些指标和方法?¶
评估量化模型精度损失,主要在原任务指标上对比量化前后性能,同时兼顾速度和效率。
主要指标

评估方法
-
数据集测试:在完整的验证/测试集上运行量化模型,计算任务指标。这是最终评估标准。
-
层级别分析:将 FP32 模型每一层的输出作为参考,对比量化后的输出,找出误差最大的层进行针对性优化。
-
退化诊断:如果精度损失大,检查权重和激活的直方图,确认是否存在大量值被裁剪或被量化为零。
-
混合精度量化:允许部分敏感层保留 FP16,使用自动或手动搜索确定敏感层。
-
A/B 测试:在真实业务环境中对比延迟与质量。
实际中,综合使用任务指标和层分析可以高效调优量化参数,达到精度与速度的最佳平衡。
结构化剪枝和非结构化剪枝有什么区别?为什么非结构化剪枝更难实现加速?¶
非结构化剪枝
将神经网络中单个不重要权重置零,即产生稀疏连接。剪枝后的权重矩阵是稀疏的,零值位置任意。
-
优点:可以达到极高的稀疏度(如 90% 以上)而几乎不损失精度,因为粒度细。
-
缺点:稀疏矩阵运算在通用硬件(CPU/GPU)上很难直接加速——不规则的内存访问和跳零计算导致实际加速比远低于理论稀疏度。通常需要专用硬件(如稀疏张量核)或特定的稀疏矩阵库(需要满足块稀疏等约束)才能有效利用。因此非结构化剪枝往往只节省存储,不容易直接提升推理速度。
结构化剪枝
以卷积核、通道、层等规则结构为单位进行剪枝。例如,移除整个滤波器、整个通道或某个注意力头。剪枝后的模型仍然是密集的,只是维度变小。
-
优点:可直接利用现有密集矩阵运算库(cuBLAS、MKL)高效加速,没有稀疏计算开销。同时减少内存占用和计算量,无需专门硬件即可获得实际加速。
-
缺点:剪枝粒度粗,同样压缩率下通常比非结构化的精度损失大,可达到的稀疏度也较低。
总结:非结构化剪枝更灵活、精度高但硬件难以加速;结构化剪枝容易加速但精度损失可能更大。实践中需要加速时多采用结构化方法。
如何在卷积神经网络中剪枝滤波器?常见的重要性判断准则有哪些(L1 范数、BN 缩放因子等)?¶
剪枝滤波器的通用流程
-
选择重要性准则,为每个滤波器(输出通道)评分。
-
根据目标剪枝比例,移除评分最低的滤波器及其关联的下一层输入通道。
-
移除后的模型权重被物理删除,得到更小的密集模型。
-
通常需要微调(fine-tuning)以恢复精度。
常见重要性准则
-
L1 范数:计算每个滤波器权重的 L1 范数(绝对值之和)。假设权值较小的滤波器对输出贡献小,可以安全移除。这是最经典的方法,简单有效。
-
L2 范数:滤波器权重平方和,类似但更强调较大的值。
-
BN 缩放因子 γ:在网络使用 BatchNorm 时,BN 中的缩放因子 γ 与对应通道的激活相关联。训练时在 γ 上施加 L1 正则化,使其稀疏,修剪那些 γ 接近零的通道。代表方法 Network Slimming。
-
激活值均值/方差:利用校准数据计算每个滤波器输出的激活平均值,小激活的滤波器被认为不重要。
-
梯度或泰勒展开:计算移除滤波器对损失函数的一阶或二阶泰勒近似,衡量其对最终损失的影响。计算代价较高但通常更准确。
-
APoZ (Average Percentage of Zeros):对于 ReLU 激活,统计每个通道输出中零的比例,比例高则激活稀疏,滤波器可能不关键。
应用示例:在 ResNet 上,使用 L1 范数对每一层滤波器排序,保留前 70% 的滤波器,然后微调 10 个 epoch,能在几乎不损失精度的情况下降低约 30% 的 FLOPs。
迭代剪枝是怎样进行的?剪枝后是否需要微调?¶
迭代剪枝是指分多次逐步剪枝,而不是一次性剪掉大量权重。每次剪枝后都对模型进行微调,使其从损伤中恢复,然后再进行下一轮剪枝。
步骤
-
训练一个基准模型(或使用预训练模型)。
-
设定单次剪枝比例(如 10%),根据重要性准则去掉最不重要的权重或滤波器。
-
对剪枝后的模型进行微调(fine-tuning),使用原始训练数据,训练若干个 epoch,使剩余权重适应新结构。
-
重复步骤 2-3,直到达到目标总剪枝率或精度下降到阈值以下。
-
最终可在保持较高精度的前提下,获得高度稀疏或紧凑的模型。
是否需要微调
是,微调至关重要。剪枝通常会立即造成精度下降,通过微调可以恢复大部分甚至全部性能。如果不微调,直接剪枝可能导致精度崩溃。微调使剩余参数重新学习被剪去参数的功能。在某些简单任务或极低剪枝率下,不微调也可接受,但普遍强烈推荐微调。微调可长可短,常用原训练学习率的 1/10 进行少量 epoch。
知识蒸馏中,教师模型和学生模型是如何定义的?蒸馏损失通常包含哪两部分?¶
定义
-
教师模型:一个高性能、通常较大、已经训练好的模型,用于提供“知识”。
-
学生模型:一个较小的、待训练的模型,通过学习教师的输出来获得接近教师的性能。
蒸馏损失
通常包含两部分损失,组合训练学生:
- 硬标签损失(学生与真实标签的交叉熵)

- 软标签损失(学生与教师软输出的蒸馏损失) 教师和学生都使用温度 T 的 softmax 产生软标签:

其中 α 为平衡权重,通常接近 1(更依赖教师)。
这样,学生既直接学习正确答案,又模仿教师关于各类别相似性的暗知识。
解释蒸馏中“温度系数”的作用,温度越高,软标签的分布有何变化?¶

作用
-
当 T=1,为标准 softmax,概率分布尖锐,硬标签的负类概率接近 0,只提供很少的信息(接近 one-hot)。
-
当 T>1,分布变得更平滑、软标签熵更高。原本很小的负类概率被放大,相对差异减小,即“软化”。这使得学生可以从教师那里学到类别间的相似性结构(例如,猫的软标签中,豹子可能也有较高概率,而汽车极低),这种丰富的暗知识对小模型训练很有价值。
-
极高温(T→∞)时,分布趋于均匀分布,蒸馏信号消失。
-
温度降低(T<1)会使分布更尖锐,接近硬标签。

在线蒸馏和离线蒸馏的区别是什么?自蒸馏是如何做到的?¶
离线蒸馏 (Offline Distillation)
-
先独立训练一个强大的教师模型(大模型),然后固定其权重,只作为知识源。
-
再训练学生模型,损失由教师提供的软标签和真实标签组成。
-
是经典的蒸馏流程,教师和学生训练解耦,可以一对多,也可多次使用。
在线蒸馏 (Online Distillation)
-
教师和学生同时训练,互相学习,或者若干模型合作学习。
-
典型如深度相互学习(Deep Mutual Learning):一群小模型一起训练,每个模型不仅最小化与真实标签的损失,还最小化与其他模型输出的 KL 散度。它们互为师生。
-
不需要预先训练好大模型,所有模型一起成长,最终选择一个作为部署模型。
自蒸馏 (Self-Distillation)
-
学生模型的结构与教师相同,或教师就是学生自己(更深层的部分)。
-
常见做法:在同一模型中,将深层(更高层的 logits)作为浅层的教师,或者用聚合预测(如模型集成)教导单个模型。
-
例如,训练一个网络,同时使用其最终的分类层和较早的分类头;深层输出作为教师,浅层输出作为学生。或者训练一个网络的 EMA(指数移动平均)版本作为教师教导原网络。
-
本质上是利用模型自身的知识进行正则化,提升泛化。
知识蒸馏除了软标签,还可以传递哪些知识?如注意力图、特征图。¶
蒸馏可以发生在模型的多个表示层,不仅限于最终 logits。常见的传递形式:
- 特征图蒸馏 (Feature Distillation)

- 注意力图蒸馏 (Attention Transfer)
传递空间注意力图(例如,对特征图的通道进行合并得到的 2D 注意力掩码)。损失函数最小化学生和教师注意力图之间的差异,促进学生关注相似区域。
- 关系蒸馏 (Relational Knowledge Distillation, RKD)
传递样本间的关系或特征间的关系。比如,对于一批样本,让学生输出特征之间的距离矩阵(相似性结构)匹配教师的距离矩阵。保留的不是绝对值,而是相对结构。
-
其他
-
激活边界:传递每层激活值的统计信息。
-
参数蒸馏:学生直接预测教师的权重?少见。
-
生成式蒸馏:用教师模型生成大量数据或 soft pseudo-labels,扩展学生训练数据。
这些方法通常可以结合软标签蒸馏,进一步提升学生性能。
算子融合为什么能加速推理?常见的融合模式有哪些(Conv+BN+ReLU)?¶
加速推理的原因
-
减少内存访问:深度学习推理常受内存带宽限制。每个独立算子都需要从显存读取输入,写出中间结果。当多个算子融合成一个 kernel 后,中间数据得以在寄存器或共享内存中即时传递,避免了大量全局内存读写,显著降低访存开销。
-
减少 kernel 启动开销:GPU 上每次启动一个 CUDA kernel 都有固定的调度延迟(数微秒)。许多小算子独立执行时,kernel launch 次数多,耗费大量时间。融合后在一个 kernel 内完成多个操作,启动次数急剧减少。
-
提高计算密度:将访存密集型操作(如 ReLU)与计算密集型操作(如卷积)合并,可以将访存与计算更好地重叠,提升硬件利用率。
-
便于编译器进一步优化:融合后的计算图更简洁,编译优化器(如 TVM、XLA)能进行更激进的循环级优化与向量化。
常见融合模式

-
矩阵乘法 + 激活:如全连接层 + GeLU / ReLU。
-
逐元素操作融合:多个连续的 element-wise 操作(add、mul、sigmoid 等)合并为一个 kernel,一次完成所有运算。
-
注意力机制融合:Transformer 中 QKV 投影合并为大矩阵乘法;softmax 与 mask、dropout 融合。
-
残差连接融合:将 Conv + BN + ReLU + Element-wise Add 一并融合。
-
LayerNorm + 后续线性层融合:将 LN 的仿射参数融入权重,或直接在同一个 kernel 内计算 LN 与矩阵乘。
推理优化器(TensorRT、ONNX Runtime、TVM)会在编译阶段自动执行这些融合。
TensorRT 是如何进行图优化和算子融合的?相比于框架推理,通常能提升多少?¶
图优化和算子融合步骤
-
导入与解析:从训练框架(ONNX、TensorFlow、PyTorch 等)读取模型图。
-
图结构优化:
- 无用层消除:移除仅用于训练的输出节点(如 loss)。
- 常量折叠:预计算静态子图(如固定 reshape、常量加减)的结果,减少运行时计算。
- 算子融合:
- 垂直融合:顺序执行的层合并,如 Conv → BN → ReLU 融合为 CBR。
- 水平融合:结构相同、输入相同的并行层合并。例如将多个并行的 1×1 卷积合并为一个更大的卷积,然后通过 slice 拆分输出,减少 kernel 启动。
-
消除串联操作:将 slice / concat 等不改变数据的操作融入前后层。
-
精度校准(INT8 量化):通过校准数据集动态确定各层的量化尺度。
-
硬件级自动调优:针对目标 GPU 架构(SM 数量、显存带宽、Tensor Core 支持等),为每个融合后的层选择或生成最优 kernel 实现。尝试不同的矩阵乘法算法、tile 大小、WMMA 指令,选择执行时间最短的配置。
-
内存优化:执行张量生命周期分析,实现显存重用,最小化显存占用。
-
生成序列化引擎:输出优化的
.engine文件,包含最终网络权重和 kernel 代码。
提升幅度
相较于 PyTorch/TensorFlow 等框架的直接推理,TensorRT 的吞吐量通常能提升 2~5 倍(FP16/INT8 甚至 10 倍以上)。具体增益取决于模型架构、batch size 和目标 GPU。小 batch size 下内存延迟优化效果显著;大 batch size 下计算优化与 Tensor Core 利用率更重要。同时显存占用也会大幅降低。
ONNX 在模型部署中的作用是什么?遇到不支持的算子怎么办?¶
ONNX 的作用
ONNX (Open Neural Network Exchange) 是一种开放的模型表示格式,它提供:
-
互操作性:可将 PyTorch、TensorFlow、Keras 等训练的模型导出为 ONNX,然后在多种推理引擎(ONNX Runtime、TensorRT、OpenVINO、CoreML、NCNN、MNN 等)中运行。
-
图优化基础:许多编译器接受 ONNX 作为输入,进行高级优化并生成不同硬件的代码。
-
硬件抽象:屏蔽训练框架差异,使模型轻松移植到不同平台(CPU、GPU、NPU、FPGA)。
遇到不支持算子的解决办法
-
用支持的等效算子替换:修改原始模型定义,将自定义或冷门算子用标准 ONNX 算子组合实现。
-
自定义算子插件:ONNX 和多数运行时支持扩展自定义算子,可注册一个算子并提供目标平台上的实现(如 ONNX Runtime 的动态库)。
-
ONNX 函数:利用 ONNX 的函数机制将复杂算子的数学定义表示为基本算子的子图,无需编写 C++ 插件。
-
使用较高 opset 版本:PyTorch
torch.onnx.export可指定 opset,高版本支持更多算子,尽量使用较新版本。 -
框架专有转换路径:如仅部署于 NVIDIA,可直接用 Torch-TensorRT 绕过 ONNX,从而利用所有算子。
-
回退到原生执行:部分平台允许在图中保留少量未转换的原生代码,但会失去可移植性。
大多数常用模型(CNN、Transformer)的算子已广泛支持,遇少数不支持时优先考虑标准化替换。
如何将 PyTorch 模型转换为可在移动端运行的格式?整体流程是怎样的?¶
整体流程
-
模型准备与优化(可选) 在服务器端应用剪枝、蒸馏等压缩技术得到轻量学生模型。
-
导出中间格式
- TorchScript:通过
torch.jit.trace或torch.jit.script导出为model.pt,可直接用于 PyTorch Mobile 或作为进一步转换的输入。 -
ONNX:使用
torch.onnx.export导出为.onnx,它是多数移动框架通用的导入格式。 -
模型转换 使用目标移动推理框架的工具链将 TorchScript/ONNX 转换为专用格式:
- NCNN:
onnx2ncnn工具 →.param与.bin - MNN:
MNNConvert→.mnn - TNN:相应转换器
- TensorFlow Lite:通过 ONNX→TF 或直接转换
- Core ML:
coremltools转换 -
PyTorch Mobile:直接使用
.pt -
模型量化(推荐) 移动端通常进行 INT8 训练后量化或量化感知训练。MNN、NCNN 等提供内置量化工具,可将 FP32 模型量化为 INT8 以减少体积和加速。
-
验证与测试 在移动模拟器或真机上测试精度与性能(延迟、内存),必要时调整优化选项。
-
集成部署 将模型文件打包入 App,使用框架 SDK 加载、执行推理,并编写前后处理代码。
技术栈示例:PyTorch → ONNX (opset 11) → NCNN/MNN → Android (JNI) / iOS (Objective-C++)。
移动端推理框架如 NCNN、MNN 有什么特点?它们如何优化卷积?¶
特点
-
无外部依赖、体积极小:纯 C++ 实现,不依赖 BLAS,包体积仅数百 KB,极易跨平台编译。
-
ARM CPU 深度优化:大量使用 NEON 汇编指令向量化,并针对不同 Cortex-A 核心调优。
-
高效内存管理:内存池技术,减少分配/释放开销,降低峰值内存。
-
异构计算支持:提供 OpenCL/Vulkan GPU 加速,MNN 还支持部分 NPU 后端。
-
兼容主流模型结构:覆盖 CNN、RNN、Transformer 等,视觉模型优化尤其成熟。
卷积优化手段
-
Im2Col + GEMM:将卷积转为矩阵乘法,调用手写 NEON 汇编 GEMM,移动端最主流方法。
-
Winograd 卷积:针对 3×3 stride 1 卷积,乘法次数减少约 2.25 倍,配合 NEON 实现。
-
直接卷积:对小核小 batch 场景,直接在循环中展开并用 NEON 向量化,避免 im2col 额外内存开销。
-
深度可分离卷积专项优化:对 Depthwise 卷积单独做内存融合与 NEON 加速,因其访存密集。
-
权重重排与内存对齐:将权重预变换为推理友好布局,并 128-bit 对齐,提升缓存与 SIMD 效率。
-
算子融合:Conv+BN+ReLU 直接合并为一个 kernel。
这些优化使复杂模型也能在移动 CPU 上达到实时推理。
什么是模型剪枝、量化、蒸馏的组合使用?如何进行精度和速度的均衡?¶
组合使用
三种技术分别从不同维度压缩模型:
-
蒸馏:大教师模型教导小模型,直接减少模型容量与计算量。
-
剪枝:在蒸馏得到的学生模型上进一步结构化剪枝,去掉冗余通道/层。
-
量化:将剪枝后模型的 FP32 参数转为 INT8/FP16,再次加速并减小体积。
典型组合流程
大模型 → 知识蒸馏获得紧凑学生 → 结构化剪枝进一步减少计算 → 微调恢复精度 → 训练后量化/量化感知训练 → 部署。
精度与速度均衡
-
蒸馏阶段确定基线模型大小与精度。
-
剪枝阶段采用渐进式迭代剪枝,每次剪掉少量参数并微调,监控验证精度。若精度下降至阈值,停止剪枝或减小剪枝率。
-
量化阶段选择量化精度(FP16/INT8/INT4)。对敏感层保留较高精度(混合精度量化)。若 PTQ 导致精度超损,可改用 QAT 恢复。
-
可在整个流程中自动搜索:设定延迟/内存目标,利用超参数搜索或 NAS 技术寻找最优的组合配置。
-
快速评估循环:每次压缩后评测,平衡延迟与精度,直至满足业务指标。
最终在一个资源限制内得到最佳的精度-效率帕累托最优解。
结构化稀疏是否可以用于 Transformer?如 2:4 稀疏模式,有什么硬件支持?¶
可以,结构化稀疏非常适合 Transformer 的矩阵乘法层。
2:4 稀疏模式
-
在权重矩阵中,每 4 个连续元素为一组,每组至少 2 个为零,形成 50% 稀疏度。剩余 2 个非零值与索引被压缩存储。
-
Transformer 的 FFN、注意力 QKV 投影等均为全连接层,可应用 2:4 稀疏。训练或微调时对权重施加掩码,使模型适应这种稀疏结构。
硬件支持
-
NVIDIA Ampere 架构(A100、RTX 30 系列)引入了稀疏张量核,能直接利用 2:4 结构化稀疏对矩阵乘法进行加速,实际吞吐提升约 1.5~2 倍。
-
后续架构(Hopper、Ada Lovelace)继续支持。
-
PyTorch +
torch.cuda.amp结合 DeepSpeed 或 ASP 工具可训练 2:4 稀疏模型,TensorRT 也能部署并加速这类稀疏模型。
2:4 稀疏是当前在 GPU 上实现 Transformer 加速的高效结构化稀疏方案。
在推理服务中,如何利用动态批处理(Dynamic Batching)提高 GPU 利用率?¶
动态批处理将来自多个客户端的小请求组合成 batch 一起推理,以充分利用 GPU 并行算力。
工作原理
-
请求入队后不立即处理,而是等待一个短暂的时间窗口(如 1~5 ms)或直到积压请求数达到一定阈值。
-
将窗口内收集的所有请求输入组合成一个 batch,进行单次前向计算。
-
输出结果拆解后分别返回给对应客户端。
提高 GPU 利用率的原因
-
单个小请求无法填满 GPU 计算单元,kernel 启动和内存延迟占比高。合并为大批量张量运算能充分发挥 GPU 的高吞吐和带宽优势。
-
大幅减少 kernel 启动次数。
-
在未优化时 GPU 利用率可能仅 10%~30%,引入动态批处理后可达 80% 以上,吞吐量提升数倍,单位推理成本明显降低。
实现注意事项
-
延迟权衡:等待时间越长 batch 越大,吞吐越高,但单个请求延迟增加,需根据 SLA 设定最大等待时间。
-
形状统一:不同请求输入尺寸各异,需填充或使用 bucket 分组(将相似长度请求组 batch)以减少无效计算。
-
推理服务器(NVIDIA Triton、TorchServe)内置动态批处理器,可配置最大 batch size 和最大延迟。
什么是模型热更新?推理服务如何在不中断的情况下更换模型?¶
模型热更新 指不停止服务、不丢失请求的情况下,用新版本模型替换旧模型。
实现方案
-
多模型副本切换(Blue/Green) 同时加载新旧模型副本,初始流量指向旧模型;新模型就绪后通过配置切换流量到新模型。旧模型保留一段缓冲期以备回滚。
-
推理服务器的版本管理(Triton, TorchServe)
- 上传新版本模型文件,服务器后台异步加载。
- 加载完成后可配置为“立即切换”或“等待旧请求完成再切换”。新请求使用新模型,进行中的老请求继续服务。
-
旧模型随后卸载。
-
容器化滚动更新(Kubernetes)
- 更新模型镜像或挂载的新权重,执行 Rolling Update。
-
新 Pod 启动就绪,旧 Pod 逐步终止,负载均衡器将流量平滑迁移,实现无中断。
-
进程内热重载 自定义服务监听信号,重新加载权重并重建计算图,原子替换旧模型指针,不重启进程。需精细管理内存,避免泄漏。
核心:加载新模型与卸载旧模型的时机配合,配合流量切换,确保请求零丢失。
解释模型在 CPU 和 GPU 上推理的瓶颈差异,如何针对性优化?¶
CPU 推理瓶颈与优化
-
瓶颈特点:单核算力有限,大模型权重加载易成 memory-bound(内存带宽瓶颈)。纯计算密集型算子执行慢,但常受限于标量吞吐。
-
优化方向:
- SIMD 指令集:AVX-512、ARM NEON 向量化。
- 低精度量化:INT8 权重和激活,降低带宽压力并利用 VNNI 等指令加速整数计算。
- 算子融合:减少中间数据读写和开销。
- 多线程并行:OpenMP 或线程池并行化 batch 维度或层内计算。
- 内存布局转换:调整为 cache-friendly 的格式,提高缓存命中。
- 高效 BLAS 库:Intel MKL、OpenBLAS。
- 移动端使用 NCNN/MNN 等框架。
GPU 推理瓶颈与优化
-
瓶颈特点:小 batch/小模型时 memory-bound 或 kernel launch bound;大 batch 时 compute-bound,需充分利用 Tensor Core。显存容量限制最大模型。
-
优化方向:
- 动态批处理 提高算力利用率。
- FP16/INT8 推理 + Tensor Core 加速。
- 算子融合 和 CUDA Graph 降低 launch 开销。
- 高效显存管理:预分配、内存池、KV 缓存、激活重计算等。
- 多流并行 处理不同请求或重叠计算与数据传输。
核心差异:CPU 侧重降低带宽和向量化;GPU 侧重提升占用率、利用专用硬件单元和降低调度开销。
对于生成式模型,KV 缓存是什么?它在推理加速中有何作用?(可结合 Transformer)¶
KV 缓存 是自回归 Transformer 解码时用于避免重复计算历史 token 的 Key 和 Value 的优化技术。
原理
-
在自回归生成第 t 个 token 时,传统做法需将所有 t−1 个历史 token 重新输入模型,计算它们的 K 和 V。
-
KV 缓存将已生成 token 的 Key 和 Value 向量存储在各解码器层。生成新 token 时,仅需计算该新 token 的 Q、K、V,并将新 K、V 追加到缓存。注意力计算时,Q 仅来自当前 token,K 和 V 来自缓存(包含全部历史 token)。
加速作用

相关优化
-
Multi-Query Attention (MQA) 和 Grouped-Query Attention (GQA) 减少 KV 头数,降低缓存大小。
-
PagedAttention (vLLM) 将 KV 缓存分页管理,提升显存利用率。
-
量化 KV 缓存为 INT8 或 FP8 进一步压缩。
如何利用多模型级联(Cascade)来降低推理成本?¶
多模型级联指根据样本难易程度,先用轻量模型处理,只在必要时才调用重模型,从而节省计算资源。
级联策略
-
置信度阈值:小模型推理并输出置信度,高于阈值则直接采纳;否则送大模型。常用于图像分类、文本分类。
-
多阶段检测:快速粗检测 + 精细验证(人脸、目标检测)。
-
早退机制:同一模型不同深度设多个出口,浅层若置信度够高则提前终止推理。
-
多分辨率级联:先在小图上用轻量网络,不确定时再用原图大网络。
降低成本的表现
-
假设 80% 简单请求被轻模型处理,只有 20% 调用重模型,平均算力消耗降至约 0.2×重模型 + 轻模型,总吞吐大幅提升,所需 GPU 数量减少。
-
边缘设备可将小模型本地处理,难例上传云端,节省带宽和云端成本。
需权衡置信度阈值:过高则重模型调用比例上升,过低则错误率上升。
解释模型量化中的“校准”(Calibration)过程,常用方法有哪些(MinMax, KL 散度等)?¶
校准是训练后量化(PTQ)的关键步骤,通过少量无标签数据统计激活值的动态范围,以确定各层的量化尺度与零点,使低精度运算保留尽可能多的信息。
校准过程
-
准备数百至数千张有代表性的校准样本。
-
在待量化的 FP32 模型中插入观察器(Observer)来收集各层激活的分布。
-
运行若干批校准数据,观察器记录张量值的 min/max 或直方图。
-
根据选定的校准算法计算每层的量化参数(scale, zero point)。
-
利用这些参数导出低精度模型。
常用校准方法
-
MinMax:直接使用最大值和最小值(或绝对值最大值)定义量化范围。简单,但易受离群值影响,导致有效分辨率降低。
-
移动平均 MinMax:多个 batch 间指数平滑 min/max,稍微提高鲁棒性。
-
百分位数(Percentile):取历史值分布的 99.99% 或其他百分位为截断点,丢弃极端离群值。
-
KL 散度校准(NVIDIA 推荐):将 FP32 激活的直方图作为参考分布 P,尝试不同截断阈值,比较 INT8 量化后分布 Q 与 P 的 KL 散度,选择使 KL 散度最小的截断阈值。能在抑制离群值的同时最大限度地保留分布信息。
-
MSE 校准:直接最小化量化前后张量的均方误差,搜索最佳截断阈值。
KL 散度校准是目前主流且效果较好的方法,TensorRT 等工具默认采用。