REFERENCE

统一规范

1. 目标

本文档定义一个 ONNX 模型符合 ax quant spec 时必须满足的约束。

本文档只描述模型本身的语义和 Q/DQ 结构,不描述:

  • producer 的默认行为;
  • QuantONNX 的推荐导出形态;
  • Python 或检查工具的实现;
  • 某一具体芯片的差异化能力。

ax quant spec 是模型符合性判定的唯一依据。一个模型只有在不违反本文档任意适用的 error 严重级规则时,才是符合 ax quant spec 的 ONNX。

本文档中的规则分为两个层次:

1. 通用规则和基础 QDQ 规则:定义模型覆盖闭合、ONNX 常量形式以及 Q/DQ 本身的共同 要求; 2. 后端约束:定义 Axera 对量化角色、算子和 Pattern 增加的限制。

后端约束面向统一的 Axera 目标,不细分具体芯片。

2. 通用规则与判定原则

2.1 适用模型

ax quant spec 适用于面向 Axera 的 QDQ ONNX 模型。

模型必须至少包含一条由算子规则或 Pattern 规则拥有的 Q/DQ 量化边。完全不包含 Q/DQ 量化边的普通非量化 ONNX 不在本文档的适用范围内。不接触任何算子或 Pattern 数据 路径的 Q/DQ 边不属于被拥有的量化边。

模型不绑定特定 producer,也不绑定具体芯片目标。

2.2 ONNX 基础要求

模型必须首先是符合其声明 opset 的有效 ONNX 模型。ax quant spec 不统一限定模型的 opset。

当本文档没有对某个 ONNX 属性、shape 或输入形式增加额外约束时,接受该模型声明 opset 下有效的 ONNX 语义,不从当前 producer 的实现或默认配置推导额外限制。

所有静态常量必须使用 ONNX initializer 表示,不使用 Constant 节点表示。 zero_point 的输入形式按第 3.1 节判定;由已覆盖节点计算得到的 zero_point 不因其 可静态求值而要求改写为 initializer。

模型必须为每个中间张量提供完整的 value_info 声明,包含确定的 dtype 与完整 shape。仅被 initializer 表示的张量不要求额外的 value_info。该项完整性检查受 check_value 控制(见第 2.5 节)。

2.3 闭合规则

模型中的每个非 QuantizeLinearDequantizeLinear 节点,都必须满足以下条件之一:

1. 被一条独立算子规则覆盖; 2. 被一个已定义 Pattern 覆盖。

模型中的每个 Q/DQ 节点以及每一组 Q/DQ 量化边,都必须具有唯一且不冲突的用途, 例如:

  • 算子的输入或输出量化边;
  • Pattern 的输入或输出量化边;
  • 被动传递子图的量化边界;
  • Identity 标记的 requantize 边界。

无法被算子规则或 Pattern 规则覆盖的节点、子图或 Q/DQ 结构,均不符合 ax quant spec。 违反任意一条 error 严重级规则时,模型整体不符合 ax quant spec。

2.4 符合性条件

对于适用范围内的模型,符合性判定只有“符合”和“不符合”两种结果。模型必须同时 满足:

1. 模型符合其声明 opset 下的 ONNX 语义; 2. 所有静态常量均采用 initializer; 3. 所有 Q/DQ 节点和量化边均不违反 error 严重级的基础 QDQ 规则; 4. 每个节点和量化边都具有唯一的算子或 Pattern 所有权; 5. 所有量化角色、算子和 Pattern 均不违反 error 严重级的后端约束。

producer 来源、默认配置、编译结果或“接近推荐形态”均不能替代上述任一条件,也不能 作为违反规则后的例外。

2.5 规则严重级与 check_value

每个检查结果使用以下严重级:

严重级含义是否影响符合性
error模型结构、类型、shape、所有权或必须满足的后端约束被违反。
warn可选的数值检查发现异常,需要调用方关注。
info补充说明检查路径、配置或统计信息。

模型没有 error 时判定为符合;warninfo 必须保留在检查结果中,但不改变符合性。

