这一节通过官方例程 介绍 INT8 inference mode.
例程位于 /usr/src/tensorrt/samples/sampleINT8
,是基于mnist的,大体流程是一致的。
流程同样是 build(Calibration )->deploy,只不过在build时多了一个校准的操作。
注意以下几点:
1 网络定义
定义网络时,注意这个地方传进去的dataType,如果使用FP16 inference 则传进去的是FP16,也就是kHALF;但如果是使用INT8 inference的话,这个地方传进去的是kFLOAT,也就是 FP32,这是因为INT8 需要先用FP32的精度来确定转换系数,TensorRT自己会在内部转换成INT8。
|
|
这个看起来就跟使用FP32是一样的流程,INT8 MODE inference的输入和输出都是 FP32的。
(After the network has been built, it can be used just like an FP32 network, for example, inputs and outputs remain in 32-bit floating point.)
2 校准网络-Calibrating The Network
校准网络时,比较麻烦的是校准集的构建,作者定义了一个BatchStream class来完成这个操作。BatchStream类有个成员函数getBatch ()是为了依次读取 batch file 中的数据的。
还有个校准类 Int8EntropyCalibrator,继承自 NvInfer.h 中的 IInt8EntropyCalibrator
|
|
这个类里面也有个 getBatch () 成员函数,实际上调用的是 BatchStream类的getBatch () ,然后将数据从内存搬到了显存,如下:
|
|
这个getBatch () 成员函数在校准时会被反复调用。
生成校准集时,校准集的样本应该是已经进行过一系列预处理的图片而不是原始图片。
校准类 Int8EntropyCalibrator 和 BatchStream 类的实现说起来比较麻烦,在后面源码解读部分直接结合注释看源码吧。
3 builder的配置-Configuring The Builder
只需要在原来builder的基础上添加以下:
|
|
4 batch file的生成-Batch Files For Calibration
例程使用的batch file 已经制作好了,位于<TensorRT>/data/mnist/batches
这是一系列二进制文件,每个文件包含了 N 个图片样本,格式如下:
- 首先是4个32 bit的整形值,代表 {N, C, H, W},batchsize和图片dims
- 然后是N个 {C, H, W}维度的浮点数据,代表N个样本
batch file二进制文件的生成有两种方式:
4.1 使用caffe生成
主要对于使用caffe的用户,这里干脆直接将官方文档上的说明拷贝过来好了,比较简单:
Navigate to the samples data directory and create an INT8 mnist directory:
1234 cd <TensorRT>/samples/datamkdir -p int8/mnistcd int8/mnist
>
Note: If Caffe is not installed anywhere, ensure you clone, checkout, patch, and build Caffe at the specific commit:
12345678910 git clone https://github.com/BVLC/caffe.gitcd caffegit checkout 473f143f9422e7fc66e9590da6b2a1bb88e50b2fpatch -p1 < <TensorRT>/samples/mnist/int8_caffe.patchmkdir buildpushd buildcmake -DUSE_OPENCV=FALSE -DUSE_CUDNN=OFF ../make -j4popd
>
Download the mnist dataset from Caffe and create a link to it:
12345 bash data/mnist/get_mnist.shbash examples/mnist/create_mnist.shcd ..ln -s caffe/examples .
>
Set the directory to store the batch data, execute Caffe, and link the mnist files:
1234567 mkdir batchesexport TENSORRT_INT8_BATCH_DIRECTORY=batchescaffe/build/tools/caffe test -gpu 0 -iterations 1000 -model examples/mnist/lenet_train_test.prototxt -weights<TensorRT>/samples/mnist/mnist.caffemodelln -s <TensorRT>/samples/mnist/mnist.caffemodel .ln -s <TensorRT>/samples/mnist/mnist.prototxt .
>
Execute sampleINT8 from the bin directory after being built with the following command:
12 ./sample_int8 mnist
4.2 其他方式生成
对于不用caffe或者模型难以转换成caffemode的用户,首先要进行一系列预处理,然后按照前面提到的batch file格式生成二进制batch file文件,但这个生成过程要自己写了,不过写的话应该也比较简单,可以参考caffe中的patch文件中的核心部分:
|
|
添加上数据集的读取,划分和预处理就可以了。
5 校准算法
从INT8的例程来看,TensorRT 支持两种方式的校准,一种就是上节我们讲过的使用相对熵的方式,还有一种是废弃的校准算法,校准时需要设置两个参数 cutoff 和 quantile,以下是 在GTC2017 上对INT8校准原理进行讲解的 Szymon Migacz 对废弃的校准算法的解读:
https://devtalk.nvidia.com/default/topic/1015108/cutoff-and-quantile-parameters-in-tensorrt/
Parameters cutoff and quantile have to be specified only for “legacy” calibrator. It’s difficult to set values of cutoff and quantile without running experiments. Our recommended way was to run 2D grid search and look for optimal combination of (cutoff, quantile) for a given network on a given dataset. This was implemented in sampleINT8 shipped with TensorRT 2.0 EA.
New entropy calibrator doesn’t require any external hyperparameters, and it determines quantization thresholds automatically based on the distributions of activations on calibration dataset. In my presentation at GTC I was talking only about the new entropy calibrator, it’s available in TensorRT 2.1 GA.
Szymon Migacz并没有充分的解释这两个参数,而是说这是 “legacy” calibrator中才会用到的参数,而且在没有做充分的试验的情况下,是很难合理地设置这两个参数的。他推荐的做法是 针对特定的网络结构和数据集使用 2D 网格搜索 来确定这两个参数的取值。而 entropy calibrator ,就是使用相对熵的校准方法,不需要任何超参数,而且能够根据校准集上的激活值分布自动确定量化阈值。NVIDIA官方也推荐使用使用相对熵校准的方式。所以 “legacy” calibrator 就不深入研究了。
6 源码解读
sampleINT8.cpp:
|
|
BatchStream.h,这个源码看起来还是稍微有点费劲的,还是我C++功底不够啊,得补。。。
|
|
7 结果
|
|
从这例程中也忽然发现在TensorRT中 1080ti GPU竟然不支持 FP16 mode,虽然1080ti官方的参数上是支持 float16的,但是在TensorRT中竟然不能使用。查了一下,是因为 1080ti的float16 吞吐量太低(throughput),效率太低,应该是TensorRT对float16也进行了条件限制,吞吐量太低的不支持。
从资料中得知,只有 Tesla P100, Quadro GP100, and Jetson TX1/TX2 支持 full-rate FP16 performance,应该也就只有这些才支持 TensorRT的FP16吧。新出的 TITAN V 加了tensor core,float16半精度性能有很大提升,应该也支持?不过有意思的是jetson TX1和 TX2 却能支持 FP16,反而不支持INT8.
可以参考下面资料:
FP16 –half=true option doesn’t work on GTX 1080 TI although it runs ./sample_int8 INT8
FP16 support on gtx 1060 and 1080The only GPUs with full-rate FP16 performance are Tesla P100, Quadro GP100, and Jetson TX1/TX2. All GPUs with compute capability 6.1 (e.g. GTX 1050, 1060, 1070, 1080, Pascal Titan X, Titan Xp, Tesla P40, etc.) have low-rate FP16 performance. It’s not the fast path on these GPUs. All of these GPUs should support “full rate” INT8 performance, however.
从结果上看:
INT8 MODE:Top 1 0.9908, 速度:0.0013438 ms/image ;
FP32 MODE : Top 1 0.9904,速度:0.00167893 ms/image;
准确率竟然还高那么一点点,速度上大概快了20%。