平台差异说明

在同样的模型量化与部署流程下,不同计算平台在量化策略、输出精度、输入输出处理和部署能力上并不完全一致。

这些差异会直接影响您在 ONNX 模型量化、PyTorch 模型量化、模型编译、quantized.bc 验证、hbm 验证以及板端部署中的选择。 如果一开始没有把平台差异纳入方案设计,后续就容易在量化配置、结果验证和部署适配上反复返工。

如果您当前正在选择量化链路或调优起点,建议先读完本节,再继续进入后续的量化或部署章节。

当前实际使用中,可以先把平台差异按下面两类理解:

  • J6E/M/B:以定点能力为主,量化策略更偏 int8 + int16,部署时更需要关注高精度输出形式、输入输出对齐和定点结果验证。

  • J6H/P/S6P:浮点能力更强,支持更多 float16 / float32 相关能力,量化与部署时通常会引入更多 float16 配置,同时还要额外考虑多核、L2M 和绑核调度等问题。其中 S6P 与 J6H/P 在量化策略和输入输出处理上一致,已知差异有两点:一是 L2 Cache 最大可用容量不同,J6H/P 上为 24MB,S6P 上为 12MB,二是 S6P 平台上 UCP 仅支持 BPU 一个 IP,其他 IP 均不支持。

如果您的当前目标只是先验证模型是否可部署,可以先重点看 量化策略差异 和 输入输出处理差异 两节。

如果您已经进入板端部署或性能调优阶段,还需要继续看 部署能力差异 一节。

平台差异影响哪些决定

不同平台的差异,通常会最先影响下面几类决定:

关注点J6E/M/B 更常见的选择J6H/P/S6P 更常见的选择
ONNX 模型量化起始方式各平台整体流程基本一致,通常先做标准 PTQ / int8 快速验证各平台整体流程基本一致,如需继续看性能或精度边界,再补做 int8 + float16 混合精度等配置验证
PyTorch Calibration 起始配置先看 int8,再逐步增加 int16常从 float16 起步,再为 Conv / MatMul / GEMM 回退 int8 / int16
PyTorch QAT 调优重点通过 int16 提升精度上限,再回退到混合精度用 float16 降低量化难度,再按敏感度补 int16
高精度输出形式
  • J6E/M 上 TAE 不支持浮点输出,模型尾部 GEMM 类算子高精度输出常表现为 int32,再反量化到 float32。
  • J6B 上 TAE 支持浮点输出,模型尾部 GEMM 类算子高精度输出常直接表现为 float32。
模型尾部 GEMM 类算子高精度输出常直接表现为 float32
输入 stride 对齐nv12 常见为 32 对齐nv12 常见为 64 对齐
非图像 tensor 最小内存单元
  • J6E/M 常见为 64 字节。
  • J6B 常见为 128 字节。
常见为 256 字节
部署调度重点更多关注单核结果正确性和一致性还要额外考虑多核、绑核、L2M 和带宽争抢
L2 Cache 最大可用容量不涉及J6H/P 上为 24MB,S6P 上为 12MB

因此,平台差异并不只是“硬件指标不同”,而是会直接改变您在量化配置、结果验证和部署代码中的推荐做法。

量化策略差异

ONNX 模型量化平台差异

如果当前走的是 ONNX 模型量化链路,平台差异首先不体现在整体流程是否不同,而更多体现在精度配置、输出精度和部署适配上。

ONNX 模型的调优流程在各平台上是通用的,整体流程是先通过标准 PTQ 流程完成模型结构验证、量化编译和基础精度验证。

平台差异主要会进一步影响两件事:

  1. 后续是否需要继续做更高精度配置验证,例如 int8 + float16、全 int16 或局部浮点配置。

  2. 编译完成后,输出类型、输入输出对齐和板端部署适配是否需要随平台调整。

J6E/M/B 起步策略

在 J6E/M/B 上,ONNX 模型量化的默认策略以 int8 + int16 混合精度为主,int8 作为默认。

常见的使用顺序是:

  1. 先通过 hb_compile --fast-perf 生成基础 int8 配置,快速拿到板端性能上限参考。

  2. 在 --fast-perf 生成的 yaml 基础上继续调优,若精度不满足需求,通过 quant_config 把敏感算子提升到 int16。

  3. 若难量化模型直接调 int16 仍不满足需求,可考虑先跑全 int16 校准看精度上限,再逐步回退到平衡的混合精度配置。