check_value 控制以下数值检查,默认值为 false;命令行使用 -c--check-value 开启:

  • zero_point 的元素值是否满足对称量化固定值或非对称量化数值范围;
  • bias_scaleinput_scale * weight_scale 的数值一致性;
  • 配对 Q/DQ 的 scalezero_point 元素值是否分别逐元素完全一致;
  • Split 被动传递 Pattern 最终出口的同类型 Q/DQ 是否具有已知且一致的 scalezero_point

check_value = true 时执行上述检查,违反项的严重级为 warncheck_value = false 时不做上述数值一致性检查,也不生成对应检查结果。zero_point 的显式输入、数据类型、 shape、量化粒度以及配对 Q/DQ 的参数类型、shape、量化粒度和 axis 一致性不受该 开关控制,违反时仍为 error。bias 的输入形式、数据类型、shape、量化粒度和适用 算子要求也不受该开关控制。

中间张量 value_info 的完整性检查(见第 2.2 节)同样受 check_value 控制: check_value = true 时缺失或不完整的声明为 errorcheck_value = false 时不做 该项检查。

3. 基础 QDQ 规则

QuantizeLinearDequantizeLinear 共同表达量化边界,不作为两个相互独立的后端 算子规则判定。每个 Q/DQ 节点必须在本节定义的完整 Q/DQ、DQ-only 常量或 requantize 结构中取得唯一所有权。

3.1 浮点侧与量化参数

QuantizeLinearDequantizeLinear 的浮点侧统一使用 FP32:

  • QuantizeLinear 的数据输入为 FP32;
  • scale 为 FP32;
  • DequantizeLinear 的数据输出为 FP32。

每个 Q/DQ 节点的 scalezero_point 必须显式存在。scale 必须是该节点直接 引用的 initializer;zero_point 不要求直接引用 initializer,但不得省略,也不得依赖 ONNX 的默认值。

scale 的每个元素都必须是有限数,并且严格大于 0。

3.2 zero_point 数值范围

本节规则严重级为 warn,并受 check_value 控制。

对称量化的 zero_point 每个元素都必须等于 0。

非对称量化的 zero_point 每个元素都必须位于其存储类型可表示的完整范围内:

存储类型最小值最大值
UINT4015
INT4-87
UINT80255
INT8-128127
UINT16065535
INT16-3276832767
INT32-21474836482147483647

不对量化数据 initializer 或运行时量化值增加排除整数最小值等额外数值约束。

3.3 量化粒度

per-tensor 量化的 scalezero_point 必须采用以下形式之一:

  • rank-0 scalar;
  • 仅含一个元素的一维 tensor。

per-channel 量化的 scalezero_point 必须是一维 tensor,并且元素数量相同。 per-channel 量化必须显式声明 axis

ax quant spec 只允许 per-tensor 和 per-channel 两种量化粒度,不允许 blocked quantization 等其他粒度。

权重 per-channel 量化的 axis 必须满足:

算子权重 axis
Conv0
Gemm0
ConvTranspose1

不接受上述 axis 的负数等价形式。

3.4 Q/DQ 配对

一组相邻的 QuantizeLinear -> DequantizeLinear 构成一条 Q/DQ 量化边。

同一组 Q/DQ 必须满足:

  • 整数量化类型相同;
  • scale 的 shape 和数据类型相同;
  • zero_point 的 shape 和数据类型相同;
  • 量化粒度相同;
  • per-channel 量化的 axis 归一化到实际 tensor 维度后相同。

上述结构一致性规则始终执行,违反时严重级为 error

check_value = true 时,还分别检查配对 Q/DQ 的 scalezero_point 元素值:

  • 两端数值均可静态读取时,必须逐元素完全一致;
  • 数值不一致时生成 warn,不改变模型符合性;
  • check_value = false 时不做这两项数值一致性检查。

Q 和 DQ 可以为量化参数引用名称不同的输入;其中 scale 仍必须是各节点直接引用的 initializer。两端参数结构必须满足上述规则;启用数值检查时,对应元素值也必须一致。

QuantizeLinear 的数据输出必须只有一个消费者,并且该消费者必须是与其配对的 DequantizeLinearQuantizeLinear 的数据输出不得直接作为 graph output。

DequantizeLinear 的数据输出可以被多个节点消费。一条共享的 Q/DQ 量化边可以作为 多个分支的共同量化边界,但所有分支必须对该边界具有一致的解释。

