系列编排日期为 2026 年 8 月;技术基线核对与教学代码 CPU 验证日期为 2026-10-12。适用 Hi3516CV610 与本系列注明的 SDK/工具版本,实测范围见第 12 章。
返回系列目录 · 本篇属于 12 章与 4 份附录。
板端最小闭环先验证“同一个模型、同一份字节输入、可解释的原始输出”,然后再接摄像头、ROI 和业务后处理。这样可以把媒体链路与 NPU 运行时问题分开定位。
文档与代码入口
读《应用开发指南》第 3 章的进程线程、Device、Context、Stream 和内存,第 4 章的 Runtime、模型加载、执行与释放。查找关键词 task_buf、work_buf、stride、缓存刷新和模型描述。
项目入口为 application/Board/HI3516CV610_00S/Src/BoardNpu.cpp,最小测试程序为 application/Dependent/shared/head_yunet_luvli/hi3516/benchmark.cpp。前者用于实际板级适配,后者用于单模型诊断,能力边界不同。
生命周期与资源所有权
|
每次 API 返回值都要检查,并让失败路径只释放已经成功获取的资源。封装对象和底层设备内存的所有权需要分别管理,销毁 dataset 不应被想当然地视为释放全部用户分配的内存。
当前 benchmark 对 load_from_mem 使用的模型内存保留到卸载后再释放。不要在未确认 API 生命周期要求时,加载返回就释放源 buffer。异步执行还要保证输入、输出和任务内存在同步完成前一直有效。
描述信息决定分配和复制
按 API 查询真实输入输出数量、shape、数据类型、buffer 大小和 stride。业务只看到一个图像输入,不代表运行时只有一个输入 buffer;模型可能还有 task 和 work 缓冲。
task 缓冲不能在同时执行的任务间共享。工作缓冲是否能复用,必须遵守手册的 Stream 和并发约束;文档允许的单 Stream 多模型复用场景,也需要按最大需求分配。不能把串行可复用推广成跨 Stream 并发共享。
图像逻辑文件每行 width*bytes_per_element 字节,设备每行可能有 padding。逐行拷贝时检查行数、row_bytes、stride 和总大小,不要把 W*H*C 直接当作分配大小。输出连续化规则见第 08 章。
使用可缓存内存时,CPU 写入后的设备可见性、设备写入后的 CPU 可见性必须按本 SDK 的缓存同步接口处理。缓存问题可能表现为重复旧结果、局部错误或偶现异常,不能仅靠多执行几次规避。
编译最小测试程序
在项目根目录、已安装本项目交叉编译工具链的主机执行:
|
产物为 application/.temp/head-yunet-luvli/hi3516/npu-benchmark。脚本选择项目 musl ARM 编译器、板级 SDK 头文件与库;不要改用宿主机 g++ 生成 x86 文件后上传 ARM 板。
将程序、同哈希 OM 和 input_0.bgr 放到设备的独立测试目录。传输地址和路径由实际设备确定,保留已有业务模型;测试前确认设备资源占用和与在线业务的互斥安排。
执行并取回输出
下面命令在设备测试目录执行,要求三个文件已传入且设备 Runtime 可用:
|
取回 board-run.log 和全部 board-output_*.bin,使用同一个比较脚本与 CPU NPZ、PC 仿真分别比对。若模型描述和当前 benchmark 的三输入假设不一致,先适配程序,不要绕过检查。
benchmark 默认预热 3 次,随后统计指定次数的执行耗时,输出均值、p50、p95及内存信息。它的模型加载耗时与执行耗时分开,测得的 execute 时间不包含完整业务的图像采集、ROI、后处理和显示。
接入业务前的验收
验收顺序是文件哈希一致、描述一致、输入字节一致、原始输出可接受、后处理一致、真实样本任务指标达标。随后再加入多模型加载、卸载、长期循环和媒体并发测试。
板端内存同时包括模型、task/work、输入输出、媒体缓冲及其他模块。单模型执行成功不能保证级联系统常驻多个模型后仍有足够内存。记录加载前、加载后、执行峰值与卸载后的状态,区分合理缓存和持续增长。
