quant_config说明

编译模型时可以通过quant_config进行量化参数的配置,支持在model_config、op_config、subgraph_config、node_config四个层面配置模型量化参数:

  • model_config:配置模型总体的量化参数,key是自定义名称。

  • op_config:配置某类算子的量化参数,key是算子的类型。

  • subgraph_config:配置某个子图的量化参数,key是子图的名字。

  • node_config:配置某个具体节点的量化参数,key是节点的名字。

配置时四个层面存在优先级关系,配置粒度越小优先级越高,即优先级model_config < op_config < subgraph_config < node_config,当某个节点同时被多个维度配置时,优先级高的维度最终生效。

注解

由于模型量化编译过程内部会对部分算子进行拆分融合等优化处理,因此可能会导致出现个别拆分算子名称无法和原始模型算子名称完全一致的情况。对于此类算子,在配置node_config时,算子名称应参考过程中生成的optimized_float_model.onnx模型中对应的算子名称。

配置节点计算精度

支持配置 int8/int16/float16 三种计算精度数据类型,关于这三种数据类型的具体说明如下:

  • int8:大部分算子的默认量化类型,一般无需您主动进行配置。

  • int16:请参考下方 int16配置说明。

  • float16:配置为float16类型时,工具内部将仅配置该算子为float16计算精度类型。

注意

对于float16数据类型:

  • 我们不会对float16计算算子上下文算子进行计算广播更新。

  • 不同计算平台对float16算子的支持范围不同,具体支持范围请参考 工具链算子支持约束列表。

  • 如果您将不支持float16计算的算子配置为float16计算,我们会将其回退成float32类型进行计算。

配置全局的模型计算精度

一级参数二级参数参数类型是否必填说明
model_configall_node_typeStringOptional一次性将模型中所有节点的输入设为指定类型,可选配置int16、float16。
model_output_typeStringOptional将模型的输出tensor设为指定类型,可选配置int8、int16。

配置某类算子的计算精度

一级参数二级参数三级参数参数类型是否必填说明
op_configNodeKindqtypeStringOptional配置某一类型的节点的输入数据类型,可选配置int8、int16、float16、float32、dual-int16。
注意
  • 'dual-int16'仅对'Conv'、'MatMul'、'Gemm'、'ConvTranspose'算子生效。

  • 'dual-int16'等价于在node_config中配置{'input0': 'int16', 'input1': 'int16'}。

关于node_config的细节可以参考配置某个节点的计算精度。

配置某个子图的计算精度

一级参数二级参数三级参数参数类型是否必填说明
subgraph_configSubgraphNameinputsListRequired配置封闭子图的输入节点名字,缺少输入节点未构成封闭子图会导致子图提取失败。
outputsListRequired配置封闭子图的输出节点名字。
qtypeStringOptional配置子图中所有节点的输入数据类型,可选配置int8、int16、float16、float32。

配置某个节点的计算精度

一级参数二级参数三级参数参数类型是否必填说明
node_configNodeNameqtypeStringOptional配置指定名称的节点的输入数据类型,可选配置int8、int16、float16、float32。
input0StringOptional配置指定名称的节点的第0个输入数据类型,可选配置int8、int16、float16、float32。
input1StringOptional配置指定名称的节点的第1个输入数据类型,可选配置int8、int16、float16、float32。
注意

qtype, input0, input1均可以用来指定节点的输入数据类型。qtype通常用来指定节点的全部输入数据类型, input0/1用来指定节点的第0/1个输入的数据类型,并且input0/1优先级高于qtype。

配置模型校准参数

支持配置多种校准方法如kl、max等校准阈值统计方法,对于每种校准方法,也支持灵活控制该方法的具体超参配置(如果没有配置则使用默认参数),此外允许您配置一些如per_channel、asymmetric、bias_correction等独立量化功能。

注意

若quant_config不进行任何配置,则默认会尝试多种校准方法并选择其中量化损失最小的校准方法。

配置激活校准参数

一级参数二级参数三级参数参数类型是否必填说明
model_configactivationcalibration_typeString/List[String]Optional激活校准方法,可选配置kl、max,支持设置一个包含多组不同校准方法的List。
num_binInt/List[Int]Optionalkl校准参数,要求num_bin > 128,默认值为1024,支持设置一个包含多组不同num_bin值的List。
max_num_binIntOptionalkl校准参数,要求max_num_bin >= num_bin,默认值为16384。
max_percentileFloat/List[Float]Optionalmax校准参数,参数范围为[0.5, 1.0],默认值为1.0,支持设置一个包含多组不同max_percentile值的List。
per_channelBool/List[Bool]Optionalper-channel量化开启与否,可选配置false、true,默认值为false,支持设置一个同时包含per-channel开启和关闭的List。
asymmetricBool/List[Bool]Optional非对称量化开启与否,可选配置false、true,默认值为false,支持设置一个同时包含非对称开启和关闭的List。

配置权重校准参数

