常见问题
通用问题
任务创建或提交后返回HB_UCP_INVALID_ARGUMENT错误码是什么原因?
可根据UCP的错误日志来判断可能的问题,可能存在如下情况:
- 算子约束问题:大部分加速算子在创建时应满足使用约束,否则会返回错误码。
- 如果遇到日志打印
op $1 of task has no proper backend, user expect $2,表示没有合适的后端可执行;其中$1表示任务的类型,$2是任务提交时的backend参数,以二进制形式打印,需要按照J6系列每种backend可支持的core数量进行配置。
如何理解hbUCPSysMem的物理地址和虚拟地址?
在J6计算平台架构中,所有硬件的DDR内存共享,通过 hbUCPMallocCached 和 hbUCPMalloc 接口可以申请到一段物理空间连续的内存,其函数返回值被包装在 hbUCPSysMem 数据结构体中,phyAddr 和 virAddr 两个字段分别对应其内存空间的物理地址和虚拟地址,虚拟地址可直接被CPU访问,物理地址不可访问。
如何理解cacheable和非cacheable的hbmem?
ucp的内存管理接口提供了hbUCPMallocCached 和 hbUCPMalloc 来分配DDR读写内存,这种内存都是物理地址连续,可被bpu/dsp等ip访问使用的,其中 hbUCPMallocCached表示分配cacheable属性的内存,并配套了 hbUCPMemFlush 函数来对Cache进行刷新。
Cache机制是由计算平台的内存架构来决定的,可参考如下图所示。CPU与主存之间存在的Cache会缓存数据,而BPU/DSP/JPU/VPU(Video Processing Unit)/PYRAMID/STITCH/GDC等其他后端硬件与主存之间则没有cache。此时若错误使用Cache将会直接影响最终数据读写的准确性和效率。
- 当CPU写完数据后,需要主动将Cache中的数据flush到memory中,否则其他硬件访问同一块内存空间时可能会读取到之前的旧数据。
- 而当其他后端硬件写完数据后,CPU在访问之前也需要主动将Cache中的数据invalidate掉,否则CPU可能会优先读取到之前缓存在cache中的旧数据。
- 在模型连续推理过程中,需要cpu读的,比如模型输出,建议申请带cacheable的内存,以加速CPU反复读写的效率,而不需要读的,只写的,比如模型输入,可以申请非cacheable的内存。
应用侧在异常处理中是否可以使用 exit 退出?
由于UCP内部存在资源管理单例,应用侧(包括重写的信号处理函数)调用exit/std::exit退出时会引发单例析构,若此时仍有线程访问单例资源,容易引发异常。因此,UCP更推荐使用_exit/std::quick_exit,若您必须使用exit/std::exit,请保证退出时没有线程访问UCP的任何资源。
应用异常退出时如何保证日志完整性?
为了确保关键的日志信息不会因进程异常退出而丢失,建议应用在异常退出前调用 hbUCPFlushLog 接口刷新缓冲的日志,确保所有日志消息都被写入磁盘。这在调试异常问题和追踪系统故障时尤为重要。
模型推理
导致模型推理hbUCPWaitTaskDone接口timeout超时的原因可能有哪些?
-
模型本身执行的时间较长,而异步等待接口设置的超时时间不足,或者当前计算资源负载较高导致任务排队时间较长,可能引发接口超时。
-
存在内存泄露情况。在系统内存不足的情况下,分配内存慢,可能会导致推理超时。
-
CPU负载过高。调度线程获取不到CPU,此时即使任务完成也无法及时同步到用户接口,导致推理超时情况。
模型推理卡住的原因
模型问题:模型指令原因导致的底层运行错误,错误没有上报,导致hang住。此时,可通过cat /sys/devices/system/bpu/bpu0/task_running对bpu任务情况进行查看,如下图所示:
s_time不为空表示任务已经正常开始,而p_time如果为空则表示没有正常返回,即可认为BPU任务hang住了,可联系sr或者编译器团队解决。
ROI输入模型约束有哪些?
您可参考 ROI简介及约束 中对ROI限制的介绍。
模型推理结果一致性问题排查
- 请确保用于比对一致性的输出已经去除 padding。
- 若模型存在动态形状输出,请确保调用了
hbDNNGetTaskOutputTensorProperties接口获取真正输出形状。 - 请确保对输入输出内存正确执行了 Flush 操作。
- 关闭 UCP ARM 优化算子后若一致性问题解决则为优化算子问题。关闭方法:
模型推理性能优化建议
- 尽量优化掉模型中的 CPU 算子。
- 推荐推理内存统一申请,分散使用,内存复用。
- 在实现模型输入输出内存复用前提下,开启 Map LRU Cache 策略缓解 BPU Map 耗时。开启方式:
- 调整线程优先级。建议调高调度线程优先级,若仅使用模型推理功能,建议禁用 DSP、ISP 等未使用的后端以减少线程数量。参考示例:
- 推理时指定 BPU 核心,用以在多核硬件上减少 Memory Map 的次数。
自定义算子开发
DSP 相关
J6选用的DSP型号?
J6 选用了 Cadence 公司的 Tensilica Vision Q8 DSP IP(以下简称 Q8), 是专用于视觉/图像处理的数字信号处理器,DSP IP数量根据开发板型号略有不同。更多信息可见:DSP开发文档 或 Cadence 官方文档。
如何获取 Cadence 官方文档?
安装步骤可参考:DSP开发文档 章节;安装完成Cadence开发套件后,可以在开发包内查看部分文档,获取完整文档包请联系地平线技术支持人员。
DSP 支持哪些计算精度?
支持 int8/int16/int32 的整型计算,以及 float32、double 的浮点计算。
如何查看 DSP 侧的日志输出?
在X86 仿真环境中,可以通过在执行示例脚本时修改日志打印等级环境变量 HB_DSP_VDSP_LOG_LEVEL 来查看日志输出,日志等级设置方法与UCP一致,修改方式请参考脚本内容;
在开发板中,可以通过监听日志文件的方式查看DSP侧的日志。具体方法如下:
- 增加环境变量 export HB_DSP_WRITE_VDSP_LOG_TO_ARM=true,使能DSP日志输出。
-
修改DSP日志打印等级环境变量 HB_DSP_VDSP_LOG_LEVEL。
-
使用如下命令启用文件监听。
DSP 自定义算子示例是否可以直接运行?
不可以。自定义算子需要重新编译 DSP 镜像,才可以将算子实现注册到 DSP 的调用框架中。因此需要先编译 DSP 镜像,然后将镜像拷贝到开发板上,再运行示例。 编译及运行步骤请参考: 自定义算子示例 章节。
但若您想进行相关代码开发,或者编译新的镜像,则需要 DSP 开发软件 Xplorer 和对应的 License 授权文件,获取方式请联系地平线技术支持人员。
DSP 调试常用命令有哪些?
- 获取vdsp对应core的状态,分为offline 和 online两种状态。
- 获取vdsp镜像名字及版本,version中包含了编译版本、编译日期、hash_id等信息,可用于版本追溯。
J6E/M的QNX操作系统中不包含name信息,请根据具体环境进行查看。
- dmesg 命令查看底软log信息。
- 查看最新落盘的vdsp日志。
- dsp 启停命令。
DSP 自定义算子卡死应该怎么排查?
- 通过打印的日志信息,查看 DSP 侧是否有报错信息。
- 判断 DSP 是卡死还是coredump,可以通过 dmesg 命令查看内核日志,查看是否有具体打印信息。
- 排查 ARM 侧代码,是否存在内存 Map/Unmap 和 cache 刷新问题。
- 排查 DSP 侧代码,是否存在 cache 刷新问题,可以通过全局刷新、逻辑二分退出等方法判断错误位置。
- 排查 DSP 侧代码,是否存在逻辑或者内存访问错误。可以使用 dmesg 命令查看内核日志,查看是否有打印信息。
DSP 自定义算子ddr cache未同步可能导致的问题有什么?
- ARM 和 DSP 侧双方写入和读取到的数据不一致。
- DSP 异常卡死或者无响应,可能是 DSP 侧使用了未刷新的内存。
- DSP coredump,此时会有错误日志打印,可以通过 dmesg 命令查看内核日志,可以根据日志定位到具体的地址。
