专栏算法工具链【地平线J6工具链入门教程】J6B计算平台部署指南

【地平线J6工具链入门教程】J6B计算平台部署指南

芯链情报局2025-10-17
459
0

1. 前言

本文旨在提供 J6B 计算平台的部署指南,将会从硬件、软件两部分进行介绍,本文整理了我们推荐的使用流程,和大家可能会用到的一些工具特性,以便于您更好地理解工具链。某个工具具体详细的使用说明,还请参考用户手册。

2. J6B硬件配置

 

 

BPU

DSP

 

 

算力

TAE浮点输出

VAE浮点

VPU

SPU 

APM

 

J6E

80T

N

N

Y

Y

Y

Q8*1

J6M

128T

N

N

Y

Y

Y

Q8*1

J6P

560T

Y

Y

Y

Y

Y

Q8*2

J6H

420T

Y

Y

Y

Y

Y

Q8*2

J6B-Base

18T

Y

Y

N

N

Y

V130*1

 

 

 

BPU内部器件:

  • TAE:BPU 内部的张量加速引擎,主要用于 Conv、MatMul、Linear 等 Gemm 类算子加速,J6B 新增浮点输出支持(模型中间层支持 fp16 输出,模型输出层支持 fp32 输出)
  • AAE:Pooling、Resizer、Warping 等偏专用单元的集合,其中 Warping 可用于加速 Gridsample 等算子
  • DTE:BPU 内部的数据排布变换引擎,支持各种维度的高效变换
  • VAE:BPU 内部的 SIMD 向量加速引擎,可用于加速 Add、Mul、查表等 Vector 计算,J6B 新增浮点支持
  • VPU:BPU 内部的 SIMT 向量加速单元,J6EM 可用于实现 Quantize、Dequantize 等算子,J6B 没有该硬件
  • SPU:BPU 内部的 RISC-V 标量加速单元,J6EM 可用于实现 TopK 等算子,J6B 没有该硬件,仅有 APM
  • APM:BPU 内部另一块 RISC-V 标量加速单元,主要用于 BPU 任务调度等功能

3. J6工具链简介

3.1 模块架构图

 

  • PTQ:J6 工具链基于horizon_tc_ui 包封装的 hb_compile 命令行工具,提供 ONNX 模型 PTQ 全流程转换能力,其内部会先调用 hmct 包实现模型解析、图优化、校准功能,再调用 hbdk4_compiler 包实现模型的定点化和编译功能;
  • QAT:J6 工具链基于 horizon_plugin_pytorch 包提供量化感知训练能力;
  • HBDK:J6 工具链编译器,基于hbdk4_compiler 包提供模型定点化、图修改、模型编译、静态 perf 等功能;
  • 高效模型算法包:J6 工具链基于 horizon-torch-samples 包,以源码开放形式提供了多场景参考算法,这些模型基于开源数据集训练,模型结构贴合地平线芯片进行了高效且用户友好的设计,并基于 QAT 链路实现了模型的量化转换;
  • UCP:J6 工具链统一计算平台,通过一套统一的异构编程接口实现了对 J6 计算平台相关计算资源的调用,提供视觉处理、模型推理、高性能计算库、自定义算子插件开发等功能;
  • AI-Benchmark:J6 工具链基于预编译好模型提供的嵌入式工程示例,可实现模型的性能评测和精度评测。

3.2 两套模型转换链路

 

J6 工具链支持 PTQ(训练后量化)、QAT(量化感知训练)两套模型转换链路,其特性和优缺点如下:

  • PTQ:基于 hb_compile 命令行工具转换模型,配置好 yaml、校准数据集后,可一步实现模型的图优化、校准、量化、编译全流程。该量化方式快捷易用,但仅基于数学统计方式的离线量化不利于模型迭代,且可能会触发难以解决的 corner case,因此在量产项目中通常用于早期评测和简单模型的量化。
  • QAT:在 PyTorch 开源框架上,基于 plugin 插件的形式提供模型量化能力,并调用 hbdk 编译器的 API 实现模型的定点化和编译。该链路支持模型校准后进一步的 finetune 训练,虽然上手难度和训练成本都较高,但精度上限也更高,更利于模型迭代优化,是量产项目中的更优选择。

