C/C++教程

英伟达TensorRT 8-bit Inference推理

本文主要是介绍英伟达TensorRT 8-bit Inference推理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

英伟达TensorRT 8-bit Inference推理

引论 

● 目标:将FP32 CNN转换为INT8,不会造成显著的精度损失。

● 原因:Int8 Math具有更高的吞吐量和更低的内存需求。

● 挑战:INT8的精度和动态范围,明显低于FP32。

● 解决方案:在将训练模型权权重化为INT8时,及在INT8计算激活时,将信息损失降至最低。

● 结果:方法已在TensorRT中实现。不需要任何额外的微调或重训练。

Outline

● INT8 compute

● Quantization

● Calibration

● Workflow in TensorRT

● Results

INT8推理挑战

● 与FP32相比,INT8的精度和动态范围明显更低。

● 需要的不仅仅是从FP32到INT8的简单类型转换。

 

 

 高通量INT8数学

● 需要sm_61+(Pascal TitanX,GTX 1080,特斯拉P4,P40等等)。

● 在32位结果中,累加四路byte字节点积。

 

 

 Context

● Performance.

● No accuracy loss.

● Hence solution has to be “simple” and compute efficient.

Linear quantization

Representation:

Tensor Values=FP32 scale factor * int8 array+FP32 bias

● 解决方案必须“简单”,计算效率高。

张量值=FP32比例因子*int8数组+FP32偏差

真的需要bias吗?

两个矩阵:

A=scale_A * QA+bias_A

B=scale_B * QB+bias_B

Let’s multiply those 2 matrices:

A * B=scale_A * scale_B * QA * QB

+ scale_A * QA * bias_B

+ scale_B * QB * bias_A

+ bias_A * bias_B

 

 

 将这两个矩阵相乘:

 

 

 真的需要bias吗?

不,两个矩阵:

A=scale_A * QA

B=scale_B * QB

将两个矩阵相乘:

A * B=scale_A * scale_B * QA * QB

对称线性量化

Representation:

张量值=FP32比例因子*int8数组

整个int8张量的一个FP32比例因子

问:如何设置比例因子?

Quantization

● No saturation: map |max| to 127

● 无饱和度:将| max |映射到127

 

Quantization

● 无饱和度:将| max |映射到127

 

● 通常,精度损失严重

● 无饱和度:将| max |映射到127

● 饱和超过|阈值|至127

 

● 通常,精度损失严重

Quantization

 

 

 问:如何优化阈值选择?

● 在INT8表示的范围和精度间,进行折衷权衡。

 

 

 两种编码的“相对熵”

● INT8模型编码与原始FP32模型相同的信息。

● 尽量减少信息损失。

● 信息损失由ullback-Leibler散度(又称相对熵或信息散度)衡量。

○ P,Q-两种离散概率分布。

○ KL_divergence(P,Q):= SUM(P[i] * log(P[i]/Q[i]),i)

● 直觉:KL散度度量,在近似给定编码时,丢失的信息量。

解决方案:校准

● 在校准数据集上运行FP32推理。

● 对于每一层:

○ 收集激活的直方图。

○ 生成许多具有不同饱和阈值的,量化分布。

○ 选择最小化KL_divergence(ref_distr,quant_distr)。

● 在典型的桌面工作站上,整个过程需要几分钟。

 

 

 校准数据集

● 表示

● 多种多样的

● 理想情况下,验证数据集的子集。

● 1000份样品

校准结果

校准结果#1

 

 

 校准结果#2

 

 

 校准结果#2

 

 

 校准结果#3

 

 

 校准结果#4

 

 

 校准结果#5

 

 

 TensorRT中的工作流

TensorRT中的典型工作流

● 需要:

○ 用FP32训练的模型。

○ 校准数据集。

● TensorRT将:

○ 在FP32中,对校准数据集,运行推理。

○ 收集所需的统计数据。

○ 运行校准算法→ 优化比例因子。

○ 量化FP32权重→ INT8。

○ 生成“CalibrationTable”和INT8执行引擎。

Results

Results – Accuracy

 

 

 TensorRT 2.1,已启用所有优化。ILSVRC2012验证数据集,batch批处理=25幅图像。对未用于校准的500batches,进行了准确度测量。