一级参数二级参数三级参数四级参数参数类型是否必填说明
model_configweightbias_correctionnum_sampleIntOptional偏差校正的样本数量,要求num_sample >= 1,默认值为1。
metricStringOptional偏差校正的模型误差度量方法,可选参数cosine-similarity、mse、mae、mre、sqnr以及chebyshev,默认值cosine-similarity。

配置校准参数搜索方法

支持两种不同粒度的校准参数搜索方法:

  • modelwise_search:在模型层面对量化参数进行搜索,该方法允许一次性配置多种校准方法,通过比较量化前后模型输出的量化损失metric(可配置),找到一个量化损失最小的校准方法。

  • layerwise_search:在节点层面对量化参数进行搜索,该方法会根据每个节点量化前后模型输出,计算量化损失metric(可配置),为该节点分配量化损失最小的校准方法。

注意

如果配置了多个校准方法,会默认启动modelwise搜索,从多个候选校准模型中找出最优的量化模型;并从中找出最优的校准方法如果配置了layerwise参数,则启动layerwise搜索方法,逐层搜索最优的量化参数。

配置modelwise搜索方法

一级参数二级参数三级参数参数类型是否必填说明
model_configmodelwise_searchmetricStringOptionalmodelwise搜索的模型误差度量方法,可选参数cosine-similarity、mse、mae、mre、sqnr以及chebyshev,默认值cosine-similarity。

配置layerwise搜索方法

一级参数二级参数三级参数参数类型是否必填说明
model_configlayerwise_searchmetricStringOptionallayerwise搜索的模型误差度量方法,可选参数cosine-similarity、mse、mae、mre、sqnr以及chebyshev,默认值cosine-similarity。

json模板配置示例

如下所示为quant_config的json模板配置示例,包含所有可配置选项,您可参考此模板进行配置。

{
    // 配置模型层面的参数
    "model_config": {
        // 一次性配置所有节点的输入数据类型
        "all_node_type": "int16"/"float16",
        // 配置模型输出的数据类型
        "model_output_type": "int8"/"int16",
        // 激活校准参数配置
        "activation": {
            // 设置激活校准方法,可配置类型:String/List[String]
            "calibration_type": "max"/"kl"/["max", "kl"],
            // 设置kl校准参数,可配置类型:Int/List[Int]
            "num_bin": 1024/2048/[1024, 2048],
            // 设置kl校准参数,可配置类型:Int
            "max_num_bin": 16384,
            // 设置max校准参数,可配置类型:Float/List[Float]
            "max_percentile": 0.99995/1.0/[0.99995, 1.0],
            // 设置per-channel量化开启与否,可配置类型: Bool/List[Bool]
            "per_channel": true/false/[true, false],
            // 设置asymmetric量化开启与否,可配置类型: Bool/List[Bool]
            "asymmetric": true/false/[true, false]
        },
        // 权重校准参数配置
        "weight": {
            // 设置偏差校正
            "bias_correction": {
                // 设置偏差校正的样本数量,可配置类型: Int
                "num_sample": 1,
                // 设置偏差校正的模型误差度量方法,可配置类型: String
                "metric": "cosine-similarity"/"mse"/"mae"/"mre"/"sqnr"/"chebyshev"
            }
        },
        // modelwise搜索配置,若配置多个校准方法会启动modelwise搜索,从多个校准模型中选择最优
        "modelwise_search": {
            // 设置modelwise搜索的模型误差度量方法,可配置类型: String
            "metric": "cosine-similarity"/"mse"/"mae"/"mre"/"sqnr"/"chebyshev"
        },
        // layerwise搜索配置,若配置layerwise参数则会启动layerwise搜索,逐层搜索最优量化参数
        "layerwise_search": {
            // 设置layerwise搜索的模型误差度量方法,可配置类型: String
            "metric": "cosine-similarity"/"mse"/"mae"/"mre"/"sqnr"/"chebyshev"
        }
    },
    // 配置某一类型节点的参数,将op_name修改为节点类型名,例如"Conv","Add","Softmax"...
    "op_config": {
        // 配置某一类型节点的输入数据类型
        "op_name1": {"qtype": "int8"/"int16"/"float16"},
        "op_name2": {"qtype": "int8"/"int16"/"float16"}
    },
    // 配置某个子图的参数,将subgraph_name修改为自定义子图名,将input_node/output_node修改为子图输入/输出节点名称,例如"Conv_0","Add_1"...
    "subgraph_config": {
        // 配置某个子图中所有节点的输入数据类型
        "subgraph_name1": {
            "inputs": ["input_node1", "input_node2"],
            "outputs": ["output_node1"],
            "qtype": "int8"/"int16"/"float16"
        }
    },
    // 配置某个节点的参数,将node_name修改为节点名称,例如"Conv_0","Add_1"...
    "node_config": {
        // 配置某个节点的输入数据类型
        "node_name1": {"qtype": "int8"/"int16"/"float16"},
        "node_name2": {"qtype": "int8"/"int16"/"float16"}
    }
}

int16配置说明

