NPU Delegate 接入:跑到加速器上,不等于真的加速
很多边缘 SoC 都带 NPU,厂商也会提供 TensorFlow Lite Delegate、RKNN、SNPE、NNAPI 之类工具。模型能跑到 NPU 上当然好,但“跑上去”不等于“真的加速”。如果算子频繁回退 CPU、输入输出拷贝太重、batch 形态不合适,最终延迟可能还不如纯 CPU。
接入 NPU Delegate,要先看算子支持表,再看数据拷贝路径,最后用端到端数据说话。别只盯厂商 PPT 里的 TOPS。
一、先确认算子是否完整支持
模型里只要有几个关键算子不支持,就可能被切成多段执行:一段 NPU,一段 CPU,再拷贝回来。每次切换都有开销。
flowchart LR A[输入 Tensor] --> B[NPU 支持算子] B --> C{遇到不支持算子} C -->|是| D[回退 CPU] D --> E[拷贝回 NPU] C -->|否| F[NPU 继续执行] E --> F因此模型转换报告很重要。要看哪些算子被 NPU 接管,哪些回退,回退是否在主干路径上。
二、初始化和内存分配也要测
很多 demo 只测单次 inference,不测模型加载、delegate 初始化和 tensor 分配。实际产品里,冷启动时间也很关键。
uint64_t t0 = now_us(); interpreter->ModifyGraphWithDelegate(delegate); uint64_t t1 = now_us(); interpreter->AllocateTensors(); uint64_t t2 = now_us(); printf("delegate=%llu us allocate=%llu us\n", t1 - t0, t2 - t1);如果初始化很慢,交互式设备可能需要预热;如果内存分配峰值过高,低内存设备会不稳定。
三、减少无意义拷贝
NPU 加速常见瓶颈是数据搬运。摄像头出来的 NV12 数据,先转 RGB,再 resize,再拷贝给 NPU,每一步都要成本。能不能用硬件 ISP、RGA 或 DMA buffer 直接对接,是工程关键。
pipeline: camera: NV12 preprocess: hardware_rga tensor_memory: dma_buffer inference: npu_delegate postprocess: cpu_lightweight如果前处理全在 CPU 上跑,NPU 再快也可能等数据。边缘 AI 是系统工程,不是只优化模型文件。
四、端到端延迟才是最终指标
验收时要拆分摄像头采集、前处理、推理、后处理、业务动作。NPU inference 从 20ms 降到 5ms,但前处理仍然 40ms,用户不会觉得快多少。
还要测连续运行。NPU 驱动、内存泄露、温升降频,都可能在长时间运行后暴露。demo 成功只是第一步,稳定跑一天才像产品。
我还会做 CPU fallback 统计。很多工具链会在转换报告里提示,但运行时仍可能因为动态 shape 或特殊输入走回 CPU。每次版本升级后,把 delegate 分段结果保存下来,和上一版比较。
delegate_check: total_ops: 86 npu_ops: 79 cpu_ops: 7 cpu_fallback: ["RESIZE_NEAREST", "CUSTOM_NMS"]如果 CPU 回退在后处理小算子上,可能能接受;如果在主干卷积或 attention 上,就要重新改模型结构。NPU 加速要看主耗时路径,不是看接管算子数量凑百分比。
五、总结
NPU Delegate 接入不能只看模型是否跑到加速器上。算子支持、CPU 回退、初始化、内存分配、数据拷贝和端到端延迟,才决定它是否真的加速。
边缘设备上,快不快不是 TOPS 说了算,是整条链路的毫秒数说了算。