运行时激活必须使用完整 Q/DQ。DequantizeLinear 的整数数据输入只能来自:

1. 与其配对的 QuantizeLinear; 2. 对应算子规则允许的整数 initializer。

不得以 graph input 或其他运行时整数节点直接驱动 DequantizeLinear,用来替代运行时 激活的完整 Q/DQ。

3.5 requantize

当一条量化数据路径上连续两组 Q/DQ 使用不同量化参数时,必须在上游 DQ 和下游 Q 之间插入 Identity,显式标记 requantize:

Q1 -> DQ1 -> Identity -> Q2 -> DQ2

以下任意一项不同,均视为量化参数不同:

  • 整数量化类型;
  • scale
  • zero_point
  • 量化粒度;
  • axis

当上述内容完全相同时,两组 Q/DQ 之间可以直接连接,不要求插入 Identity

requantize Identity 只标记其所在分支。普通 Identity 仍遵循被动传递规则,不得 改变量化参数。

3.6 常量的量化表示

量化权重允许以下两种表示:

1. FP32 initializer -> QuantizeLinear -> DequantizeLinear; 2. integer initializer -> DequantizeLinear

量化 bias 允许以下三种表示:

1. 直接使用 FP32 initializer; 2. FP32 initializer -> QuantizeLinear -> DequantizeLinear; 3. INT32 initializer -> DequantizeLinear

除权重和 bias 外,作为算子数据输入参与浮点计算的静态常量:

  • 使用 FP32 initializer 时,必须经过完整 Q/DQ;
  • 使用整数 initializer 表示量化数据时,必须经过 DQ;
  • 不得以 FP32 initializer 直接进入 quant-only 算子的数据输入。

shape、axis、indices、condition、pads 等辅助输入遵循对应算子的原生类型规则,不因其 为 initializer 而要求量化。

4. 后端约束:量化角色

算子和 Pattern 可以在以下范围内进一步缩小允许类型,但不得自行扩大类型或粒度范围。

角色允许类型量化粒度量化方式
激活U4per-tensor非对称
激活S8per-tensor对称或非对称
激活U8per-tensor非对称
激活S16per-tensor对称
激活U16per-tensor非对称
权重S4、S8per-channel对称
量化 biasS32per-channel对称
非量化数据或参数FP32 或算子原生类型不适用不量化

U4 激活仅允许用于 Conv、ConvTranspose 或 Gemm(canonical fully-connected)的激活 输入;其他算子不得使用 U4 激活。使用 4 bit 量化时,激活的通道数必须为偶数; S4 权重的输出通道数必须为偶数。

不同算子、不同边以及同一算子的不同输入,可以使用不同的激活类型和量化参数。除非 算子或 Pattern 另有明确约束,不要求模型全局使用同一种激活类型,也不要求多输入 算子的输入共享 scalezero_point

量化 bias 必须逐通道满足:

bias_scale = input_scale * weight_scale

该关系用于数值一致性检查,不表示推荐值。检查结果的严重级为 warn,受 check_value 控制。执行检查时,乘法按 FP32 数值语义计算,并逐元素按以下阈值判定:

abs(bias_scale - input_scale * weight_scale)
    <= 1e-7 + 1e-5 * abs(input_scale * weight_scale)

不满足该不等式的元素违反本项规则。其中绝对阈值为 1e-7,相对阈值为 1e-5

ConvTranspose 在 group > 1 时不得使用量化 bias;无 bias 或直接使用 FP32 bias 不受 此项限制。

5. 后端约束:算子规则

5.1 算子行为分类

本文档使用以下行为分类组织算子规则:

分类含义
quant-only算子的浮点数据路径必须由其规则规定的 Q/DQ 边包围,不提供完整非量化数据模式。
non-quant-only算子自身不拥有 Q/DQ,可以出现在模型的非量化子图中。
被动传递可以处理非量化数据,也可以位于量化数据路径中;量化模式不改变数据的量化参数。
量化或原生模式根据数据语义使用量化浮点模式或原生整数/非量化模式,两种模式不得混淆。
量化或非量化模式同一算子允许量化模式和非量化模式;两种模式分别应用对应规则。

quant-only 算子的“输入”和“输出”均指其浮点数据角色。shape、axis、indices、condition 等辅助角色不插入 Q/DQ。