Results – Performance

 

 

 TensorRT 2.1,已启用所有优化。

公开挑战/改进

● ReLU后激活的Unsigned int8。

● RNNs→ 开放性研究问题。

● 微调饱和阈值。

● 公开API,接受用户提供的自定义比例因子。

Conclusion

● 引入了一种自动,无参数的方法,用于将FP32 CNN模型,转换为INT8。

● 对称线性量化,用于权重和激活。

● 量化原始FP32数据,使信息损失最小化。

● 使用FP32训练的大众化,公开可用的CNN模型,可转换为INT8,INT8模型的精度与FP32基线相当。

 

熵校准-伪码

输入:FP32直方图H,共2048个bins单元:bin[0],…,bin[2047]

For i in range( 128,2048):

reference_distribution_P=[bin[0],...,bin[i-1]] // take first ‘ i ‘ bins from H

outliers_count=sum( bin[i],bin[i+1],…,bin[2047])

reference_distribution_P[i-1] += outliers_count

P/=sum(P) // normalize distribution P

candidate_distribution_Q=quantize [bin[0],…,bin[i-1]] into 128 levels // explained later

expand candidate_distribution_Q to ‘ i ’ bins // explained later

Q/=sum(Q) // normalize

distribution Q divergence[i]=KL_divergence( reference_distribution_P,

 candidate_distribution_Q)

End For

Find index ‘m’ for which divergence[m] is minimal

threshold=( m+0.5) * ( width of a bin)

 

候选分布Q

● KL_divergence(P,Q) 要求 len(P) == len(Q)

● 候选分布 Q 源自融合‘ i ’ bins,从bin[0] 到 bin[i-1],生成 128 bins

● 随后,Q 再次‘expanded’到‘i’ bins

简单示例:

参考分布P由8 bins组成,希望量化到2 bins:

P=[1,0,2,3,5,3,1,7]

融合到 2 bins (8/2=4 连续 bins 合并成一个 bin) [1+0+2+3,5+3+1+7]=[6,16]

随后,按比例expand 到 8 bins,原始分布P保存为empty bins:

Q=[6/3,0,6/3,6/3,16/4,16/4,16/4,16/4]=[2,0,2,2,4,4,4,4]

now we should normalize both distributions,after that we can compute

规范化这两个分布,可以计算

KL_divergence P/=sum(P) Q/=sum(Q) result=KL_divergence(P,Q)

 

INT8 conv内核的伪代码

// I8 input tensors: I8_input,I8_weights,I8 output tensors: I8_output

// F32 bias (original bias from the F32 model)

// F32 scaling factors: input_scale,output_scale,weights_scale[K] I32_gemm_out=I8_input * I8_weights // Compute INT8 GEMM (DP4A)

F32_gemm_out=(float)

I32_gemm_out // Cast I32 GEMM output to F32 float

// At this point we have F32_gemm_out which is scaled by ( input_scale * weights_scale[K]),

// 要将最终结果存储在int8中,需要使scale等于“output_scale”,必须重新缩放:

// (this multiplication is done in F32,*_gemm_out arrays are in NCHW format)

For i in 0,... K-1:

rescaled_F32_gemm_out[:,i,:,:]=F32_gemm_out[:,i,:,:] * [output_scale/(input_scale * weights_scale[i])]

//添加bias偏差,要执行添加,必须重新缩放原始F32 bias,使用“输出_比例”进行缩放:

rescaled_F32_gemm_out _with_bias=rescaled_F32_gemm_out+output_scale * bias //

Perform ReLU (in F32)

F32_result=ReLU(rescaled_F32_gemm_out _with_bias)

//转换为INT8,保存为全局

I8_output=Saturate( Round_to_nearest_integer( F32_result))

Results - Performance - Pascal Titan X

 

 

 TensorRT FP32 vs TensorRT INT8

Pascal TitanX

Results - Performance - DRIVE PX 2,dGPU

 

 

 TensorRT FP32 vs TensorRT INT8

DRIVE PX 2,dGPU

 

参考链接:

https://on-demand.gputechconf.com/gtc/2017/presentation/s7310-8-bit-inference-with-tensorrt.pdf

 

这篇关于英伟达TensorRT 8-bit Inference推理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!