3.3 工具链推荐使用流程

鉴于两条量化链路的特性,我们建议的工具链使用流程如下:

 

 

  1. Step1:先导出浮点 ONNX 模型(opset10~19),并基于 PTQ 链路进行快速的模型结构验证,全 int8 性能上限验证;若该性能符合预期,则可以精调 PTQ,若最终精度/精度都可同时满足预期,则可进行板端部署。
  2. Step2:如果遇到 PTQ 无法解决的精度 corner case,则需要转到 QAT 链路进行量化。依然建议先进行模型结构验证和全 int8 性能上限验证;若该性能符合预期,则优先在全 int16 配置下将精度训练至符合预期,然后再降低 int16 比例,实现 int8/int16/fp16 混合精度下的性能/精度调优,最后进行板端部署。

在以上推荐链路中:

  1. PTQ 链路的模型结构验证和标准量化,可在 X86 端参考本文 4.2 节使用 hb_compile 命令行工具;
  2. 模型性能分析和验证,可在 X86 端参考本文 6.4 节《静态perf》使用 hbm_perf 接口生成 html 分析文件,可在板端参考本文 8.2.1 节使用 hrt_model_exec 工具;
  3. 模型推理,可在 X86 端参考用户手册《训练后量化-PTQ转换工具-HBRuntime推理库》,可在板端参考本文第 8 章《模型板端部署》使用 UCP 推理接口;
  4. 模型性能/精度调优,请见后续文章的详细介绍。

4. PTQ链路

4.1 模型转换流程

4.2 hb_compile工具

hb_compile 为 PTQ 模型转换的命令行工具,支持以下 3 种使用方式:

 

hb_compile --march nash-b -m xxx.onnx

模型检查,用于早期确认是否有 J6B 不支持的结构或算子

hb_compile --march nash-b -m xxx.onnx --fast-perf

 

快速性能评测,用于验证性能上限,工具会生成在板端运行性能最高的模型,工具内部主要会执行:

  • 将 BPU 可执行算子算尽可能地运行在 BPU 上(int8)

  • 删除模型首尾部可删除算子,如 Quantize/Dequantize、Cast、Transpose、、Reshape等

该功能执行后会在 .fast_perf 隐藏文件夹下生成一个 yaml 文件,您可以在其基础上做二次修改复用。

hb_compile -c config.yaml

标准模型转换流程,精调模型性能/精度

 

4.3 PTQ模型产出物

original_float.onnx

浮点

对 Caffe1.0 模型进行解析,转成 ONNX

optimized_float.onnx

浮点

图优化,例如 BN 融合到 Conv

calibrated.onnx

伪量化

插入校准节点,并基于校准数据计算统计到每个节点的量化参数

ptq.onnx

查表算子定点+其他算子伪量化

将查表算子定点化

quantized.bc

定点

整个模型定点化,并转换为地平线 hbir 中间表达

hbm

指令集

经过编译后的最终部署模型

4.4 PTQ精度配置方法

在 config.yaml 中,支持通过 json 的方式配置 全局某类算子某个子图某个节点 的计算精度,可根据 BPU 算子支持约束进行配置。

 

 4.5 PTQ精度调优流程

请参考用户手册《训练后量化-PTQ转换步骤-模型精度调优》和《训练后量化-PTQ转换步骤-精度调优实战》章节。

 

5. QAT链路