对于多输出算子,只有被消费或作为 graph output 的量化数据输出才要求具有 Q/DQ。 完全未使用且不是 graph output 的输出不要求插入 Q/DQ。

quant-only 算子的每个已使用量化数据输出分支都必须具有 Q/DQ,除非该分支直接进入 一个已定义 Pattern,并由该 Pattern 接管内部边。

5.2 Conv、ConvTranspose 与 Gemm

Conv、ConvTranspose 和 Gemm 为 quant-only:

  • 输入激活必须量化;
  • 权重必须量化;
  • 输出激活必须量化;
  • 输入激活和输出激活的类型、scalezero_point 相互独立;
  • 权重只允许对称 S4 或 S8 per-channel 量化;
  • Conv 和 Gemm 的权重 axis = 0
  • ConvTranspose 的权重 axis = 1

bias 为可选输入。存在 bias 时,允许:

  • 直接 FP32 initializer;
  • FP32 initializer 经 S32 Q/DQ;
  • INT32 initializer 经 DQ。

量化 bias 必须为对称 S32 per-channel,并满足第 4 节的 bias scale 关系。

Gemm 只接受 canonical fully-connected 形式:

transA = 0
transB = 1
alpha = 1
beta = 1

除 ONNX 自身要求外,当前不增加 bias shape 和广播形式约束。

Transpose、MatMul、Add 等节点分解形成的 linear 计算不定义为独立 FC Pattern。此类 子图中的节点分别应用 Transpose、MatMul 和 Add 的算子规则,节点之间保留各自规则 要求的 Q/DQ,不因其整体语义等价于 linear 而移除内部量化边。对此类分解形式不增加 额外 rank 约束。

5.3 MatMul

MatMul 为 quant-only:

  • 两个数据输入都必须使用对称 per-tensor S8 或 S16;
  • 两个输入的整数量化类型必须相同,即同时为 S8 或同时为 S16;
  • 两个输入的 scalezero_point 可以不同;
  • 输出从激活类型范围中独立选择类型和量化参数;
  • 常量输入可以使用完整 Q/DQ,也可以使用整数 initializer 经 DQ。

5.4 GridSample

GridSample 不提供完整非量化模式:

  • 特征输入必须使用对称 per-tensor S8 或 S16;
  • grid 只允许 FP32 或对称 per-tensor S16;
  • FP32 grid 直接输入,静态 FP32 grid 必须是 initializer;
  • 运行时 S16 grid 使用完整 Q/DQ;
  • 静态 S16 grid 可以使用整数 initializer 经 DQ;
  • 输出从激活类型范围中独立选择类型和量化参数。

grid 不允许使用 S8 量化。

5.5 二元及多元算术

Add、Sub、Mul、Div、Max、Min 为 quant-only 浮点数据算子:

  • 所有浮点数据输入必须量化;
  • 输出必须量化;
  • 各输入和输出的量化类型及量化参数相互独立;
  • Max 和 Min 的所有可变数量数据输入均遵循此规则。

Add、Sub、Mul 在处理 shape 或 index 算术时,可以使用无 Q/DQ 的原生整数模式。

Add、Sub、Mul 的 FP32 静态数据操作数必须经过完整 Q/DQ;整数静态量化数据必须经过 DQ,不允许以直接 FP32 initializer 作为量化数据操作数。

Pow 为 quant-only,但只量化 base 和输出。exponent 不量化;静态 exponent 必须使用 initializer 表示。

LogSoftmax 和 LpNormalization 为 quant-only,其数据输入和输出的量化参数相互独立。

5.6 一元 quant-only 算子

以下算子的浮点数据输入和输出都必须量化,输入与输出的量化参数相互独立:

  • Cos
  • Elu
  • Erf
  • Exp
  • HardSigmoid
  • HardSwish
  • Log
  • Mish
  • Sin
  • Softplus
  • Sqrt
  • Tanh
  • Reciprocal

5.7 激活、归一化与池化

以下算子为 quant-only,数据输入和数据输出必须量化,输入与输出的量化参数相互独立:

  • Sigmoid
  • Gelu
  • LeakyRelu
  • Softmax
  • AveragePool
  • GlobalAveragePool
  • LayerNormalization
  • GroupNormalization
  • InstanceNormalization
  • BatchNormalization

