3. 模型部署

3.1. 常见问题

1. camera 数据如何传递给模型推理?

答:J5 工具链的 OE 包在 ddk/samples/ai_forward_view_sample 路径下提供了一个 数据从 camera 采集到送给 BPU 进行模型推理的全流程示例, 辅助理解可参考文章:J5 全流程示例解读

2. 是否支持图片 ROI 区域的模型推理?

答:XJ3 及 J5 芯片均支持 gray/nv12 模型的输入为图片的 ROI 区域(支持多个 ROI),此类模型被称为 resizer 模型, 具体部署方式可参考:resizer模型使用与部署

3. 是否支持模型以 batch 模式推理?

答:XJ3 及 J5 芯片均支持 batch 模式推理,具体部署方式可参考:多batch模型使用与部署

4. 如何理解 more 模式推理?

答:XJ3 及 J5 工具链的 OE 包在 ddk/samples/ai_toolchain/horizon_runtime_sample/code/02_advanced_samples/multi_model_batch 路径下提供了一个 more 模式模型推理示例。 该模式主要用于将推理速度很快的小模型绑定在一起,全部执行完再一次性返回。这样就可以减少每个模型都响应中断的时间开销。但请注意,使用 more 模式时请勿重复提交同一个模型的多个任务。

另外,如果某个绑定了多个 model 的 task 任务设置了 BPU 任意核调度,那么这些 model 并不会按照实时负载分配在不同的核心上,而是会被统一调度至某一个 BPU 核心上。

5. 为什么 nv12 模型比 rgb 模型的推理速度更快?

答:因为 nv12 的数据量是 rgb/bgr 数据量的一半,所以数据加载的耗时更少。

6. 前后处理 CPU 优化建议?

答:以下提供一些通用建议作为参考:
  1. 尽量使用 float 数据类型替代 double 类型,模型精度不一定会下降;

  2. 可以用结构体记下关键信息,与需要做 for 循环的信息做绑定;

  3. 尽量合并代码中的 for 循环;

  4. 数据尽量使用引用方式代替拷贝;

  5. 还可以参考 J5 工具链 fcos3d 示例模型的后处理优化思路,其代码位于:ddk/samples/ai_benchmark/code/src/method/qat_fcos3d_post_process_method.cc

7. 如何更新板端的工具链环境?

答:板端的工具链环境依赖两个动态链接库,分别是 libhbrt_<architecture>_aarch64.solibdnn.so,其中 XJ3 的 <architecture>bernoulli2,J5 的 <architecture>bayes。 用户更新工具链版本获取新的 OE 开发包后,可以从 ddk/package/host/host_package 路径下的 xj3_aarch64j5_aarch64 目录, 解压 dnn_<version>.tar.gz,再从 lib 目录下获取当前工具链版本的两个动态链接库,替换掉开发板上的旧文件即可。

8. 为什么板端后处理增加可视化代码会严重影响推理速度?

答:可视化操作不适合在端侧运行,建议将推理结果传给 pc 端再做可视化。

9. 如何优化量化/反量化算子推理性能?

答:XJ3 和 J5 平台默认会将量化/反量化算子集成在模型中,并使用 CPU 计算,整体效率并不高效。 因此可参考 反量化节点的融合实现,将量化/反量化节点融合进前后处理中,从而减少数据遍历开销。 J5 平台还可参考 DSP的量化/反量化算子调用,使用 DSP 硬件进行加速。

10. 移除模型中的反量化节点并合入后处理后推理结果错误,应如何分析?

答:因为 BPU 硬件对齐规则,模型编译后的输出尺寸有 valid_shapealigned_shape 两种。 若模型删除反量化节点后,仍以 CPU 算子结尾,则板端预测库(libDNN)会自动完成去 padding 操作,此时模型的输出即为 valid_shape,可以直接得到正确的后处理结果; 若模型直接以 BPU 算子结尾,那么 libdnn 不会自动去除 padding,此时模型的输出尺寸为 aligned_shape,需要用户在编写反量化计算代码时自行跳过 padding 区域,才能得到正确的后处理结果,具体实现可参考 AI-Benchmark 的 PTQ 后处理源码。