5.1 模型转换流程

 

  • 浮点模型改造:在模型前插入 QuantStub、在模型后插入 DequantStub,用于识别模型首尾部,剥离前后处理
  • 模型校准:通过在模型中插入 Observer 的方式,在 forward 过程中统计各处的数据分布,以计算出量化参数
    • 部分模型仅通过 Calibration 便可满足精度要求,则无需进行 QAT,可直接编译模型用于部署

    • 即使 Calibration 无法满足精度要求,也可降低后续 QAT 难度,缩短训练时间,提升最终训练精度

  • 量化感知训练:进一步通过训练的方式微调模型参数,如果 Calibration 精度较好,则推荐固定激活 scale
    • JIT-STRIP:使用 hook 和 subclass tensor 的方式感知图结构,在原有 forward 上做算子替换/算子融合等操作,并且会根据模型中 QuantStub 和 DequantStub 的位置识别并跳过前后处理

      • 优点:全自动,代码修改少,屏蔽了很多细节问题,便于 debug

      • 缺点:动态代码块仍需要特殊处理

5.2 QAT精度配置方法

5.3 QAT精度调优流程

整体调优流程:

J6B区别于J6E/M来说浮点算子(fp16)的支持能力更多,但是由于没有vpu,因此不高优推荐 fp16 调优,仍建议沿用。

 

fp16配置方式:

QAT新版qconfig量化模板使用教程见:https://developer.horizon.auto/blog/13112

需要注意,由于J6B没有vpu,fp16算子的使用可能会引入cpu的quant、dequant算子。建议尽量少的配 FP 16,避免性能损失。

6. 模型导出/定点化/编译

6.1 PTQ链路

该流程封装在 hb_compile 中,相关参数通过 yaml 进行配置。若自行调用编译器接口执行,参考代码如下:

 

 

 

6.1.1 输入/输出去padding 

模型在 BPU 上推理时,其输入和输出节点的内存大小和数据存放规则需满足硬件对齐要求。

内存对齐:申请的内存大小需满足某个字节数的整数倍,
跨距对齐:跨距(Stride)是指数据存储在内存中时,每一行所占空间的实际大小,当对齐到某个字节数的整数倍后,硬件即可高效处理。该对齐的操作又叫 Padding,实际的对齐规则取决于具体的软硬件系统。假设一份 NHWC 为 1x20x30x1 的 int8 数据,若硬件要求跨距 W32 对齐,那么每一行 W 都将 Padding 2 个字节。
J6 工具链支持在 compile 接口中传入 input_no_padding、output_no_padding 参数来控制是否使用 BPU 自动完成 padding 对齐操作。开启后用户即可不关心 BPU 跨距对齐要求,无需手动 Padding,数据可连续存储在内存中。该特性可优化模型输入/输出的 IO 负载,但也有微小概率会引入性能的小幅下降,所以是否开启该功能请在您的模型上实际验证,并请在模型编译和板端部署环节统一跨距对齐的处理策略。

6.2 QAT链路

QAT 链路的模型定点化和编译直接调用如上的编译器接口,模型导出额外封装了一层,参考代码如下:

6.3 模型修改

编译器支持在 hbir 上进行多 batch 拆分、插入数据前处理、算子删除、调整输入输出 layout 等修改操作,其主要应用场景如下:

多batch拆分:典型场景是 BEV 模型在部署时,多 V 输入来源于不同的摄像头,其数据在内存中独立存储,因此模型可将其多 V 输入沿 batch 维度做拆分;
数据前处理:J6 工具链支持在模型前端插入一个前处理节点,以实现颜色空间转换(如 NV12—> BGR)、数据归一化((data-mean)/std),和 Resizer 功能(从大图上抠图 + Resize),并可由 BPU 进行加速;
算子删除:J6 工具链支持将模型首尾部的 Quantize、Dequantize、Cast、Reshape、Transpose 等算子删除,以适配更加灵活的部署方案;
调整输入输出 layout:模型首尾部除了支持删除 Reshape、Transpose 节点外,还支持插入 Transpose 节点,用户可灵活调整其 layout 排布。