J6H/P/S6P 起步策略

在 J6H/P/S6P 上,由于浮点能力增强,ONNX 模型量化的默认策略也随之不同。

更常见的起始策略是:

  1. 以“全局 float16 + Conv / GEMM / Matmul / ConvTranspose 回退 int8”作为基础配置。

  2. Resize / GridSample 建议在 quant_config 中显式回退 int8。原因是 int8 在这两个算子上性能更好,起步阶段建议先从 int8 开始尝试。

  3. 若基础配置下精度仍不满足需求,再依据敏感度结果,把局部敏感算子提高到 int16。

PyTorch 模型量化平台差异

如果当前走的是 PyTorch 量化链路,平台差异首先体现在 Calibration 与 QAT 阶段的量化策略起点上,其次也会体现在输出类型和部署适配上。

PyTorch 链路的整体流程在各平台上是通用的,均遵循"浮点模型改造 → Prepare → Calibration → 可选 QAT → Export / Convert → Compile → 板端验证"这一主线,具体参考 PyTorch 模型量化基本流程说明 章节。

平台差异主要会进一步影响两件事:

  1. Calibration 和 QAT 的起始量化策略(是从 int8 + int16 起步,还是从 float16 起步)。

  2. 编译完成后,输出类型、输入输出对齐和板端部署适配是否需要随平台调整。

J6E/M/B 起步策略

在 J6E/M/B 上,PyTorch 模型在进入 QAT 之前的 Calibration 阶段,量化策略通常以 int8 + int16 混合精度为主。

常见的使用顺序是:

  1. 先完成 PyTorch Calibration 或全 int8 验证,确认模型结构、量化链路和基础性能没有明显问题。

  2. 如果精度不满足需求,再通过全 int16 或更高比例的 int16 配置先看精度上限。

  3. 精度达到目标后,再逐步降低 int16 比例,回到更平衡的 int8 / int16 混合精度配置。

  4. 如果 Calibration 已经比较接近浮点结果,再进入 PyTorch QAT 时可优先尝试固定激活 scale 的训练方式。

这一策略的重点不是一开始就把所有算子都提到高精度,而是先看精度上限,再回退高精度比例,最终仍然回到 quantized.bc / hbm 结果验证。

J6H/P/S6P 起步策略

在 J6H/P/S6P 上,由于浮点能力增强,PyTorch Calibration 和后续 PyTorch QAT 的起点通常都会不同。

更常见的起始策略是:

  1. 先以“全局 float16 + Conv / Matmul / GEMM 类算子使用 int8”作为基础配置。

  2. 如果基础配置下精度仍不满足需求,再依据敏感度结果,把局部敏感算子提高到 int16。

  3. 对于大量 vector 类计算,float16 往往比直接堆高 int16 更容易降低量化调优难度。

  4. 若某些中间计算的数值范围超出 float16 表示能力,再有针对性地切回 int16。

这一策略的核心原因是,J6H/P/S6P 上很多 vector 计算中,int16 和 float16 的速度差异并不大,而 float16 通常更有利于降低量化难度和调参成本。

这些差异会直接影响什么

  • 对 ONNX 模型量化:整体 PTQ 流程在各平台上基本通用,平台差异主要体现在 quant_config 平台经验模板。

  • 对 PyTorch Calibration:J6E/M/B 更适合先用全 int8 或全 int16 看精度边界,J6H/P/S6P 更适合把 float16 也纳入基础配置一起验证。

  • 对 PyTorch QAT:J6E/M/B 更强调通过 int16 找到精度上限后再回退,J6H/P/S6P 更强调利用 float16 降低量化难度,再对局部算子补 int16。

  • 对量化配置:J6H/P/S6P 更容易用到新版 qconfig 模板中的全局 float16 配置,而 J6E/M/B 更多是从全局 int8 出发,再对敏感算子配置 int16。

如果您已经确定平台和起始策略,下一步建议结合 模型精度调优指导 和对应链路章节继续细化配置。

输出精度差异

高精度输出形式差异

不同平台上,模型尾部 GEMM 类算子的高精度输出形式可能不同,这会直接影响后处理代码和结果验证方式。