11. cv::COLOR_BGR2YUV_I420 是否为模型推理所需的 nv12 格式?

答:当我们进行网络回灌时,通常会使用 opencv 的接口 cv::cvtColor 将数据转换为 cv::COLOR_BGR2YUV_I420 格式, 但这种编码格式的 yuv 数据依次排列 Y、U、V 分量(例如:YYYYYYYYUUVV),而地平线支持的 nv12 格式需交错排列 U、V 分量(例如:YYYYYYYYUVUV)。 I420 至 nv12 的转换方式可参考 OE 包 horizon_runtime_sample 中,00_quick_start 示例 read_image_2_tensor_as_nv12 函数的代码实现。

12. 板端部署报错,如何排查是模型问题还是代码问题?

答:可以首先使用 OE 包 ddk/package/board/hrt_tools/bin 目录下提供的 hrt_model_exec 工具在板端执行单模型的性能测试,若运行失败,则属于模型问题;若运行成功,则属于代码问题。 对于模型问题,可基于日志信息或反馈给地平线进行分析和修复;对于代码问题,可参考 horizon_runtime_sampleAI-Benchmarkhrt_model_exec 工具源码等示例代码进行检查。

13. 如何编写多线程推理代码?

答:您可以参考 hrt_model_exec 工具 perf 功能的源码实现,文件路径为 /ddk/package/board/hrt_tools/src/hrt_model_exec/src/util/function_util.cpp, 可重点关注其中的 run_model_with_multi_thread 函数。


3.2. 常见故障

1. hbDNNInitializeFromFiles failed, error code:-6000014

答:该报错是模型编译架构与运行芯片不匹配导致,例如将 XJ3 的模型部署在 J5 芯片上。 请检查模型编译时的参数配置是否正确(XJ3 芯片为 bernoulli2,J5 芯片为 Bayes)。

2. keros_i2c_read failed 或 keros_authentication failed

答:如果开发板上没有 keros 芯片,就会导致在模型加载阶段出现相关报错,但不影响正常的板端部署效果,可以忽略。 目前 XJ3 工具链版本 ≥ v2.6.2b/v1.16.2c,J5 工具链版本 ≥ v1.1.49 均已优化相关日志,不会再触发。

3. pseudo_firmware 相关 warning

答:不影响正常的板端部署效果,可以忽略。

4. Output layout only support: 0, 2; given: 1 (error code:-6000012)

答:该报错触发在输出为 channel argmax 的 QAT 模型通过 PTQ load 方式校准编译,并在板端运行时的场景。因为 channel argmax 算子的输出排布不受编译时命令行选项的控制,所以若存在非 NHWC/NCHW 的 layout,就无法正常推理。
  1. 此时建议模型先 float2qat,然后加载 qat 模型参数,再导出 onnx;

  2. 若先加载 float 模型参数,再执行 float2qat,并导出 onnx,就会出现以上报错。

5. 【X3pi】ERROR: cannot reshape array of size xxx into shape (xxx)

答:该报错为模型输出和后处理代码要求的数据 shape 不一致,通常是因为直接复用了 OE 包提供的示例代码或其他来源的后处理代码,而没有针对性地修改后处理脚本导致。

以 Yolov5 模型为例,可先理解其原理及后处理流程,再修改 OE 包中的示例代码;也可参考以下社区文章进行全流程部署:
  1. [BPU部署教程] 教你搞定YOLOV5部署 (版本_ 6.2)

  2. 【模型提速】如何在X3pi使用yolov5模型50ms推理

6. the alloced memory size should be less than xxx 或 Fail to share ion memory (Too many open files)

答:该报错常见于多线程推理或 batch 模型推理场景,原因是推理占用的内存超出了上限,建议使用更少的线程数,降低 batch 数,或者使用内存占用更小的模型。