函数 init_quantize_config 是 Quantizer 类的核心接口函数。PPQ 使用这个函数为所有算子初始化 TQC(Tensor Quantization Config)。 通常而言,我们将根据算子的类型、算子的调度情况(算子上的 platform 属性)来决定如何量化给定的算子。 你需要认识到一个事实,在 PPQ 中所有的逻辑都围绕着 TQC(Tensor Quantization Config) 这一控制结构体展开 - Quantizer 负责初始化 TQC
(self, operation: Operation)
| 49 | |
| 50 | class MyQuantizer(BaseQuantizer): |
| 51 | def init_quantize_config(self, operation: Operation) -> OperationQuantizationConfig: |
| 52 | """ |
| 53 | 函数 init_quantize_config 是 Quantizer 类的核心接口函数。PPQ 使用这个函数为所有算子初始化 TQC(Tensor Quantization Config)。 |
| 54 | 通常而言,我们将根据算子的类型、算子的调度情况(算子上的 platform 属性)来决定如何量化给定的算子。 |
| 55 | |
| 56 | 你需要认识到一个事实,在 PPQ 中所有的逻辑都围绕着 TQC(Tensor Quantization Config) 这一控制结构体展开 |
| 57 | - Quantizer 负责初始化 TQC |
| 58 | - Optim Passes 负责调整 TQC 的参数和状态 |
| 59 | - Exporter 负责导出 TQC |
| 60 | |
| 61 | init_quantize_config 函数只有一个参数,即需要被量化的算子,返回一个量化算子的量化控制结构体。 |
| 62 | |
| 63 | Args: |
| 64 | operation (Operation): 需要被量化的算子 |
| 65 | |
| 66 | Returns: |
| 67 | OperationQuantizationConfig: 返回的控制结构体 |
| 68 | """ |
| 69 | # ------------------------------------------------------------ |
| 70 | # 成员函数 create_default_quant_config 负责提供默认的 OQC (Operation Quantization Config) |
| 71 | # 数据结构 OQC 只是 TQC 的一个简单集合,对于任何一个 onnx 算子而言,它都会具有 n 个输入变量和 m 个输出变量 |
| 72 | # 因此对应的 OQC 内将包含 n 的关于输入变量的 TQC, 以及 m 个关于输出变量的 TQC |
| 73 | |
| 74 | # 以卷积算子为例,它可以有 2 - 3 个输入变量,以及至多一个输出变量 |
| 75 | # 因此它的 OQC 内将含有 2 - 3 个输入 TQC,分别对应 输入量化、权重量化、bias 量化 |
| 76 | |
| 77 | # OQC 一旦创建,则图结构不能发生改变,因此图的变换需要发生在量化之前 |
| 78 | # 因为图结构一旦变换,则可能导致算子的输入个数变化,从而导致 OQC 不匹配 |
| 79 | |
| 80 | # 下面的代码将把算子上所有的 TQC 初始化为非对称 PER_TENSOR 量化 |
| 81 | # ------------------------------------------------------------ |
| 82 | OQC = self.create_default_quant_config( |
| 83 | policy=QuantizationPolicy( |
| 84 | QuantizationProperty.ASYMMETRICAL + |
| 85 | QuantizationProperty.LINEAR + |
| 86 | QuantizationProperty.PER_TENSOR), |
| 87 | rounding=RoundingPolicy.ROUND_HALF_EVEN, |
| 88 | op=operation, num_of_bits=8, exponent_bits=0, |
| 89 | quant_max=255, quant_min=0, |
| 90 | observer_algorithm='percentile') |
| 91 | |
| 92 | # 对于卷积和矩阵乘算子而言,它的 bias 量化通常需要使用 scale = input scale * weight scale |
| 93 | # 此时我们希望你将卷积的 bias 量化状态设置为 PASSIVE_INIT, 而后 PassiveParameterQuantizePass 将会正确处理 bias 的 scale 问题 |
| 94 | # 于此同时你还需要将 bias 的量化位宽调整到 32 位,并且相应的调整 quant min, quant max |
| 95 | # 同时将 bias 的量化调整为 对称 PER_TENSOR 量化 |
| 96 | if operation.type in {'Conv', 'ConvTranspose', 'Gemm'}: |
| 97 | if operation.num_of_input == 3: |
| 98 | TQC = OQC.input_quantization_config[-1] |
| 99 | TQC.state = QuantizationStates.PASSIVE_INIT |
| 100 | TQC.num_of_bits = 32 |
| 101 | TQC.quant_max = 1 << 30 |
| 102 | TQC.quant_min = -1 << 30 |
| 103 | TQC.policy = QuantizationPolicy( |
| 104 | QuantizationProperty.SYMMETRICAL + |
| 105 | QuantizationProperty.LINEAR + |
| 106 | QuantizationProperty.PER_TENSOR) |
| 107 | TQC.observer_algorithm = 'minmax' |
| 108 |
nothing calls this directly
no test coverage detected