推理流程与延迟构成:从模型输入到输出的完整流水线
在Arm Ethos-U NPU的推理优化工作中,一个最常见的误区是:工程师将“模型推理延迟”视为一个不可拆分的黑盒指标,只关注总耗时,却忽略了延迟在流水线各阶段的实际分布。事实上,一次完整的推理并非从NPU启动才开始,而是从传感器数据到达、经预处理、输入张量搬运、NPU计算、输出张量回读、后处理,直到应用层拿到结果的完整链路。任何一个环节的瓶颈都会成为整体延迟的天花板。本章将拆解这条流水线,量化各阶段延迟占比,并给出基于Ethos-U架构特性的延迟预算控制方法。
上图展示了从数据采集到输出回读的完整推理流水线,以及各阶段在典型视觉模型中的延迟占比。需要特别强调的是,NPU计算虽然通常占据最大比例(约60%-70%),但数据搬运和预处理环节的延迟往往决定了系统能否达到实时性要求。在Ethos-U系列中,由于NPU与CPU共享内存带宽,搬运延迟的波动可能比计算延迟更不可控。
4.1 核心原理:Ethos-U推理流水线的五个阶段
Ethos-U的推理流水线可以抽象为五个串行阶段,每个阶段都有独立的延迟特征和优化空间:
| 阶段 | 主要操作 | 硬件单元 | 延迟特征 | 典型占比 |
|---|---|---|---|---|
| 1. 数据采集 | 从传感器/内存读取原始数据 | DMA、外部接口 | 受外设速度影响,可预取 | 3%-8% |
| 2. 预处理 | Resize、Normalize、色彩空间转换 | CPU(Cortex-M/A) | CPU周期消耗,可并行 | 8%-15% |
| 3. 输入搬运 | 将输入张量从系统内存搬至NPU SRAM | DMA控制器 | 带宽受限,可双缓冲 | 5%-12% |
| 4. NPU计算 | 卷积、全连接、激活、池化等算子 | Ethos-U核心 | MAC利用率决定,可优化 | 55%-70% |
| 5. 输出回读 | 将结果从SRAM搬回系统内存 | DMA、总线 | 与计算可部分重叠 | 5%-10% |
理解这五个阶段的延迟构成,是进行延迟预算控制的前提。值得注意的是,Ethos-U的NPU计算与DMA搬运在硬件层面支持部分重叠,这意味着如果软件流水线设计得当,搬运延迟可以被计算时间掩盖,从而降低总延迟。
4.2 判断方法:如何测量各阶段延迟
要优化延迟,首先必须能精确测量各阶段耗时。在Arm Corstone-300/310参考平台上,推荐使用以下方法:
- 硬件计时器:使用Arm通用定时器(Generic Timer)在关键代码段打点,精度可达纳秒级。
- Ethos-U驱动事件:NPU驱动提供事件回调(如ETHOSU_EVENT_JOB_DONE),可获取计算完成时刻。
- DMA完成中断:在DMA传输完成中断中记录时间戳,用于测量搬运延迟。
- 性能计数器:Ethos-U内部有MAC周期计数器,可精确统计NPU计算周期。
// 伪代码示例:测量各阶段延迟
uint32_t t0 = timer_get_us();
// 阶段1: 数据采集(假设已由DMA预取)
uint32_t t1 = timer_get_us();
preprocess_input(img, &tensor); // 阶段2: 预处理
uint32_t t2 = timer_get_us();
ethosu_dma_transfer_in(&tensor); // 阶段3: 输入搬运
uint32_t t3 = timer_get_us();
ethosu_run_job(&job); // 阶段4: NPU计算
uint32_t t4 = timer_get_us();
ethosu_dma_transfer_out(&result);// 阶段5: 输出回读
uint32_t t5 = timer_get_us();
printf("采集:%dus 预处理:%dus 搬运入:%dus NPU:%dus 搬运出:%dus\n",
t1-t0, t2-t1, t3-t2, t4-t3, t5-t4);
在实际项目中,建议至少采集100次推理的统计数据,计算平均值、P50、P95和最大值,以识别延迟抖动。如果P95远大于平均值,说明存在偶发性的调度或带宽竞争问题。
4.3 案例拆解:智能音箱关键词检测的延迟优化
以一个实际的智能音箱关键词检测(KWS)项目为例,模型为DS-CNN(Depthwise Separable CNN),输入为49x10x1的MFCC特征图,运行在Cortex-M55 + Ethos-U55平台上。
初始状态:系统总延迟为12.8ms,其中NPU计算仅占4.2ms,但整体延迟远超预算(目标10ms)。通过打点测量发现:
- 数据采集:0.3ms(2.3%)—— 正常
- 预处理(MFCC特征提取):4.5ms(35.2%)—— 严重超标
- 输入搬运:1.2ms(9.4%)—— 偏高
- NPU计算:4.2ms(32.8%)—— 正常
- 输出回读:0.6ms(4.7%)—— 正常
- 调度开销:2.0ms(15.6%)—— 可优化
分析判断:预处理(MFCC)在CPU上执行,消耗了过多周期。同时,调度开销来自RTOS任务切换和驱动调用。进一步分析发现,MFCC计算中使用了浮点运算,而Cortex-M55虽然支持FPU,但效率不如定点运算。
优化措施:
- 将MFCC中的浮点运算改为Q15定点运算,利用CMSIS-DSP库的优化函数,预处理时间从4.5ms降至1.8ms。
- 将输入搬运改为双缓冲模式,与NPU计算重叠,搬运延迟从1.2ms降至0.4ms(隐藏)。
- 合并驱动调用,减少RTOS任务切换次数,调度开销从2.0ms降至0.8ms。
优化结果:总延迟从12.8ms降至7.2ms,满足10ms预算。其中NPU计算占比从32.8%提升至58.3%,成为主要延迟来源,符合预期。
4.4 常见误区与总结复盘
在延迟预算控制实践中,以下误区需要特别注意:
总结复盘:推理延迟的构成是一个系统工程问题,需要从数据采集到输出回读的全局视角进行预算分配。在Ethos-U平台上,建议遵循以下延迟预算控制流程:
- 建立各阶段延迟的测量基线,识别占比异常项。
- 优先优化占比最高的阶段,但需评估优化对其他阶段的影响。
- 利用硬件特性(双缓冲、DMA、事件回调)实现阶段重叠。
- 在系统层面设置延迟预算上限,并预留20%的余量应对抖动。
- 持续监控P95和最大值,确保实时性稳定。