1. 支持的网络模型
Qualcomm®神经处理SDK支持下表所列的网络模型。
有关支持的运行时和单个图层类型的限制和约束的详细信息,请参阅 限制 。
GPU运行时中支持的所有层对两种GPU模式都有效:GPU_FLOAT32_16_HYBRID和GPU_FLAAT16。GPU_FLOAT32_16_HYBRID-数据存储以半浮点数完成,计算以全浮点数完成。GPU_FLOAT16-数据存储和计算都是在半浮点中完成的。
可以在ONNX Operator Support找到支持的ONNX操作列表。
Converters Equivalent
- COMMAND_LINE:表示操作是通过转换过程中提供的命令行参数支持的,而不是作为源框架模型的一部分。有关更多详细信息,请参阅源框架的转换器帮助。
- INFERRED:表示源框架没有Op的具体定义。但是,转换器模式会匹配一系列Op,以映射到列出的QNN Op。
- --:表示没有相应的源框架操作,或者相应的操作尚不受支持。
Runtime Support
YES:运行时有Op的实现。
详细参考:Snapdragon 神经处理引擎 SDK (qualcomm.com)
2.支持的 ONNX 操作
snpe-onnx-to-dlc 目前支持以下运算符和参数
详细参考表格:Snapdragon Neural Processing Engine SDK (qualcomm.com)
3.量化模型与非量化模型
概述
非量化DLC文件使用网络参数的32位浮点表示。
量化的DLC文件使用网络参数的定点表示,通常为8位权重【weight】和8或32位偏差【biase】。不动点表示与Tensorflow量化模型中使用的不动点表示相同。
ONNX
snpe-onnx-to-dlc的默认输出是非量化模型。这意味着所有网络参数都保留在原始ONNX模型中存在的32位浮点表示中。要将模型量化为8位定点,请参阅 SNPE-DLC-QUANTIZE。请注意,打算使用 snpe-dlc-quantize 进行量化的模型必须将其批处理维度设置为1。通过在初始化过程中调整网络大小,可以在推理过程中使用不同的批处理维度。
TensorFlow
snpe-onnx-to-dlc的默认输出是非量化模型。这意味着所有网络参数都保留在原始TensorFlow模型中存在的32位浮点表示中。要将模型量化为8位定点,请参阅 SNPE-DLC-QUANTIZE 。 请注意,打算使用 snpe-dlc-quantize 进行量化的模型必须将其批处理维度设置为1。通过在初始化过程中调整网络大小,可以在推理过程中使用不同的批处理维度。
在量化或非量化模型之间进行选择
摘要
运行 | 量化 DLC | 非量化 DLC |
---|---|---|
中央处理器CPU | 兼容的。如果启用了CPU定点模式,则可以将模型直接传递给运行时。否则,运行时会对模型进行反量化,从而增加网络初始化时间。准确性可能会受到影响。 | 兼容的。该模型是此运行时的本机格式。模型可以直接传递给运行时。可能比量化模型更准确。 |
图形处理器GPU | 兼容的。运行时对模型进行反量化,增加了网络初始化时间。准确性可能会受到影响。 | 兼容的。该模型是此运行时的本机格式。模型可以直接传递给运行时。可能比量化模型更准确。 |
DSP | 兼容的。该模型是DSP运行时的原生格式。模型可以直接传递给运行时。精度可能与非量化模型不同 | 兼容的。该模型由运行时量化,增加了网络初始化时间。精度可能与量化模型不同。 |
AIP | 兼容的。该模型采用AIP运行时支持的格式。模型可以直接传递给运行时。 | 不相容的。AIP运行时不支持非量化模型。 |
详细信息
-
中央处理器
-
默认情况下,CPU 使用浮点 (非量化) 网络参数。
-
支持将量化的 DLC 文件与 CPU 运行时一起使用。要直接使用量化网络参数, 应启用 CPU 定点模式。如果未启用,网络初始化时间将 急剧增加,因为 Qualcomm® 神经处理 SDK 将自动 对网络参数进行去量化,以便在 CPU 上运行。
-
DLC 文件的量化确实会引入噪声,因为量化是有损的。
-
执行期间的网络性能不受 选择量化和非量化 DLC 文件。
-
-
图形处理器
-
GPU 始终使用浮点 (非量化) 网络参数。
-
支持将量化的 DLC 文件与 GPU 运行时一起使用。网络 初始化时间将显著增加,因为 Qualcomm® 神经处理 SDK 将自动 对网络参数进行去量化,以便在 GPU 上运行。
-
如果担心网络初始化时间,建议 对 GPU 使用非量化 DLC 文件(默认)。
-
DLC 文件的量化确实会引入噪声,因为量化是有损的。
-
执行期间的网络性能不受 选择量化和非量化 DLC 文件。
-
-
DSP
-
DSP 始终使用量化的网络参数。
-
支持在 DSP 上使用非量化 DLC 文件。网络 初始化时间将显著增加,因为 Qualcomm® 神经处理 SDK 将自动 量化网络参数以便在 DSP 上运行。
-
一般建议使用量化的 DLC 文件来运行 在 DSP 上。除了更快的网络初始化时间外, 使用量化模型还可以减少 初始化,并减小 DLC 文件大小。
-
-
AIP
-
AIP 运行时始终使用量化的网络参数。
-
通过 snpe-dlc-quantize 是生成 HTA 子网的二进制文件。
-
不支持将非量化 DLC 文件与 AIP 运行时一起使用。
-
HTA 子网使用 DLC 中的量化参数。
-
HNN (Hexagon NN) 子网使用 DSP 运行时也是如此。
-
-
平衡 DLC 文件大小、网络初始化时间和准确性
-
如果网络主要在 GPU 和 CPU 上运行,则为 建议在 发展。如果量化模型提供了足够的准确度,则 它可以直接用于使用 CPU 定点模式的 CPU。对于 GPU, 它的使用可能会以增加网络初始化为代价 时间。这样做的好处是 DLC 文件要小得多。两者之间的权衡 accuracy、network initialization time 和 DLC 文件大小为 特定于应用程序。
-
如果网络主要在 DSP 上运行,则 使用非量化模型。如前所述,它将 显著增加网络初始化时间和 DLC 文件 大小,但不会提供准确性优势。
-
量化算法
本节介绍Qualcomm®神经处理SDK中使用的量化算法背后的概念。snpe-dlc量化使用这些概念,高通®神经处理SDK在使用DSP运行时也使用这些概念进行输入量化。
概述
注:Qualcomm®神经处理SDK支持多种量化模式。这里描述了量化的基本原理,无论模型如何。有关更多信息,请参见量化模型。
-
量化将浮点数据转换为 Tensorflow 样式的 8 位定点格式。
-
满足以下要求:
-
涵盖了所有输入值。
-
强制要求最小范围 0.0001。
-
浮点零是完全可表示的。
-
-
量化算法输入:
- 要量化的浮点值集。
-
量化算法输出:
-
一组 8 位定点值。
-
编码参数:
-
encoding-min :可表示的最小浮点值(由固定点值 0 表示)。
-
encoding-max : 可表示的最大浮点值(由固定点值 255 表示)。
-
-
-
算法
-
计算输入数据的真实范围 (min, max)。
-
计算 encoding-min 和 encoding-max。
-
量化输入浮点值。
-
输出:
-
固定点值
-
encoding-min 和 encoding-max 参数
-
-
量化示例
-
输入:
- 输入值 = [-1.8, -1.0, 0, 0.5]
-
encoding-min 设置为 -1.8,encoding-max 设置为 0.5
-
编码范围为 2.3,大于所需的 0.0001
-
encoding-min 调整为 −1.803922,encoding-max 调整为 0.496078 至 使零精确可表示
-
步长 (delta 或 scale) 为 0.009020
-
输出:
- 量化值为 [0, 89, 200, 255]
非量化示例
-
输入:
-
量化值 = [0, 89, 200, 255]
-
编码最小值 = −1.803922,编码最大值 = 0.496078
-
-
步长为 0.009020
-
输出:
- 反量化值 = [−1.8039, −1.0011, 0.0000, 0.4961]
偏移比特宽度Bias BitWidth
Qualcomm®神经处理SDK目前支持权重和偏差的默认量化位宽为8。然而,通过指定 SNPE-DLC-QUANTIZE的命令行选项"--bias_bitwidth 32",可以覆盖偏置位宽以使用32位量化。对于某些模型,使用32位偏置可能会使准确性略有提高。不幸的是,很难预测哪些模型会从中受益,因为模型架构、权重分布等都会对量化性能产生影响。
激活 BitWidth
® Qualcomm 神经处理 SDK 还支持量化 bitwidth 为 16 以进行激活。(见注释)
要启用 16 位定点推理,请将量化位宽指定为 激活设置为 16,同时保持权重为 8。将 命令行选项:"--act_bitwidth 16 --weights_bitwidth 8" 更改为 snpe-dlc-quantize 将生成 16 位的量化模型文件 activations 和 8 位权重。
建议使用 UserBuffer TF16 作为 效率更高。在这种情况下,Qualcomm® Neural Processing SDK 的用户需要量化/去量化 如果使用浮点数据,则自行输入/输出数据。什么时候 使用 snpe-net-run 进行测试,命令行选项 "--userbuffer_tfN 16" 可以 用于选择 UserBuffer TF16 模式。ITensor 和 UserBuffer 浮点 format 仍然可以用于 16 位整数推理,但效率较低 内部应用的量化。
打包的 4 位量化
在打包的 4 位量化中,两个 4 位量化张量可以存储在单个 8 位缓冲区中。下半食 存储第一个值,而较高的 Nibble 存储第二个值。这可以通过提供 "--pack_4_bit_weights" 来自 snpe-dlc-quantize。对于量化值 (10, 4),其中 unpacked 和 packed 表示形式如下。
-
解压缩 = (0000 1010, 0000 0100)
-
包装 = (0100 1010)
在每通道/每行量化的情况下,量化值将沿每个通道/行打包。对于大小为 (3,3,3,32) 包含 32 个输出通道,每个通道 27 个值,则解包和打包的表示将采用 每个通道 27 个量化值的内存量如下。
-
解包 = (3*3*3) = 27 字节
-
打包 = ceil((3*3*3)/2) = 14 字节
注意打包的 4 位张量以 QNN_DATATYPE_SFIXED_POINT_4/QNN_DATATYPE_UFIXED_POINT_4 数据类型存储,而 解压缩的 4 位张量与 QNN_DATATYPE_SFIXED_POINT_8/QNN_DATATYPE_UFIXED_POINT_8 数据类型一起存储。请参考 添加到后端补充中,以查找支持 4 位打包张量的运算。
量化模式
® Qualcomm 神经处理 SDK 支持多种量化模式,区别在于如何 Quantization 参数。
默认量化模式
默认模式已在上面描述,并使用真正的 min/max 数据被量化,然后将范围调整为 确保最小范围并确保 0.0 完全可量化。
增强的量化模式
增强的量化模式(通过使用 "use_enhanced_quantizer" 参数用于 snpe-dlc-quantize)使用 算法来尝试确定一组更好的量化参数 提高准确性。该算法可能会选择与 默认量化器,在某些情况下,它可能会设置范围,以便 一些原始权重和/或激活不能归入其中 范围。但是,此范围确实比简单的 使用真正的 Min/Max。可以启用增强的量化器 通过附加 "weights" 来独立地用于权重和激活 或选项后的 "activations"。
这对于权重和/或激活可能 有 "长尾巴"。(假设一个范围的大多数值介于 -100 和 1000,但有一些值远大于 1000 或远小于 -100。 在某些情况下,可以忽略这些长尾,范围 -100, 1000 可以比全系列更有效地使用。
增强型量化器仍强制执行最小范围,并确保 0.0 为 完全可量化。
调整后的权重量化模式
此模式仅用于将权重量化为 8 位固定 point(通过使用 snpe-dlc-quantize 的 "use_adjusted_weights_quantizer" 参数调用),它使用 调整的 Min 或 Max 被量化的数据,而不是 True Min/Max 或不包括长尾的 min/max。这已被验证为 能够专门为降噪模型提供精度优势。用 此量化器,如果满足以下条件,则 Max 将扩大或减少 min 必要。
调整后的权重量化器仍强制执行最小范围,并确保 0.0 是完全可量化的。
增强的量化技术
量化可能是一个难以解决的问题,因为存在无数 训练技术、模型架构和层类型。在 an attempt 为了缓解量化问题,两种新的模型预处理技术 已添加到 SNPE-DLC-QUANTIZE 中,这可能会提高 量化精度。
引入的新技术是 CLE (Cross Layer Equalization)。
CLE 的工作原理是通过以下方式扩展网络中的卷积权重范围 利用激活函数的 scale-equivariance 属性。在 此外,该工艺还吸收了可能由以下原因引起的高偏差 从一个卷积层到后续卷积的权重缩放 层。
增强的量化技术:限制
在许多情况下,CLE 可以使量化模型恢复到接近 它们的原始浮点精度。有一些 当前算法的注意事项/限制:
CLE 对存在于 单个分支(输出不能被多个 OP 使用)。这 匹配的操作模式(r=必需,o=可选)为:
Conv(r)->Batchnorm(r)->activation(o)->Conv(r)->Batchnorm(r)->activation(o)
Conv(r)->Batchnorm(r)->activation(o)->DepthwiseConv(r)->Batchnorm(r)->activation(o)->Conv(r)->Batchnorm(r)->activation(o)
CLE 算法目前仅支持 Relu 激活。任何 Relu6 激活将自动更改为 Relu 和任何激活 否则将导致算法忽略前面的 卷积。通常,从 Relu6->Relu 的转换是无害的,并且 不会导致精度降低,但某些型号可能会 准确率略有下降。在这种情况下,CLE 可以 仅将精度恢复到该降级水平,而不是原始水平 浮点精度。
CLE 需要 batchnorm(特别是可检测的 batchnorm beta/gamma data) 在转换为 DLC 之前存在于原始模型中 要运行的完整算法并重新获得最大准确性。为 Tensorflow,即使使用 折叠的 batchNorm 中,只要折叠不折叠参数 引入卷积的静态权重和偏差中。如果未检测到 必填信息您可能会看到一条类似于以下内容的消息: "HBA 量化算法的模型无效。"这表示 算法将仅部分运行,并且可能会出现准确性问题 目前。
要运行 CLE,请将 "--optimizations cle" 传递给 snpe-dlc-quantize。
原始转换的 float 模型应始终用作 snpe-dlc-quantize 的将量化模型传递回量化器不是 支持,将导致未定义的行为。
有关算法的更多信息,请参见 此处:https://arxiv.org/abs/1906.04721
量化影响
量化模型和/或在量化运行时中运行模型(如 DSP) 可能会影响准确性。某些模型在量化时可能效果不佳, ,并且可能会产生不正确的结果。用于衡量 对进行分类的模型上的量化通常为 "Mean Average Precision"、"Top-1 Error" 和 "Top-5 Error" 的命令。这些指标 发布在各种模型的 Qualcomm® 神经处理 SDK 发行说明中。
混合精度和 FP16 支持
Mixed Precision 允许指定不同的位宽(例如 8 或 16)或 数据类型(整数或浮点)用于同一图形中的不同操作。 当激活精度或 数据类型在连续操作之间是不同的。图形可以混合使用浮点 和定点数据类型。每个操作的权重精度可以不同,而 激活。但是,对于特定操作,要么是所有输入、输出和参数 (weights/biases) 将为浮点格式,或者全部为 fixed-point 格式。
量化覆盖
如果在模型转换期间提供了--quantization_overrides选项,则用户可以提供一个包含用于量化的参数的json文件。这些将与模型一起缓存,可用于覆盖从转换中携带的任何量化数据(例如TF伪量化),或在snpe-dlc量化中的正常量化过程中计算的量化数据。要在snpe-dlc量化期间覆盖参数,必须传递选项override_rams,并使用缓存值。json格式是根据AIMET规范定义的,可以在下面找到。
json中有两个部分,一个是用于覆盖运算符输出编码的部分,称为"activation_encodings",另一个是覆盖参数(权重和偏置)编码的部分。两者都必须存在于文件中,但如果不需要覆盖,则可以为空。
包含当前支持的所有选项的示例:
{
"activation_encodings": {
"Conv1:0": [
{
"bitwidth": 8,
"max": 12.82344407824954,
"min": 0.0,
"offset": 0,
"scale": 0.050288015993135454
}
],
"input:0": [
{
"bitwidth": 8,
"max": 0.9960872825108046,
"min": -1.0039304197656937,
"offset": 127,
"scale": 0.007843206675594112
}
]
},
"param_encodings": {
"Conv2d/weights": [
{
"bitwidth": 8,
"max": 1.700559472933134,
"min": -2.1006477158567995,
"offset": 140,
"scale": 0.01490669485799974
}
]
}
}
在"activation_encodings"下,名称(例如"Conv1:0")代表 应覆盖量化的 output Tensor names。下 "param_encodings" 名称表示 将指定编码。常见情况的简要分析 参数:
-
bitwidth (int, required) - 用于量化的位宽。注意 这与运行时的现有 bitwidth 支持非常匹配 模型将运行。
-
max (float, required) - 分配中的最大数字,或 所需范围。
-
min (float, required) - 分配中的小数或 所需范围。
-
offset (int) - 表示零点的整数偏移量(即 点,其中 0 正好表示)。
-
scale (float) - 表示整数大小除以 所需的分布范围。
请注意,它不需要提供比例(也称为 delta) 和 offset (零点) 的 Delta) 进行转换。如果提供它们,它们将被使用, 否则,它们将根据提供的 bitwidth、min 和 max 参数。
注 : 用于激活的量化位宽 16,支持 Snapdragon 865/765 在某些运行时及更高版本,目前未启用 适用于所有 OPS。
Float16(半精度)还可以将整个模型转换为 FP16 或在 FP16 和 FP32 之间进行选择 浮点运算的数据类型,以防混合了浮点和整数运算的混合精度图形。这 下面介绍了使用混合精度的不同模式。
-
No override:如果编码文件没有给出 --quantization_overrides 标志,则所有激活都按照 --act_bitwidth (默认 8),参数按照 --weight_bitwidth/--bias_bitwidth (默认 8/8) 进行量化 分别。
-
完全覆盖:如果给出 --quantization_overrides 标志以及指定 中所有运算编码的编码文件 模型。在这种情况下,根据 JSON 设置所有运算的位宽,根据编码定义为整数/浮点数 文件(json编码中为dtype='int'或dtype='float')。
-
部分覆盖:如果给定 --quantization_overrides 标志以及指定部分编码的编码文件 (即某些 Ops 缺少编码),将发生以下情况。
-
编码在 json 文件中不可用的图层的编码方式与 no override 情况相同 即定义为整数,其位宽定义为 --act_bitwidth/--weight_bitwidth/--bias_bitwidth (或其默认值 8/8/8)。 对于某些操作(Conv2d、Conv3d、TransposeConv2d、DepthwiseConv2d、FullyConnected、MatMul),即使任何 output/weights/bias 在编码文件中指定为 float,则这三个都将被 float 覆盖。 使用的 float bitwidth 将与 encodings 文件中覆盖张量的 float bitwidth 相同。我们 在这种情况下,还可以手动控制 bias 张量的 bitwidth (如果编码中没有它的编码) json 和 present for output/weights),并使用 --float_bias_bitwidth (16/32) 标志。
-
编码在 json 中可用的图层的编码方式与完全覆盖大小写相同。
-
我们展示了一个包含3个Conv2d操作的网络示例json。第一和第三卷积运算是INT8,而第二卷积运算被标记为FP32。FP32操作(即conv2_1)夹在"activation_encodings"中的两个INT8操作之间,因此转换操作将插入FP32操作之前和之后。conv2_1的相应权重和偏差也在JSON的"param_encoding"中标记为浮点。
{
"activation_encodings": {
"data_0": [
{
"bitwidth": 8,
"dtype": "int"
}
],
"conv1_1": [
{
"bitwidth": 8,
"dtype": "int"
}
],
"conv2_1": [
{
"bitwidth": 32,
"dtype": "float"
}
],
"conv3_1": [
{
"bitwidth": 8,
"dtype": "int"
}
]
},
"param_encodings": {
"conv1_w_0": [
{
"bitwidth": 8,
"dtype": "int"
}
],
"conv1_b_0": [
{
"bitwidth": 8,
"dtype": "int"
}
],
"conv2_w_0": [
{
"bitwidth": 32,
"dtype": "float"
}
],
"conv2_b_0": [
{
"bitwidth": 32,
"dtype": "float"
}
],
"conv3_w_0": [
{
"bitwidth": 8,
"dtype": "int"
}
],
"conv3_b_0": [
{
"bitwidth": 8,
"dtype": "int"
}
]
}
}
json中不存在的操作将被假定为定点,位宽将分别根据-act_bitwidth/-weight_bitwidth/-bias_bitwidth进行选择。
{
"activation_encodings": {
"conv2_1": [
{
"bitwidth": 32,
"dtype": "float"
}
]
},
"param_encodings": {
"conv2_w_0": [
{
"bitwidth": 32,
"dtype": "float"
}
],
"conv2_b_0": [
{
"bitwidth": 32,
"dtype": "float"
}
]
}
}
以下量化混合精度图将基于上述JSON生成。请注意,转换操作是适当添加的,用于在float和int类型之间进行转换,反之亦然。
每通道量化覆盖
每通道量化应用于作为Conv消费者(Conv2d、Conv3d、TransposeConv2d、DepthwiseConv2d)权重输入的张量。本节提供了手动覆盖这些基于卷积的运算权重张量的每个通道编码的示例。当我们为给定的张量提供多个编码(等于通道数量)时,将使用每通道量化。我们看到以下情况的卷积权重示例。
情况1:没有每通道量化的非对称编码
{
"features.9.conv.3.weight": [
{
"bitwidth": 8,
"is_symmetric": "False",
"max": 3.0387749017453665,
"min": -2.059169834735364,
"offset": -103,
"scale": 0.019991940143061618
}
]
}
情况2:具有3个输出通道的每通道量化编码
{
"features.8.conv.3.weight": [
{
"bitwidth": 8,
"is_symmetric": "True",
"max": 0.7011175155639648,
"min": -0.7066381259227362,
"offset": -128.0,
"scale": 0.005520610358771377
},
{
"bitwidth": 8,
"is_symmetric": "True",
"max": 0.5228064656257629,
"min": -0.5269230519692729,
"offset": -128.0,
"scale": 0.004116586343509945
},
{
"bitwidth": 8,
"is_symmetric": "True",
"max": 0.7368279099464417,
"min": -0.7426297045129491,
"offset": -128.0,
"scale": 0.005801794566507415
}
]
}
注意:每通道量化必须使用偏移量==-2^(位宽-1)的对称表示。每个通道总是有is_symmetric=True。