Press "Enter" to skip to content

PPQ ~ OpenPPL 之多平台量化部署工具来啦!

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

 

深度学习模型部署过程中,我们希望可以快速地对模型进行压缩和推理加速,离线量化是一种常用的压缩加速方法。

 

各硬件厂商纷纷推出了自家的 INT8 推理库和对应的离线量化工具,然而自带的量化工具所支持的平台较为单一,无法迁移至其他平台,并且时常会伴随着量化精度损失。

 

由于推理库的量化细节未知,「黑盒」平台的量化精度修复,是一个「痛苦」的踩坑过程。
只有推理库的量化细节和量化模拟器对齐,才能更好地发挥量化算法的价值。

 

OpenPPL 团队一直致力于异构平台的推理加速,我们已经支持 Turing 系列显卡和多种 DSP 的 INT8 量化推理。面对大量模型的多平台量化部署需求,一款支持多平台量化部署的工具必不可少,PPL Quantization Tool (PPQ) 应运而生。

 

PPQ 支持多平台量化模拟、量化误差分析和量化优化。目前已开源,点击文末「
原文链接
」直达 GitHub。

 

本文将从以下方面对其进行介
绍:

 

 

量化基本概念

 

量化工具框架

 


化图调度

 

量化联合定点与图融合

 

量化工具上手指南

 

 

一、量化概述

 

量化是指将连续的信号取值,离散化为有限个取值的过程。
深度学习模型量化是使用低比特定点数表征模型浮点参数的压缩方法。

 

我们以线性量化的 conv 计算为例,详细说明量化计算的流程。
线性量化的数学表达如下:

 

 

 

 

 

对于模型 weight 而言,可以离线标定其数值范围,而模型 activation 数值范围,则需要少量标定集进行统计。

 

基于上述公式,可以将模型浮点参数量化成为整型参数。线性量化 Conv 的计算流程如下:

 

 

 

 

 

int8 输入与 int8 权重卷积运算后,累加至 int32,乘以 fp32 的 s_w 和 s_x 进行解量化,再与 fp32 bias 相加,最后进行输出量化;若部署平台不支持 fp32 的 scale 进行解量化,则会将 (s_w * s_x / sy) 近似为整数乘法和位移代替(或者将 scale 近似为 power of two 的形式),并累加量化的 bias,最后将 int32 中间结果直接 requantize 至 int8 输出。

 

量化推理过程中,为避免不必要的数据转换开销,应量化将尽可能多的层。

 

二、量化工具框架

 

 

 

△ PPQ 框架图

 

PPQ Paser 模块
可读取 onnx 或 caffe 模型,并解析成内部格式。
解析完成后,Scheduler
模块对模型进行切分与调度,粗颗粒度地划分量化与非量化算子。

 

Quantizer 模块
是 PPQ 量化执行的中枢,为模型算子分配特定的部署平台,并初始化量化设置,调用各种优化 Pass,完成量化联合定点、图融合及量化优化。

 

Executor 模块
依据模型拓扑关系,调用底层算子实现,执行前向推理。
模型量化完成后,调用 Exporter 模块,导出模型和量化参数。

 

三、量化工具图调度

 

执行量化前,我们应首先划分模型的可量化区和不可量化区。

 

单一的根据算子类型来判断是否量化是不合理的,
因为训练框架的模型转换成 onnx 模型时,大量程序逻辑被转换成细碎的 onnx 算子实现。
比如分类模型和检测模型的前处理部分,经常出现 Shape 相关算子,用于获取动态输入的相关信息;
而检测模型的后处理部分则存在大量争议算子。
如下图所示。

 

 

 


PPQ 图调度

 

PPQ 使用 graph dispatcher 将图中所有算子划分为三类:

 

不可量化区:
这区域的算子与 shape或者 index 有关,一旦量化将导致图的计算发生错误,因此不可量化,同时默认被调度到 Host 端以浮点精度执行。

 

可量化区:
这区域的算子被认为是可以量化的,它们是 input, conv, gemm 的延伸算子,PPQ 使用数值追踪技术标记这些算子,这些算子处理的运算一定是 input, conv, gemm 的计算结果。
它们被调度到设备端以 int8 精度执行。

 

争议区:
这区域的算子同时接收来自不可量化区以及可量化区的输入,所有争议区的算子延伸也是争议算子,量化这些算子是有风险的,PPQ 不能保证量化产生的影响。
该区算子被调度到设备端以浮点精度执行。

 

为了找出这些区域,PPQ 使用图搜索引擎进行区域划分,其基本思想是通过枚举所有算子的计算情况,确定输入的来源是否与 shape 或 index 相关。
你可以通过  ppq.scheduler 中的代码看到它们的具体实现。

 

在 PPQ 中,我们实现了三种不同的调度逻辑,不同的调度逻辑将产生不同的区域划分:

 

激进式调度:
该调度方法将所有争议区算子视作可量化的。

 

保守式调度:
该调度方法将所有争议区算子视作不可量化的(它们依然将被调度到设备端)。

 

pplnn:
该调度方法只量化
卷积层与其相关算子。

 

对于 mask_rcnn 这样的复杂网络结构来说,我们推荐你尝试使用保守式调度或 pplnn 调度方式。对于复杂检测网络而言,量化其后处理算子是风险的,可能导致网络精度大幅下降。

 

四、量化联合定点与图融合

 

量化部署过程中,时常遇到量化模拟器与硬件精度不对齐的问题,这也是量化部署非常令人「头疼」的问题。

 

硬件精度未对齐的主要原因
在于
—— 推理库后端会对模型做大量的联合定点和图融合优化,我们写入的量化参数已被后端融合或修改,量化模拟与后端推理并不一致,导致优化算法大打折扣。

 

常见的融合操作包括 Conv-Relu 融合、Conv-Add 融合与 Conv-Clip 等;而对于一些非计算算子,如 Concat, Reshape, Slice, MaxPool 等,则需要输入输出联合定点,以避免不必要的 requantize 运算。

 

PPQ 可模拟常见的联合定点与图融合
,如下图所示:

 

 

 

PPQ 使用 Tensor Quantization Config 类来描述算子数值量化的细节,其绑定在算子之上。

 

Executor 模块执行每一个算子时,并不会在模型中插入量化节点,而是通过一种类似于 hook 的形式,直接将量化操作添加到算子的执行逻辑中。模型算子输入/输出变量是否量化,由算子输入/输出的 Tensor Quantization Config 的 state 属性决定。上图中灰色模块表示量化被融合或覆盖,未生效。

 

五、量化工具上手指南

 

我们为大家提供了极简的量化接口,你只需准备模型和标定数据,选定部署平
台 TARGET_PLA
TFORM,运行如下命令即可:

 

python ProgramEntrance.py

 

量化接口文件中,可选择是否进行量化误差分析、存储模拟量化中间结果,以及图融合、优化策略。

 

PPQ 完成量化后,输出量化后的模型和量化参数文件。目前 OpenPPL CUDA 已经支持 INT8 推理,小伙伴们只需在 PPQ 中选定 TargetPlatform.PPL_CUDA_INT8 部署平台,即可生成所需的量化文件,完成 CUDA INT8 的量化推理啦!

 

详情可参考:《OpenPPL CUDA 支持 INT8》

 

更多自定义量化平台的部署实践,我们将在后续教程中为大家详细介绍。

 

:star:️ 欢迎 star

 

:link:
https://github.com/openppl-public

 

Be First to Comment

发表评论

您的电子邮箱地址不会被公开。