在模型转换的过程中,模型中的大部分算子都会被量化到int8进行计算,而通过配置 quant_config 参数, 可以详细指定某个op的输入/输出数据类型为int16计算(具体支持的算子范围可参考 工具链算子支持约束列表,基本原理如下:

在您配置了某个op输入/输出数据类型为int16后,模型转换内部会自动进行op输入输出上下文(context)int16配置的更新和检查。 例如,当配置op_1输入/输出数据类型为int16时,实际上潜在同时指定了op_1的上/下一个op需要支持以int16计算。 对于不支持的场景,模型转换工具会打印log提示该int16配置组合暂时不被支持并回退到int8计算。

平台经验模板

上文字段规范给出了 quant_config 各字段的通用配置方法。实际使用时,各平台的量化策略起点不同,本节按平台整理一组经验模板供起步参考,并列出常见误区。具体差异维度和链路选择建议参考 平台差异说明 章节。

J6E/M 与 J6B 经验模板

在 J6E/M 与 J6B 上,推荐以"int8 + int16 混合精度"作为起步策略,int8 作为默认。基础起步可先通过 hb_compile --fast-perf 生成 int8 配置,若精度不满足需求,再针对量化敏感的算子或节点通过 quant_config 提升到 int16。

参考的 quant_config json 模板如下:

{
  "op_config": {
    "Softmax": {"qtype": "int16"},
    "LayerNormalization": {"qtype": "int16"}
  },
  "node_config": {
    "Conv_0": {"qtype": "int16"}
  }
}

其中 int8 是大部分算子的默认量化类型,一般无需通过 model_config.all_node_type 主动配置。直接在 op_config 中按算子类型批量提升敏感算子到 int16,或在 node_config 中按具体节点名精细控制即可。示例中的 Softmax / LayerNormalization / Conv_0 仅为常见量化敏感算子的示范,实际使用时应结合模型精度评估结果替换为您模型中的实际算子类型或节点名称。

若难量化模型仍不满足需求,可考虑跑一次精度上限配置查看精度上限,再逐步回退到平衡的混合精度配置。J6E/M 与 J6B 上的精度上限配置为 all_node_type 全局 int16 叠加 Conv / MatMul / ConvTranspose / Gemm 使用 dual-int16,对应模板如下:

{
  "model_config": {
    "all_node_type": "int16"
  },
  "op_config": {
    "Conv": {"qtype": "dual-int16"},
    "MatMul": {"qtype": "dual-int16"},
    "Gemm": {"qtype": "dual-int16"},
    "ConvTranspose": {"qtype": "dual-int16"}
  }
}

其中 dual-int16 仅对 Conv、MatMul、Gemm、ConvTranspose 算子生效,等价于把这些算子的两个输入都配置为 int16,具体机制参考本页 配置某类算子的计算精度 小节。

J6H/P 经验模板

在 J6H/P 上,推荐以"全局 float16 + Conv / GEMM / MatMul / ConvTranspose 回退 int8"作为起步策略。相应的 quant_config json 模板如下:

{
  "model_config": {"all_node_type": "float16"},
  "op_config": {
    "Conv": {"qtype": "int8"},
    "ConvTranspose": {"qtype": "int8"},
    "MatMul": {"qtype": "int8"},
    "Gemm": {"qtype": "int8"},
    "Resize": {"qtype": "int8"},
    "GridSample": {"qtype": "int8"},
    "Sin": {"qtype": "float32"},
    "Cos": {"qtype": "float32"}
  }
}
注解
  • 为什么要显式回退 Resize / GridSample:依据经验,一般情况下 Resize/ GridSample 仅需设置为 int8 即可,且性能相较 int16/float16 会友好很多,如果后续基于敏感度分析需要配置更高精度,建议您基于上下游算子的量化精度从 int16 或 float16 中进行选择尝试。例如 Resize + Conv 结构,Resize 应优先尝试 int16 以适配 Conv 的定点化输入。

  • 为什么 Sin / Cos 要显式配置为 float32:Sin / Cos 属于对精度较敏感的算子,推荐使用全局 float32 精度。

常见误区

使用 quant_config 时,常见误区如下:

  • 配置了 quant_config 但工具因算子约束回退:工具最终会以算子约束为准,若配置的 qtype 超出算子输入/输出支持范围,工具会自动回退到支持的类型(例如从 float16 回退到 int8,或从 BPU 回退到 CPU),且会在 hb_compile.log 中给出提示。判断 qtype 是否真正生效应以 hb_compile.log 中的 Output Data Type 列为准,而不是 yaml / json 里的配置。

  • Resize / GridSample 未显式回退 int8 导致性能不佳:在 J6H/P 全 float16 起步策略下,Resize / GridSample 起步阶段建议先从 int8 开始尝试(int8 上性能更好)。建议将这两个算子的 qtype 显式配置为 int8。

  • 尾部 BPU 可加速算子被回退到 CPU:为保证精度,模型尾部 Conv 默认以 int32 / float32 高精度输出,其后跟随的 BPU 可加速算子(例如 ReLU、Add)会默认回退到 CPU。若性能优先且可接受一定精度损失,可通过 quant_config 中的 op_config 或 node_config 显式指定这些算子的 qtype,强制其运行在 BPU 上。代价是可能引入一定量化损失,需要结合 模型精度评估 章节的数据集精度验证权衡。