LayerNormalization、GroupNormalization 和 InstanceNormalization 中存在的 affine scale、bias 必须是直接使用的 FP32 initializer。

独立 BatchNormalization 的数据输入和输出必须量化;scale、bias、mean、variance 必须全部是直接使用的 FP32 initializer。

Conv 或 ConvTranspose 后接 BatchNormalization 时,可以由第 6 节定义的融合 Pattern 接管。

5.8 带有类型化输入输出的 quant-only 算子

以下算子为 quant-only:

  • CumSum
  • PRelu
  • ReduceL2
  • ReduceMean
  • ReduceSum
  • RoiAlign
  • ScatterElements
  • ScatterND
  • Where

具体角色约束如下:

  • PRelu:数据输入和输出量化;slope 必须为 FP32 initializer。
  • CumSum、ReduceL2、ReduceMean、ReduceSum:数据输入和输出独立量化;axis 或 axes 使用原生类型,不量化。
  • RoiAlign:feature 和输出独立量化;rois 为 FP32;batch_indices 为原生整数。
  • ScatterElements、ScatterND:data 和 updates 必须量化且整数量化类型相同, scalezero_point 可以不同;输出独立量化;indices 为原生整数。
  • Where:condition 为 BOOL;X 和 Y 必须量化且整数量化类型相同,scalezero_point 可以不同;输出独立量化。

5.9 non-quant-only 算子

以下算子自身不拥有 Q/DQ,可以出现在模型的非量化子图中:

  • Abs
  • Ceil
  • Floor
  • Neg
  • Round
  • And
  • ArgMax
  • ArgMin
  • Cast
  • Equal
  • Greater
  • GreaterOrEqual
  • Less
  • LessOrEqual
  • Not

这些算子可以消费上游 DQ 输出形成的 FP32 或原生类型数据,但不得把自身解释为一个 量化算子。

5.10 被动传递算子

以下算子同时允许非量化模式和量化被动传递模式:

  • DepthToSpace
  • Expand
  • Flatten
  • Gather
  • Identity
  • Reshape
  • Slice
  • SpaceToDepth
  • Split
  • Squeeze
  • Transpose
  • Unsqueeze
  • MaxPool
  • ReduceMax
  • Resize
  • Tile
  • GatherElements
  • GatherND
  • ReduceMin
  • GlobalMaxPool

在量化被动传递模式下:

  • 算子内部不插入 Q/DQ;
  • Split 被动传递 Pattern 外,所有量化数据出口必须与入口共享完整量化参数;
  • 共享内容包括整数量化类型、scalezero_point、量化粒度和 axis
  • shape、indices、axes、sizes 等辅助输入使用算子原生类型;
  • MaxPool 的 indices 输出使用原生整数类型,不量化。

多个相连的被动传递算子可以构成带分支的被动传递子图。子图内部不得插入 Q/DQ, 每个量化数据出口都必须共享入口的完整量化参数。包含 Split 的被动传递 Pattern 对最终出口应用第 5.11 节专用规则。

普通 Identity 遵循上述规则;用于 requantize 标记的 Identity 遵循第 3.5 节。

5.11 Split

Split 是被动传递算子。由 Split 以及其各分支上连续的被动传递算子构成一个 Split 被动传递 Pattern,直至分支连接 Q/DQ、非被动传递算子或 graph output。

结构规则如下:

  • Split 允许使用非量化模式或量化被动传递模式;
  • 量化被动传递模式下,Pattern 内部不插入 Q/DQ;
  • 每个分支可以继续经过其他被动传递算子;
  • 使用量化数据的分支必须在离开 Pattern 时建立完整 Q/DQ 边界;
  • 完全未使用且不是 graph output 的输出不构成量化数据出口;
  • 最终出口 Q/DQ 的整数量化类型可以与输入不同,各出口之间也可以不同;
  • 不因最终出口的整数量化类型或量化参数与输入不同而生成 error

check_value = true 时,对 Pattern 的输入 Q/DQ 和所有最终出口 Q/DQ 执行以下 数值检查:

1. 最终出口与输入的整数量化类型相同时,该出口的 scalezero_point 必须可静态 读取,并分别与输入逐元素完全一致; 2. 将最终出口按整数量化类型分组;同一类型至少有两个出口时,组内所有 scalezero_point 必须可静态读取,并分别逐元素完全一致; 3. 数值未知或不一致均生成 warn,不生成 error,也不改变模型符合性; 4. 不同整数量化类型的出口之间不比较 scalezero_point

check_value = false 时不做上述数值一致性检查。每个最终出口 Q/DQ 自身仍应用第 3 节 基础 QDQ 规则。

当 Split 位于 GLU Pattern 内部时,由 GLU Pattern 接管,不单独应用被动传递规则。

5.12 Concat

Concat 的浮点数据模式必须量化,同时允许原生整数模式。

在量化模式下:

  • 所有数据输入必须量化;
  • 所有输入的整数量化类型必须相同;
  • 各输入的 scalezero_point 可以不同;
  • 输出必须量化;
  • 输出类型和量化参数独立于各输入。

5.13 Pad

Pad 允许使用量化模式或非量化模式。

在量化模式下:

  • 数据输入和数据输出共享完整量化参数;
  • pads 使用原生整数类型;
  • constant_value 存在时,必须是直接使用的 FP32 initializer,不单独量化。

5.14 TopK

TopK 允许使用量化模式或非量化模式。

在量化模式下:

  • X 必须量化;
  • Values 与 X 共享完整量化参数;
  • Indices 使用原生整数类型,不量化;
  • Values 被消费或作为 graph output 时必须具有 Q/DQ;
  • Values 完全未使用且不是 graph output 时不要求 Q/DQ。

5.15 Relu

Relu 允许使用独立 quant-only 形式,也可以作为量化算子或 Pattern 的分支局部融合尾。

对称量化形式:

  • Relu 前后都必须具有 Q/DQ;
  • 输出 zero_point = 0
  • 不形成融合尾。

非对称独立形式:

  • graph input 或被动传递子图之后的 Relu,前后都必须具有 Q/DQ;
  • 输出 zero_point = 0

非对称融合尾形式:

... -> input Q/DQ -> X -> Relu -> output Q/DQ
  • X 必须是已被独立算子规则或 Pattern 规则定义的非被动量化计算;
  • X 与 Relu 之间不得插入 Q/DQ;
  • Relu 输出必须具有 Q/DQ;
  • 输出 zero_point = 0
  • 融合只拥有选中的 Relu 分支;
  • X 的其他消费者继续分别遵循各自的算子或 Pattern 规则。

5.16 Clip

Clip 允许使用独立 quant-only 形式,也可以作为分支局部融合尾。

min 和 max 只允许:

  • 省略;
  • 使用直接引用的 FP32 initializer。

动态 min 或 max 不符合 ax quant spec。静态边界值不限定为 ReLU6 等固定范围。

对称量化 Clip 前后都必须具有 Q/DQ,不形成融合尾。

非对称 Clip 可以采用与 Relu 相同的独立形式或分支局部融合尾形式。Clip 输出的 zero_point 由输出量化方式决定:

  • 对称量化时为 0;
  • 非对称量化时位于对应存储类型的有效范围内。

Clip 不具有统一的输出 zero_point = 0 要求。

5.17 不符合 ax quant spec 的算子或形式

以下算子不符合当前 ax quant spec:

  • AffineGrid
  • GRU
  • LSTM

以下输入形式也不符合当前 ax quant spec:

  • 动态 Clip;
  • ConvTranspose 在 group > 1 时使用量化 bias。

6. 后端约束:Pattern 规则

6.1 Pattern 所有权

当一个子图同时匹配多个 Pattern 时,语义节点和语义边覆盖范围最大的 Pattern 优先。 被最大 Pattern 拥有的内部节点不再独立应用算子规则。

若两个最大 Pattern 覆盖规模相同且发生重叠,同时无法形成唯一所有权,则模型不符合 ax quant spec。

除规则明确允许外:

  • Pattern 内部不得插入 Q/DQ;
  • Pattern 内部中间结果不得被 Pattern 外部节点消费;
  • Pattern 只通过其定义的输入和输出边与外部图连接。

