BM1684X上将YOLOv8量化为INT8BModel
本文由AI辅助编写
为了把YOLOv8部署到BM1684X,这次使用TPU-MLIR完成了从ONNX到BModel的转换。F16模型可以直接编译,INT8则要多做一次校准;全INT8精度不理想时,再用qtable把敏感层保留为浮点计算。
这次只转换了少量模型,目标是跑通工具链并比较F16和INT8,没有覆盖其他检测、跟踪和人脸模型。TPU-MLIR版本当时没有记录,命令中的参数应以所用SDK附带的文档为准。
参考
从ONNX生成MLIR
先准备固定输入尺寸的ONNX模型、一张测试图片和校准图片目录,工作目录使用以下名称:
1 | workspace/ |
转换时把YOLOv8的0~255RGB输入缩放到0~1,并生成后续比对需要的测试结果:
1 | model_transform.py \ |
这里的预处理必须和训练、ONNX推理及最终应用保持一致。--keep_aspect_ratio会在缩放时保留宽高比并补边;如果原来的推理代码采用直接拉伸,这个参数也要随之调整,不能只照搬示例。
命令还会生成detector_in_f32.npz,它是同一张测试图片经过预处理后的输入,后面的F16和INT8编译都用它做数值比对。
先生成F16基线
F16不需要校准表,可以直接从MLIR生成BM1684X使用的BModel:
1 | model_deploy.py \ |
先保留F16结果很有必要。它既是部署候选,也能把“模型转换本身的问题”和“INT8量化带来的误差”分开。
可以用model_runner.py检查BModel输出:
1 | model_runner.py \ |
model_deploy.py的相似度检查和输出张量统计只能发现明显的数值异常,不能代替完整数据集上的mAP、Precision和Recall评估。
生成校准表和INT8模型
这次探索使用了100张校准图片:
1 | run_calibration.py detector.mlir \ |
校准图片应来自实际输入分布。100张只是这次跑通流程时的取值,不是固定标准;TPU-MLIR当前文档给出的常见范围是100至1000张,正式模型仍要根据数据复杂度和精度结果调整。
使用校准表生成全INT8对称量化模型:
1 | model_deploy.py \ |
--tolerance控制转换过程中的相似度检查门限,不代表最终检测精度。模型成功生成之后,仍要使用带标签的数据集进行评估。
全INT8不够时使用混合精度
TPU-MLIR用qtable记录哪些算子保留为F32、F16或BF16。当前版本能够为YOLO结构自动识别部分不适合INT8的后处理算子,也可以通过search_qtable继续搜索敏感层。
搜索命令同时指定校准表和qtable的输出名称,避免后续部署时串错文件:
1 | run_calibration.py detector.mlir \ |
不同TPU-MLIR版本对搜索后更新校准表的文件名处理并不完全一致。有的版本会另外生成new_cali_table.txt,因此下一步不能凭文件名猜测:先查看搜索日志,确认最终qtable和更新后校准表的实际路径,再传给model_deploy.py。
1 | SEARCH_CALI_TABLE=new_cali_table.txt |
部署阶段如果引用了另一个临时qtable文件,命令仍可能成功,却不能证明模型使用的是刚完成搜索的配置。这里最好统一命名,并在编译前查看两个表的路径和内容。
这次的精度和耗时
同一检测模型的测试结果如下。数据集规模、TPU-MLIR版本和板卡运行状态没有完整记录,所以只比较这组测试内部的相对变化。
| 模型 | mAP@0.5 | mAP@0.5:0.95 | Precision | Recall | F1 | 推理(ms) | 换算FPS |
|---|---|---|---|---|---|---|---|
| BModel FP32 | 0.9439 | 0.6620 | 0.9043 | 0.9699 | 0.9359 | 38.0 | 26.4 |
| BModel F16 | 0.9440 | 0.6620 | 0.9037 | 0.9699 | 0.9356 | 14.1 | 71.1 |
| BModel INT8方案A | 0.9156 | 0.6128 | 0.8864 | 0.9706 | 0.9266 | 11.6 | 86.5 |
| BModel INT8方案B | 0.9242 | 0.6250 | 0.9008 | 0.9671 | 0.9328 | 11.5 | 86.7 |
| BModel INT8自动pattern | 0.9242 | 0.6250 | 0.9008 | 0.9671 | 0.9328 | 11.6 | 86.6 |
F16相对FP32把推理耗时从38.0ms降到14.1ms,精度指标基本不变。三份INT8结果的耗时都在11.5ms左右,其中方案B和自动pattern的mAP@0.5为0.9242,比F16低0.0198;F1只低0.0028。
方案A和方案B对应两次混精度调整,但当时没有把具体qtable差异记录下来,无法从结果反推出是哪几层带来了改善。自动pattern与方案B得到相同精度,说明在这个模型上没有必要仅为了“手工调过”而保留更复杂的配置。
现有结果足以支持继续使用F16,并把INT8作为有条件的优化选项。真正上线INT8之前,还需要在目标板卡上用真实图片复查预处理、后处理和检测结果;这部分当时没有完成,不能把转换成功直接当成部署验证通过。