以下参考代码对一个多输入模型实现了多 batch 输入拆分、图像输入的色彩空间转换、数据归一化、Resizer 功能:

6.4 静态perf

对于编译好的 hbm,编译器支持在 X86 端对其 BPU 部分进行静态性能预估,执行以下命令即可生成一个 html 文件,包含模型预估性能、带宽、内存占用、BPU内部单帧执行时序图等信息。

 

 

7. 浮点能力使用

7.1 TAE张量输出,VAE向量计算支持浮点

J6B BPU 的 TAE 张量计算单元支持 FP16/FP32 输出,VAE 向量计算单元支持 FP16 计算。但在实际部署中仍需综合评估后再使用,具体原因如下:

  • 精度:FP16 并非在所有情况下都优于 INT16,通常情况下数值范围小时 FP16 更优,数值范围大时 INT16 更优,但也需要考虑数值较小或较大部分的误差对模型输出的影响程度。所以量化精度是否使用 FP16,更建议基于精度 Debug 的分析结果来确定;
  • 性能:除 Reduce 性能为 INT16 的 1/2 外,其他算子的 FP16 性能和 INT16 性能持平
  • 额外开销:虽然 FP16 算子本身无需量化,但上下游算子如果涉及 FP16 INT16 的数据转换,则会引入量化/反量化:
    • 虽然该节点可以由 VAE 硬件直接支持,但相比于全 INT16 直接串接仍会有额外的性能、带宽开销;

    • 新引入的量化或反量化节点的 Scale 需要重新校准/QAT训练得到。

7.2 无VPU加速量化/反量化

相比于 J6EM 计算平台,J6B 无 VPU 硬件加速模型首尾部的量化/反量化节点,但支持 Gemm 类算子直接 FP32 输出,其他 INT8/INT16 输出节点的反量化,则更建议使用编译器接口将其从 quantized.bc 上移除,并参考该篇文章(反量化节点的融合实现)将其融合进前后处理代码中,以减少一次数据遍历的冗余开销。

7.3 无SPU,标量计算能力有限

相比于 J6 其他计算平台,J6B 的标量计算单元算力减少,因此 TopK 等标量算子的部署性能需要综合评估后选择合适方案。

8. 模型板端部署

8.1 UCP简介

UCP(Unify Compute Platform,统一计算平台)定义了一套统一的异构编程接口, 将 SOC 上的功能硬件抽象出来并进行封装,对外提供基于功能的 API 进行调用。UCP 提供的具体功能包括:视觉处理(Vision Process)、神经网络模型推理(Neural Network)、高性能计算库(High Performance Library)、自定义算子插件开发

UCP 支持的 Backend 如下:

8.2 快速上手

使用 UCP 推理模型的基本代码参考如下,详细信息可参考用户手册《统一计算平台-模型推理开发》、《模型部署实践指导-模型部署实践指导实例》、《UCP通用API介绍》等相关章节。

 

8.2.1 hrt_model_exec工具

为了方便用户快速查看 hbm 和 quantized.bc 的模型信息、进行模型单帧推理和性能评测,J6 工具链 UCP 提供了 hrt_model_exec 工具,并支持编译 X86、aarch64(aarch64仅支持hbm推理)两个架构下的可执行程序。

hrt_model_exec 的三种使用方法如下:

 

8.3 图像输入动态shape/stride 

在 J6 芯片的视频通路上,有一块叫 Pyramid 的金字塔硬件处理模块,可提供 Camera 输入图像的缩放及 ROI 抠图能力,其输出为 nv12 类型的图像数据,并可基于共享内存机制直接给到 BPU 进行模型推理。因此在 J6 工具链中:

  • Pyramid 模型指的是具有 nv12 图像输入的模型;

  • Resizer 模型指的是具有 nv12 图像输入和 ROI 输入的模型,编译器支持通过 JIT 动态指令的方式,从 nv12 图像上完成 ROI 抠图 + Resize 的功能。