在 J6E/M 上,由于 TAE 硬件不支持浮点输出,如果模型尾部 Conv / Linear / Matmul 等 GEMM 类算子配置为高精度输出,常见表现形式是:

  • 算子本身先输出 int32。

  • 再通过反量化节点转成 float32。

在 J6B/H/P/S6P 上,由于 TAE 硬件支持浮点输出,同样的高精度输出更常直接表现为 float32,无需软件侧反量化。

这意味着如果您原先在 J6E/M 上是按“尾部 int32 + 软件侧反量化”的方式处理输出,迁移到 J6B/H/P/S6P 时,软件侧需要重新确认输出类型是否已经变成浮点。

这会影响哪些环节

  • 对 ONNX 模型量化:模型尾部 Conv / GEMM 类算子默认走高精度输出,实际输出类型会随平台不同(J6E/M 为 int32,J6B/H/P/S6P 为 float32),一致性对比与板端后处理代码需要按平台适配。

  • 对 PyTorch 模型量化:需要确认高精度输出的目标到底是保留 int32 结果,还是直接让模型输出浮点结果。J6B/H/P/S6P 的 TAE 支持 float32 直接输出,J6E/M 则输出 int32 后再软件反量化,两侧路径不同,部署代码需要按平台适配。

  • 对 quantized.bc / hbm 验证:需要确认比较的对象是否是同一种输出类型,避免把输出类型变化误判为精度异常。

  • 对后处理和部署代码:如果代码里假定了固定的 int32 或固定的反量化路径,迁移平台时容易直接出错。

如果您的模型尾部使用了高精度输出:

输入输出处理差异

stride、padding 与 aligned byte size 差异

跨平台迁移时,最常见的问题之一并不是量化本身,而是输入输出 tensor 的内存布局处理不一致。

需要重点关注的差异包括:

  • nv12 输入的 stride 对齐要求不同。

  • 非图像 tensor 的最小内存单元不同。

  • 模型输入输出 tensor 的 stride 和 alignedByteSize 可能变化。

以常见部署场景为例:

  • J6H/P/S6P 上 nv12 输入常要求 64 对齐。

  • J6E/M/B 上 nv12 输入常要求 32 对齐。

  • 非图像 tensor 的最小申请内存单元,J6H/P/S6P 常为 256 字节,J6E/M 常为 64 字节,J6B 常为 128 字节。

这类差异最终都会体现在模型节点属性里的 stride、validShape 和 alignedByteSize 上。

处理建议

建议优先采用下面两种方式,尽量避免写死平台相关处理:

  1. 编译时统一评估是否开启 input_no_padding=True 和 output_no_padding=True。

  2. 部署代码中统一根据 validShape、stride 和 alignedByteSize 准备输入和解析输出,不要依赖 hard code 的固定跨距或固定内存大小。

如果部署代码本身就是按节点属性解析有效数据,那么即使跨平台后 stride 或最小对齐单位变化,通常也不需要再单独改一套逻辑。

这些差异会影响什么

  • 对 ONNX 模型量化:yaml 的 compiler_parameters.extra_params 是否配置 input_no_padding / output_no_padding、nv12 输入的 stride 对齐要求(J6E/M/B 为 32 对齐,J6H/P/S6P 为 64 对齐),会直接影响 quantized.bc ↔ hbm 一致性对比时的输入准备。若板端输入未按平台对齐,可能表现为 hbm 输出与 quantized.bc 不一致。

  • 对 PyTorch 模型量化:调用 hbdk4.compiler.compile() 时同样需要评估 input_no_padding / output_no_padding 两个参数。这些开关会直接改变 qat.bc / quantized.bc / hbm 的输入输出形式,板端输入准备与一致性对比的数据准备都需要与之匹配。

  • 对模型编译:是否开启 input_no_padding、output_no_padding,都会影响后续部署时是否还要手动处理 padding。

  • 对 quantized.bc / hbm 验证:若离线验证和板端输入输出布局不一致,容易把内存布局问题误判成精度问题。

  • 对板端部署:如果输入输出仍按旧平台的 stride、padding 或最小内存单元处理,迁移后最容易出现解析错误或结果异常。

如需继续看这部分的具体接口与处理方式,参考 模型推理应用开发指导、动态输入介绍 和 对齐规则 章节。一致性判读方面,ONNX 链路参考 ONNX 模型部署一致性分析 章节,PyTorch 链路参考 部署一致性分析说明 章节。

