一、 tensorRt量化
-
实际操作中,
input[float32], w[int8], bias[float32], output[float32]
-
具体操作如下:
input[int8] = to_int8(input[float32]) y[int16] = input[int8] * w[int8] # 此处乘法由计算机转换为int16,保证精度 output[float32] = to_float32(y[int16] + bias[float32])
-
整个量化过程只是为了减少float32的乘法数量以实现提速
-
对于to_int8过程,并不是直接线性缩放,而是使用KL散度进行阈值截断,使得量化前后权重的分布差异尽可能小。
二、构建模型的区别
1. config配置setFlag
```cpp
config->setFlag(nvinfer1::BuilderFlag::kINT8);
```
2. 配置int8标定数据读取工具:用于评估量化前后的分布改变
-
实现int8熵校准器(Int8EntropyCalibrator类),继承自属于nvinfer1的IInt8EntropyCalibrator2类,覆盖其中的一些函数,实现自己的需求
-
getBatchSize:告诉引擎,这次标定的batch大小
-
getBatch:告诉引擎,这次标定的输入数据是什么,把指针赋值给bindings,返回false说明已没有数据了
-
readCalibrationCache:从缓存文件中加载标定信息,抗压避免读取文件和预处理,若该函数返回空指针表示没有缓存,程序会重新通过getBatch进行计算
-
writeCalibrationCache:标定结束后,调用该函数,储存标定后的结果,多次标定可以使用该缓存实现加速
// int8熵校准器:用于评估量化前后的分布改变 class Int8EntropyCalibrator : public nvinfer1::IInt8EntropyCalibrator2 { public: Int8EntropyCalibrator(const vector<string>& imagefiles, nvinfer1::Dims dims, const Int8Process& preprocess) { assert(preprocess != nullptr); this->dims_ = dims; this->allimgs_ = imagefiles; this->preprocess_ = preprocess; this->fromCalibratorData_ = false; files_.resize(dims