在 J6 工具链中,Pyramid 的输入 stride 为动态,Resizer 模型的 stride 和 shape 都是动态。如下为 mobilenetv1 编译后的模型信息:

 

 

Pyramid

Resizer

hb_model_info X86端命令行工具

 

hrt_model_exec model_info 板端可执行程序工具

 

 

其中,-1 为占位符,表示为动态,Pyramid 输入的 stride 为动态;Resizer 输入的 H、W、stride 均为动态。

8.4 非图像tensor内存对齐

对于非图像 tensor,J6B 要求 128对齐,J6EM 要求内存 64 对齐,J6PH 要求 256 对齐。如上图所示,模型输出节点虽然 stride[0] 为 4000,但需要申请的 BPU 内存大小(aligned byte size)为 4096,即为 128 对齐的结果。

在模型实际部署中,非图像输入/输出节点所需申请的内存大小( aligned byte size)均可从模型节点属性的结构体中读取到(hbDNNTensorProperties),因此无需特别关注。

8.5 图像tensor跨距对齐

J6EMB 对于 Pyramid/Resizer 模型的图像输入,要求 W32 对齐,J6PH 要求 W64 对齐。若您有 J6 不同架构平台迁移的场景,请注意跨距对齐要求的差异。

部署代码建议您避免 hard code,推荐基于模型节点属性中的 validShape(张量有效内容尺寸)和 stride(张量各维度步长)进行解析和使用。

 

8.5.1 Pyramid输入

 

Pyramid 输入 tensor 准备的参考代码如下:

 

示例:

注意

视频通路上的金字塔硬件,其输出层支持配置 y、uv 的 stride,但仅要求 W16 对齐,若数据需要喂给 BPU 推理模型,建议直接按 BPU 的跨距对齐要求来配置。金字塔硬件的更多信息请参考系统软件用户手册。

 

8.5.2 Resizer输入

Resizer 输入的 H、W 也是动态的,因此需要设置为原图尺寸,并计算好 W32 对齐的 Stride;ROI 作为模型输入节点,也需要对其进行赋值。以下为参考代码:

 

示例:

8.6 小模型批量处理功能

由于 BPU 是资源独占式硬件,所以对于 Latency 很小的模型而言,其框架调度开销占比会相对较大。在 J6 平台,UCP 支持通过复用 task_handle 的方式,将多个小模型任务一次性下发,全部执行完成后再一次性返回,从而可将 N 次框架调度开销合并为 1 次,以下为参考代码:

 

8.7 优先级调度/抢占

UCP 支持任务优先级调度和抢占,可通过 hbUCPSchedParam 结构体进行配置,其中:
  • priority > customId > submit_time(任务提交时间)
  • priority 支持 [0, 255],对于模型任务而言:
    • [0, 253] 为普通优先级,不可抢占其他任务,但在未执行时支持按优先级进行排队

    • 254 为 high 抢占任务,可支持抢占普通任务

    • 255 为 urgent 抢占任务,可抢占普通任务和 high 抢占任务

    • 可被中断抢占的低优任务,需要在模型编译阶段配置 max_time_per_fc 参数拆分模型指令
  • 其他 backend 任务,priority 支持 [0, 255],但不支持抢占,可以认为都是普通优先级

8.8 X86仿真 

J6 工具链在 X86 端支持 hbm 指令仿真,但效率非常低,所以更推荐使用 quantized.bc 模型进行推理,其定点部分和 hbm 数值二进制一致,浮点部分可能存在架构本身差异,但通常对精度影响可忽略不计。

 

J6B 平台 X86 仿真需要配置如下环境变量,默认架构为"nash-m":

export HB_UCP_SIM_PLATFORM_TYPE=nash-b

8.8.1 推理quantized.bc

Python推理:

quantized.bc 在 X86 端的推理,可以使用 horizon_tc_ui 包封装的 HBRuntime 接口,具体可见用户手册《训练后量化-PTQ转换工具-HBRuntime推理库》,参考代码如下:

 

quantized.bc 也可以直接调用其 func 的 feed 接口进行推理,其输入格式也为 dict,value 支持 torch.tensor 和 np.array 两种类型,输出格式与输入格式保持一致。参考代码如下:

 

C++推理:

quantized.bc 的 C++ 推理接口复用 hbm UCP 推理接口,仅 so 动态库需要替换成 X86 版本即可。 您也可以在 X86 端使用 hrt_model_exec 工具对 quantized.bc 进行模型信息查看和单帧推理。

8.8.2 推理hbm

由于 X86 端 hbm 推理为指令仿真,运行速度非常慢,因此工具链提供了 hbm_infer 工具以便用户在服务器端给直连的开发板下发推理任务。本文只介绍最简单的单进程使用方式,多进程、多阶段模型输入输出的传输优化,以及统计模型推理、网络传输耗时等功能请参考用户手册《hbm_infer工具介绍》。

9. UCP视觉处理/高性能算子

除模型推理外,UCP 还提供了视觉处理和高性能算子两大方向的多种算子接口,可支持诸如 Remap、Jpeg、H264/265、FFT/IFF 等功能,这些算子底层是基于地平线 SOC 上不同硬件 IP 进行的封装,并提供统一的调用接口。

更多信息可参考用户手册《统一计算平台》的相关章节。

注意:

1. 板端实际部署时,ISP 到 Pyramid 的视频通路不建议使用 UCP,无法实现数据 Online,建议直接调用底软接口进行功能实现。

2. 基于 DSP Backend 实现的 HPL 算子,在 J6B 平台仅会提供 J6EM 上 Q8 实现的源码,如需在 J6B 上使用 HPL 算子,需要您自行适配 V130 并编译镜像。VP 算子和 SLAM 等 J6EM 上已有的 Q8 DSP sample,将在 J6B 后续正式版本中提供 V130 版本。

10. UCP自定义算子(DSP)

为了简化用户开发,UCP 封装了一套基于 RPC 的开发框架,来实现 CPU 对 DSP 的功能调用,但具体 DSP 算子实现仍是调用 Cadence 接口去做开发。总体来说可分为三个步骤:

  1. 使用 Cadence 提供的工具及资料完成算子开发;

  1. DSP 侧通过 UCP 提供的 API 注册算子,编译带自定义算子的镜像;

  1. ARM 侧通过 UCP 提供的算子调用接口,完成开发板上的部署使用。

更多信息可见用户手册《统一计算平台-自定义算子-DSP算子开发》。

 

11. 性能监测工具

 

J6 平台 BPU、DSP 都是独占的硬件资源,任务一旦提交就会独占推理,UCP 侧仅能通过 hrt_ucp_monitor 工具去监测其硬件占用率(采样频率支持配置 [10, 1000],默认 500),并且能查看到 DDR 内存占用情况。

 

 

12. QNX带来的功能裁剪

1. UCP Service (中继模式)

UCP 框架支持两种主要工作模式:直连模式、中继模式。系统默认运行在直连模式下,在中继模式下,UCP 将支持跨进程任务优先级的统一调度。但 QNX 上跨进程调度的模型性能较差,不满足使用需求,故功能移除。

2. UCP Trace UCP trace 通过在 UCP 执行的关键路径上嵌入 trace 记录,提供深入分析 UCP 应用程序调度逻辑的能力。在出现性能异常时,可以通过分析 UCP trace,快速找到异常发生的时间点。但 QNX 底软不支持 Trace 功能,故移除。
3. DEB部署包 用于简化板端部署,可通过自动安装所需的二进制文件和相关依赖库,快速设置并运行UCP相关的应用程序,具体包括:ucp_service 和 hrt_ucp_monitor。但鉴于 ucp_service 不支持,该功能也移除。
算法工具链
社区征文征程6官方教程技术深度解析
评论0
0/1000