Relu 和 Clip 的分支局部融合尾是内部结果不得逃逸规则的明确例外:主算子 X 可以有 其他消费者,但融合 Pattern 只拥有选中的 Relu 或 Clip 分支。

6.2 SiLU

SiLU Pattern 由 Sigmoid 和 Mul 构成:

X -> Sigmoid
X ----------> Mul -> Y
  • X 和 Y 是 Pattern 的量化边界;
  • Pattern 内部的 Sigmoid 和 Mul 之间不插入 Q/DQ;
  • 内部节点和边由 SiLU Pattern 拥有,不再应用独立 Sigmoid、Mul 规则。

6.3 GLU

GLU Pattern 由 SplitSigmoidMul 构成:

X -> Split -> A -----------------> Mul -> Y
             B -> Sigmoid -> G ---^
  • X 和 Y 必须分别具有完整 Q/DQ,二者的量化类型和量化参数相互独立;
  • SplitSigmoidMul 之间不插入 Q/DQ;
  • 内部节点和边由 GLU Pattern 统一拥有,不再应用独立算子规则;
  • 不对内部 Split 单独应用被动传递规则;
  • Pattern 内部结果 A、B、G 不得被 Pattern 外部节点消费;
  • 当 GLU 子图同时与更小的算子或 Pattern 规则匹配时,由 GLU 作为最大 Pattern 接管。

6.4 Conv/ConvTranspose 与 BatchNormalization 融合

Conv 或 ConvTranspose 后接 BatchNormalization 时,可以形成融合 Pattern:

  • Pattern 输入、权重、可选 bias 和输出遵循对应卷积量化边界;
  • Conv/ConvTranspose 与 BatchNormalization 之间不插入 Q/DQ;
  • BatchNormalization 的参数使用 FP32 initializer;
  • Pattern 内部结果不得被其他节点消费;
  • 可以继续连接规则允许的 Relu 或静态 Clip 融合尾。

6.5 Relu 与 Clip 融合尾

Relu 和静态 Clip 可以作为已定义非被动量化计算 X 的分支局部融合尾:

  • X 与融合尾之间不插入 Q/DQ;
  • 融合尾输出形成新的量化边界;
  • Pattern 只拥有被选择的尾分支;
  • X 的其他分支分别应用各自规则;
  • Relu 和 Clip 继续满足第 5 节各自的量化方式和 zero_point 约束。

6.6 被动传递子图

一个或多个被动传递算子可以形成带分支的被动传递 Pattern:

  • Pattern 内部不插入 Q/DQ;
  • 普通被动传递 Pattern 的所有量化数据出口与入口共享完整量化参数;
  • Split 被动传递 Pattern 的最终出口应用第 5.11 节类型分组与数值检查规则;
  • 原生类型辅助输入和输出不量化;
  • 每个分支分别在离开被动传递 Pattern 后应用下游规则。

6.7 requantize Pattern

当相邻量化区域的量化参数发生变化时,使用以下 Pattern:

upstream Q/DQ -> Identity -> downstream Q/DQ

Identity 只表示该分支发生 requantize,不要求其他共享上游 DQ 的分支同时改变参数。

7. Graph input 与 graph output

ax quant spec 不为 graph input 和 graph output 规定统一的固定数据类型或固定 Q/DQ 形态。

  • graph input 的形式由第一个消费它的算子或 Pattern 决定;
  • graph output 的形式由最后一个产生它的算子或 Pattern 决定;
  • 同一 graph input 可以进入多个分支,各分支分别遵循其算子或 Pattern 规则;
  • 不要求提供或对比量化前的原始 ONNX 模型。

8. 当前不增加的约束

除本文档已经明确规定的内容外,当前不额外限制:

  • 模型使用的具体 opset;
  • 合法 ONNX 属性的取值;
  • 一般 tensor rank;
  • Conv、ConvTranspose、Gemm bias 的 shape 和广播细节;
  • 激活量化类型在模型全局或不同区域之间的一致性;
  • 多输入算子的 scalezero_point 一致性;
  • 静态量化数据是否使用了整数存储类型的最小值。

上述项目仍必须满足模型声明 opset 下的 ONNX 语义。后续如需增加 ax quant spec 约束,应先明确对应算子或 Pattern 的判定边界,再更新本文档。