当前位置: 代码迷 >> 综合 >> 基于openvino 2019R3的INT8推理(inference)性能的深入研究 (一) MobilenetV2
  详细解决方案

基于openvino 2019R3的INT8推理(inference)性能的深入研究 (一) MobilenetV2

热度:71   发布时间:2024-01-12 21:17:09.0

最近一直在研究OpenVINO的INT8的推理性能,原本以为INT8是个万能膏药,任何模型经过INT8转换都可以提高性能。但是实战发现并非如此,最近分析了2个模型MobilenetV2和MobilenetV3,发现MobilenetV2的模型在转成INT8以后性能会大幅提升,但是MobilenetV3转换成INT8模型后性能反而会大幅下降。原来一直以为是自己转换的方法不对,后来深入分析了一下模型的架构,发现了一点规律,在这里分享一下 :)

 

首先是能够利用INT8模型大幅提高性能的例子 MoiblenetV2

从这里下载模型https://github.com/tensorflow/models/tree/master/research/slim/nets/mobilenet 下载mobilenet_v2_1.4_224这个模型,然后转换成OpenVINO FP32模型

python "c:\Program Files (x86)\IntelSWTools\openvino\deployment_tools\model_optimizer\mo_tf.py" --reverse_input_channels --input_shape=[1,224,224,3] --input=input --mean_values=input[127.5,127.5,127.5] --scale_values=input[127.5] --output=MobilenetV2/Predictions/Reshape_1 --input_model=mobilenet_v2_1.4_224_frozen.pb

在mo转换的时候,指定了mean/shift和reverse_input_channel, 让OpenVINO帮忙在inference的时候把输入的像素做RGB转BGR,并且归一化到[-1,1]之间

通过netron观察原始mobilenet_v2_1.4_224_frozen.pb的网络架构和转换后的mobilenet_v2_1.4_224_frozen.xml的网络架构

观察一下输入层下面几层网络,可以看到MO在转换的时候把Conv2D和BiasAdd合并优化成了一个Convolution操作,把DepthwiseConv2D和FusedBN合并成了一个Convolution操作。通过这种网络层的合并,节省了多个network layer之间的输入输出的内存读写的带宽开销,非常不错 :)

 

接下来看看IE在运行时候的时间,利用openvino sdk自带的benchmark app

benchmark_app.exe -m mobilenet_v2_1.4_224_frozen.xml  -nireq 1 -nstreams 1 -b 1 -pc

这里只想获得最快的单帧图像的推理时间,不考虑高并发,所以用以上参数指定每次inference request只有1,也可以用-api sync来获得相同的数据

benchmark_app.exe -m mobilenet_v2_1.4_224_frozen.xml  -api sync -pc

-pc参数可以让benchmark之后打印出每一层网络计算的时间,再观察一下头几层的运算时间

IE在运算时,通过MKL-DNN的post-ops操作,把convolution->relu6->depthwise_convolution->relu6 4层操作又合并在一起计算了,这下又节省了不少内存读写的开销了。

 

最终我们得到了MobilenetV2 FP32的各层计算的时间, 每次推理7.75ms

Full device name: Intel(R) Core(TM) i5-7440HQ CPU @ 2.80GHzCount:      6688 iterations
Duration:   60023.43 ms
Latency:    7.75 ms
Throughput: 111.42 FPS

 

接下来看看INT8模型的运行时间

首先转换成INT8模型,模型转换最简单的方法就是用OpenVINO官方提供的docker workbench来转换,全部图形化操作,省去了写各种转换配置文件的时间;另一种方法用sdk自带的calibration tool工具来转换,如果不考虑转换精度的话,可以设置转换模式为-sm (simple mode), 在这种模式下,不需要提供用于计算转换精度的样本集,转换工具会转换所有能够转成INT8的网络层。这样转出来的模型虽然精度损失很大,但是可以用benchmark_app来快速评估转换出来INT8模型的性能提升。

python "c:\Program Files (x86)\IntelSWTools\openvino\deployment_tools\tools\calibration_tool\calibrate.py" -sm -m mobilenet_v2_1.4_224_frozen.xml -e C:\Users\???\Documents\Intel\OpenVINO\inference_engine_samples_build\intel64\Release\cpu_extension.dll

转换出来的INT8模型可以继续用benchmark打印出各层的计算时间,并且和FP32的时间做一个对比

可以看到

  1. INT8模型在进行Conv INT8计算前,多做了一步FP32, 因为MKL-DNN做Conv FP32计算时,最高效的内存格式是nChw8c,而Conv INT8的计算,首选内存格式是nhwc。所以从FP32计算切换到INT8模式前,要先做一步Reorder; 同理在INT8计算完以后返回FP32计算前,也需要多做一步Reorder, 把内存数据排列再转换回去。
  2. 相对于Conv FP32, 每次Conv INT8卷积计算的时间可以大幅度缩减。我的CPU最高支持到AVX2, 如果CPU支持AVX512, 这个计算时间可以继续缩减。

总的INT8 模型的推理时间是4.70ms每帧,相对FP32推理的7.75ms 提升了不少

Full device name: Intel(R) Core(TM) i5-7440HQ CPU @ 2.80GHzCount:      12037 iterations
Duration:   60006.28 ms
Latency:    4.70 ms
Throughput: 200.60 FPS
  • 要注意的是, 上面这个4.70ms只是一个理论的数据。这个数据的前提是所有能够转成INT8的卷积计算全部转成INT8计算。在实际转换过程中,calibration tool会根据你定义好的精度损失阈值来动态的调整转换的Conv层的数量,如果精度损失超过了你的阈值, 会再把一些Conv INT8卷积层再回退到FP32卷积层。最终得到的INT8模型里既会有INT8卷积层,也会有FP32卷积层,因此会实际的性能会不如这个理论值。

 

最终,统计了一下MobilenetV2 FP32和INT8推理时各层的数量和CPU计算用的时间

FP32

  层数量 时间(微秒)
Convolution 53 8619
Reorder 2 107
其他层 52 101
总计 107 8827

INT8

  层数量 时间(微秒)
Convolution 53 4676
Reorder 3 125
其他层 52 66
总计 108 4867

 

可以看出基本上在推理开始就通过一次Reorder开始做INT8卷积,然后就一直INT8卷积计算下去,直到最后计算Softmax前才切换回FP32数据。 这样卷积层计算基本节省了一大半的时间,而额外增加的一层Reorder只增加了额外20us不到的开销。

MobilenetV2是个非常好的基于OpenVINO的INT8模型提升性能的例子,

  相关解决方案