pyramid / resizer 输入差异

如果模型输入来自 pyramid 或 resizer,平台差异会更早暴露在输入链路里,而不是等到模型本身运行时报错。

需要重点注意的是:

  • pyramid 输入通常是 stride 动态。

  • resizer 输入通常是 shape 和 stride 都动态。

  • 不同平台上,图像输入的 stride 对齐要求不同,跨平台迁移时需要同步检查配置文件和输入准备逻辑。

例如在 J6H/P/S6P 上,nv12 输入通常按 64 对齐处理,而在 J6E/M/B 上更常见的是 32 对齐。若原先在 J6E/M/B 上的 pyramid 配置文件就是按 32 对齐写死的,迁移到 J6H/P/S6P 时就需要检查是否满足新的对齐要求。

对这类模型,除了检查输入 stride 外,还应同步确认:

  • 训练时输入的数据格式和数值范围。

  • 部署时插入的前处理节点和输入类型设置。

  • 如果在 PyTorch QAT 中对输入使用了 fixed scale,是否仍与当前平台上的输入来源一致。

这类差异会直接影响 PyTorch Calibration、PyTorch QAT、ONNX 模型量化的输入准备与 quantized.bc / hbm 一致性判读、编译配置和板端验证结果。如果输入链路不一致,即使模型本身量化配置正确,也可能出现精度偏差。

如果您的模型使用 pyramid 或 resizer 输入,建议下一步继续结合 模型推理应用开发指导、动态输入介绍 和量化配置章节一起确认。一致性判读方面,ONNX 链路参考 ONNX 模型部署一致性分析 章节,PyTorch 链路参考 部署一致性分析说明 章节。

部署能力差异

J6H/P/S6P 需要额外关注的能力

相较于 J6E/M/B,J6H/P/S6P 还需要额外关注多核、L2M 和绑核调度等部署能力差异。

这些能力不会直接改变量化公式本身,但会明显影响:

  • 模型拆分方式。

  • 编译方式。

  • 运行时调度方式。

  • 板端延时和带宽表现。

多核和绑核

J6H/P/S6P 具备更多 BPU 核心,应用调度空间更大。

在实际使用中,更常见的推荐方式是:

  • 优先按功能拆分模型或拆分 pipeline。

  • 在静态编排后做绑核运行。

  • 尽量减少依赖 HB_UCP_BPU_CORE_ANY 这类会引入额外波动的调度方式。

这样做的原因是,模型的性能收益与模型结构耦合较强,且 BPU 是独占式硬件,单次推理占用多个核后,其他任务的调度空间会显著下降。

L2M

J6H/P/S6P 支持 L2M,可用于缓解多核并发场景下的 DDR 带宽争抢问题。

但 L2M 并不是默认自动生效的能力,通常需要同时完成两件事:

  1. 编译时给模型指定合适的 max_l2m_size。

  2. 运行时通过环境变量为对应核心分配正确的 L2M 大小。

如果编译时指定了 L2M,运行时却没有分到足够空间,推理可能直接失败,或者没有预期的带宽收益。

需要注意的是,J6H/P 与 S6P 上 L2 Cache 的最大可用容量不同,J6H/P 上为 24MB,S6P 上为 12MB。因此在 S6P 上指定 max_l2m_size 与分配运行时 L2M 时,上限需要按 12MB 而不是 24MB 来评估。若沿用 J6H/P 上的编译与运行时配置直接迁移到 S6P,容易因超出上限而失败或拿不到预期收益。

这些差异会影响什么

  • 对模型编译:是否要引入 L2M 会改变编译和部署策略。跨 J6H/P 与 S6P 迁移时,还需要重新评估 max_l2m_size 是否仍在目标平台的上限内。

  • 对板端部署:是否绑核、是否开启抢占、如何分配 L2M,都会直接影响端到端延时稳定性。

  • 对性能评测:J6H/P/S6P 上的评测不再只是单模型 latency,还需要把多核并行、带宽争抢和 pipeline 设计一起纳入考虑。

如果您已经进入部署编排或板端性能优化阶段,建议继续阅读 模型推理应用开发指导 以及对应的性能评测章节。

下一步看哪里

如果您读完本节后,已经明确了自己当前更关心的是哪一类差异,可按下面的方向继续: