作为一名长期从事深度学习部署的工程师,我经常遇到模型量化落地的实际问题。今天要分享的是基于TensorRT INT8量化的完整工程化方案,特别适合需要在嵌入式设备(如RK3588)上部署模型的开发者。这个方案已经在我们多个工业级项目中验证过,从算法到部署全链路打通。
INT8量化是模型加速的重要手段,但真正落地时会遇到校准集选择、精度损失控制、工程化封装等一系列问题。本文将结合CMake工程化管理,展示一个可复用的量化部署流程。我们以YOLOv5目标检测为例,但方法论适用于大多数CNN模型。
模型推理时,float32计算对嵌入式设备来说存在两个痛点:
实测表明,在RK3588上:
TensorRT的INT8量化属于动态量化,即根据实际输入数据动态确定各层的scale值。核心步骤:
注意:校准集必须覆盖实际场景的数据分布。我曾用纯白天数据校准,导致夜间推理完全失效。
对于精度敏感的场景,建议先做QAT再导出ONNX:
python复制model = torch.quantization.quantize_dynamic(
model, {torch.nn.Linear}, dtype=torch.qint8
)
这样训练时模型会模拟量化误差,提升最终INT8精度。
标准化的工程目录:
code复制project/
├── CMakeLists.txt
├── include/
│ └── tensorrt_wrapper.h
├── src/
│ ├── calibrator.cpp # 量化校准器
│ └── inference.cpp # 推理引擎
└── tools/
├── calibrate.py # 校准数据生成
└── eval_accuracy.py
关键CMake配置:
cmake复制find_package(TensorRT REQUIRED)
add_library(trt_inference SHARED src/inference.cpp src/calibrator.cpp)
target_link_libraries(trt_inference ${TensorRT_LIBRARY})
继承IInt8EntropyCalibrator2的C++实现:
cpp复制class Calibrator : public nvinfer1::IInt8EntropyCalibrator2 {
public:
Calibrator(const std::string& calib_data_path) {
// 加载校准图像到buffer
}
bool getBatch(void* bindings[], const char* names[], int nbBindings) override {
if (current_idx >= total_images) return false;
// 填充当前batch数据到bindings
return true;
}
};
完整流程代码:
cpp复制auto builder = std::unique_ptr<nvinfer1::IBuilder>(...);
auto network = std::unique_ptr<nvinfer1::INetworkDefinition>(...);
auto parser = std::unique_ptr<nvonnxparser::IParser>(...);
// 设置INT8模式
builder->setInt8Mode(true);
builder->setInt8Calibrator(calibrator);
// 构建优化引擎
auto config = std::unique_ptr<nvinfer1::IBuilderConfig>(...);
config->setFlag(nvinfer1::BuilderFlag::kINT8);
auto engine = std::shared_ptr<nvinfer1::ICudaEngine>(
builder->buildEngineWithConfig(*network, *config)
);
当遇到量化后精度下降严重时,可尝试:
cpp复制layer->setPrecision(nvinfer1::DataType::kHALF);
cpp复制context->enqueueV2(buffers, stream, nullptr);
createExecutionContextWithoutDeviceMemory减少内存拷贝在RK3588上测试YOLOv5s:
| 模式 | 推理时延 | mAP@0.5 |
|---|---|---|
| FP32 | 45ms | 0.874 |
| INT8(常规) | 22ms | 0.862 |
| INT8(QAT) | 25ms | 0.871 |
经验:对于检测任务,建议接受1-2%的mAP损失换取速度提升;分类任务可考虑QAT。
现象:Error Code 4: Internal Error (Calibration failure)
排查:
现象:量化后检测框全乱
解决步骤:
cpp复制network->getOutput(0)->setType(DataType::kFLOAT);
trtexec工具验证引擎正确性这个方案已经成功应用于智能安防、工业质检等多个项目。实际部署时,建议先用少量设备试运行24小时,监控精度波动情况。