🤝量化粒度
Last updated
Last updated
量化中非常重要的概念: Quantization Granularity(量化粒度) 指的是对于一个Tensor,以多大的粒度去共享scale和z,或者dynamic range。
根据分组的依据不同,量化粒度有多种形式:
per-tensor/per-layer
per-channel/per-axis
per-col/per-row
per-embeding/per-token
per-block/group
一般来说,量化粒度越小,需要额外存储的量化系数就越多,比如针对卷积运算常见的 per-tensor/per-channel 量化,如下图所示,per-tensor 只需一组 (S, Z) 量化系数,而 per-channel 需要多组,提升了量化精度,但同时会一定程度增加量化后数据的大小
Per-tensor量化
优点:低延迟: 一个tensor共享同一个量化参数
缺点:高错误率: 一个scale很难覆盖所有FP32的 dynamic range
Per-channel (layer)量化
优点:低错误率: 每一个channel都有自己的scale 来体现这个channel中的数据的dynamic range
缺点:高延迟: 需要使用vector来存储每一个 channel的scale
从很多实验结果与测试中,对于weight和activation values的量化方法,一般会选取
对于activation values,选取per-tensor量化
对于weights,选取per-channel量化
为什么weight需要per-channel呢?主要是因为
BN计算与线性计算的融合 (BN folding)
线性变化𝑦=𝑤∗𝑥的BN folding可以把BN的参数融合在线性计算中。但是BN的可参数是per-channel的。如果 weights用per-tensor的话,会掉精度。
depthwise convolution
depthwise convolution中kernel的channel size是1,每一个kernel针对输入的对应的channel做卷积。所以每一个 channel中的参数可能差别会比较大。如果用per-tensor的话容易掉精度比较严重
目前的TensorRT已经默认对于Activation values选用Per-tensor,Weights选用 Per-channel,这是他们做了多次实验所得出的结果。很多其他平台的SDK可能不会 提供一些默认的量化策略,这时我们需要谨慎选择,尽快找到掉点的原因。