推理引擎
推理引擎
推理系统与推理引擎
训练和推理服务
推理和训练的区别:
- 模型部署后,长期运行;
- 不需要反向传播;
- 部署设备更加多样。
推理服务系统的功能(与 AI 算法关系不大,更多地是平台性的工作):
- 模型加载;
- 版本管理;
- 数据管理;
- 服务接口。
优化目标
- 低延迟;
- 高吞吐:高负载;
- 高效率:低功耗使用 CPU/GPU;
- 灵活性:支持多框架;
- 扩展性。
部署态
场景:数据中心的服务端、边缘侧的移动端。
- 云端;
- 边侧:严格约束功耗、算力不足、数据分散、平台多样化。
推理系统架构
推理服务化、推理服务框架。
基本概念:
- 推理:前向计算;
- 部署:将模型部署到硬件上,包括:移植、压缩、加速等;
- 服务化:将模型封装为 sdk 或 web 服务。
Triton 服务化框架:
- 接入层:HTTP、gRPC、CAPI;
- 模型仓库;
- 模型预编排:解析 URL 请求;
- 框架后端:指推理引擎(如 TensorRT、ONNX Runtime、MindSpore Lite 等);
- 监控功能:健康管理。
模型版本管理
模型生命周期管理:
- 金丝雀策略(Canary);
- 回滚策略(Rollback)。
推理引擎介绍
特点:
- 高性能:充分发挥芯片算力;
- 轻量化:端侧部署(手机、手表);
- 通用性:支持多种主流模型文件格式、主流网络结构、嵌入式设备、操作系统;
- 易用性:提供丰富的 API。
技术挑战:
- 需要适配不同 AI 框架的大量算子;
- 需要深入优化计算资源的性能;
- 需要端侧的模型变小(压缩),但精度保持不变(有限的精度损失)。
推理引擎架构
- API 接口;
- 模型格式转换、图优化;
- 模型压缩:量化、蒸馏、剪枝、二值化;
- 端侧学习:联邦学习、增量学习;
- 其它:性能测试等;
- IR/Schema:中间表达(推理引擎自己的模型格式、计算图?);
- Runtime:模型加载、模型执行,功能包括:动态 Batch、内存分配、大小核调度;
- 高性能算子层(Kernel 层):算子优化、算子执行、算子调度。
推理流程
- 模型转换:将多种 AI 框架训练得到的模型转换为推理引擎所需的格式,得到推理模型;
- 对推理模型进行模型压缩;
- 准备环境:拉取模型等;
- 开发/编译推理程序:
- 模型离线转换;
- 推理配置管理:模型路径、运行 Kernel、优化选项;
- 调用推理引擎:图优化、算子融合、内存优化;
- 执行推理过程。
- 执行推理:在推理引擎的 Runtime 中运行模型。
模型压缩
模型压缩的好处
- 减少模型大小:节省内存;
- 加快训练速度;
- 保持相同精度。
模型量化
模型量化:将浮点计算转成低比特定点计算(FP32/FP16 -> INT16/INT8/INT4),可以有效降低模型的计算强度、参数大小和内存消耗,但往往带来精度上的损失。
量化方法:
- 量化训练(感知量化,QAT):让模型感知量化运算对模型精度带来的影响,使用大量带标签的数据进行 finetune;
- 动态离线量化(动态训练后量化,PTQ dynamic):仅将模型中特定算子的权重从 FP32 映射成 INT8/16;
- 静态离线量化(静态训练后量化,PTQ static):使用少量无标签的数据进行校准。
量化的原理:在定点与浮点之间建立数据映射关系,以较小的精度损失为代价获得较好的收益。
量化的类型:
- 对称量化:-127 ~ 127;
- 非对称量化:0 ~ 255。
模型小型化
推理参数介绍
- FLOPs(浮点运算次数):计算量,用于衡量算法/模型的时间复杂度;
- FLOPS(每秒执行的浮点运算次数):计算速度,用于衡量硬件性能(芯片算力)/模型速度;
- MACCs(乘加操作次数):大约是 FLOPs 的一半;
- Params(模型参数数量):单位是 M,训练时参数通常使用 float32,因此模型大小是参数数量的 4 倍;
- MAC(内存访问代价):单个样本完成一次前向传播所需的内存交换总量,用于衡量模型的空间复杂度,单位是 Byte;
- 内存带宽:将数据从内存移动到计算核心的速度。
Transformer 小型化
…
Kernel 优化
Kernel 层
Kernel 层:高性能算子层,供 Runtime 调度。
- 人工高性能算子;
- 高性能算子库。
Img2Col 算法
算法原理:对 kernel 和 input 数据进行重新排列,从而将卷积操作转换为矩阵相乘。具体地,将输入数据按卷积窗进行展开,并存储在矩阵的列中,多个通道的数据展开后拼接到矩阵的同一列中。最后,直接使用 GEMM 将两个矩阵相乘,得到输出矩阵。
- 优点:高性能矩阵乘法库;
- 缺点:多余的内存开销。
空间组合优化
算法原理:将大卷积计算拆分为若干个小卷积进行计算,计算总量不变,但计算小矩阵时,访存局部性更好,从而获得性能上的提升。
推理内存布局
Tensor 内存布局:
- NCHW:以 GPU/NPU 为基础的 PyTorch 和 MindSpore 框架默认使用该格式,更适合并行操作,适合对每个通道单独做运算的操作(如 MaxPooling);
- NHWC:推理引擎(大多以 Arm CPU 作为主要的计算单元)大多使用该格式,适合对不同通道的同一像素做某种运算的操作(如 Conv);
- NCHWX。
模型转换与图优化
挑战 & 目标
推理引擎中模型转换模块的挑战:
- 需要有自己的算子定义和格式,来对接不同 AI 框架的算子层;
- 需要有自定义的计算图 IR,来对接不同 AI 框架的计算图(对接多种文件格式);
- 需要有丰富的 Demo 和 Benchmark,来为主流的模型(网络结构)提供性能和功能基准;
- 需要有良好的可扩展性,来支持多种 AI 特性。
推理引擎中优化模块的挑战:
- 结构冗余:如无效的计算节点、重复的计算子图、相同的结构模块,去除冗余的同时保持计算图语义 -> 计算图优化:算子融合、算子替换、常量折叠等;
- 精度冗余:压缩精度 -> 模型压缩:低比特量化、剪枝、蒸馏等;
- 算法冗余:算子或 kernel 层面的算法本身冗余 -> 统一算子/计算图表达:kernel 提升泛化性;
- 读写冗余:重复读写内存 -> 数据排布/内存分配优化。
架构与流程
转换模块(Converter)架构:
- Graph Converter(Frontends):负责支持不同的 AI 训练框架;
- Graph Optimize:通过算子融合、算子替代、布局调整等方式优化计算图。
转换流程:
- 多种 AI 训练框架的模型格式,通过 Converter 转换为统一的 Inference IR,后续基于该 IR 进行图优化;
- Pre Optimize:公共表达式消除、死代码消除、代数简化;
- Optimize:算子融合、算子替换、常量折叠;
- Pos Optimize:数据格式转换、内存布局计算、重复算子合并。
模型格式转换
- 模型序列化:将训练好的模型存储起来;
- 模型反序列化:将硬盘中的二进制数据反序列化到内存中,得到模型对应的内存对象。
PyTorch 模型序列化(模型导出):torch.onnx.export()。
目标文件格式:ProtoBuffer/FlatBuffer(推理引擎使用较多)。
自定义计算图
计算图的基本组成:
- 基本数据结构:Tensor(张量);
- 基本运算单元:Operator(算子);
- 控制流。
不同计算图的区别:
- AI 框架:前向传播+反向传播、动态图+静态图、支持分布式并行;
- 推理引擎:反向传播、静态图为主、单卡推理为主。
张量的定义:
- 数据维度(shape);
- 数据内存排布格式;
- 数据类型。
算子的定义(不同框架可能不同):
- 输入数据;
- 输出数据;
- 算子公共属性和参数;
- 算子类型;
- 算子名称。
计算图的定义:
- 网络模型:模型名称、输入 Tensor 名称、输出 Tensor 名称、算子列表、子图列表等;
- 网络模型子图:子图名称、输入、输出、Tensor、节点(算子列表)等。
模型转换流程
- AI 框架:生成计算图;
- Converter:算子对接;
- Converter:格式转换;
- Converter:模型保存与导出。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 xhj的博客!