2、基础知识:延迟、吞吐量、实时性、确定性等核心概念及其在TinyML中的特殊性
在进入TinyML推理延迟测试之前,必须先厘清一组经常被混用、但在嵌入式机器学习场景下含义截然不同的核心指标:延迟(Latency)、吞吐量(Throughput)、实时性(Real-time)与确定性(Determinism)。这四个概念在通用服务器端ML系统中往往只影响服务质量(QoS),但在TinyML中,它们直接决定了系统能否在电池供电、资源受限、物理环境交互的场景下正常工作。例如,一个用于电机堵转保护的异常检测模型,若推理延迟从2ms抖动到15ms,就可能导致保护动作滞后,烧毁驱动器。本章将逐一拆解这些概念,并重点说明它们在MCU级部署中的特殊含义与测量陷阱。
2.1 延迟:从“平均时间”到“分位数思维”
核心原理:延迟是指从输入数据准备好(例如传感器采样完成、DMA传输结束)到推理结果可用(输出张量写入指定内存)所经过的完整时间。在TinyML中,这个时间通常由三部分组成:数据预处理时间(归一化、量化、格式转换)、模型推理时间(算子执行、内存访问)、后处理时间(阈值判断、结果编码)。与服务器端不同,MCU上的内存带宽极窄(如STM32F4的AXI总线仅32位),Flash读取速度远低于CPU主频,因此访存延迟往往比计算延迟更显著。
判断方法:测量延迟不能只取平均值。在TinyML中,由于中断嵌套、Flash缓存命中率变化、DMA与CPU竞争总线,单次推理延迟可能呈现明显的长尾分布。正确做法是采集至少1000次推理的周期计数,计算P50(中位数)、P95和P99分位数。例如,一个关键词唤醒模型平均延迟为8ms,但P99达到23ms——这15ms的尾部延迟可能来自Flash等待状态或中断抢占。
clock()函数在MCU上通常精度不足,且可能被优化掉;应使用volatile变量和__ASM volatile确保读取不被重排。
2.2 吞吐量:被忽视的“系统级”指标
核心原理:吞吐量定义为单位时间内系统能完成的推理次数,单位通常为FPS(帧/秒)或次/秒。在TinyML中,吞吐量并不等于1/延迟。因为MCU通常是单核顺序执行,且推理期间无法同时处理其他任务(除非使用协处理器或双核)。实际吞吐量受限于:传感器采样率、数据搬运时间、推理占用的CPU占比。例如,一个图像分类模型单次推理5ms,但摄像头采集一帧需要20ms(OV7670无FIFO时),则系统吞吐量上限为40FPS,而非200FPS。
判断方法:测量吞吐量时,应模拟真实数据流:传感器持续产生数据,MCU持续处理。使用一个循环,在每次推理完成后立即开始下一次,记录1秒内完成的次数。注意区分“裸推理吞吐量”(只算模型执行)和“端到端吞吐量”(包含采集、预处理、推理、输出)。在TinyML中,端到端吞吐量才是系统设计的关键。
| 场景 | 延迟(单次) | 吞吐量(端到端) | 瓶颈 |
|---|---|---|---|
| 关键词唤醒(KWS) | 15ms | 50次/秒 | 音频帧缓冲(20ms) |
| 振动异常检测 | 0.8ms | 1200次/秒 | ADC采样率(3.2kHz) |
| 图像分类(QVGA) | 120ms | 7FPS | DMA传输+模型计算 |
2.3 实时性:硬实时与软实时的边界
核心原理:实时性不是“快”,而是“可预测地在截止时间前完成”。在TinyML中,实时性分为两级:硬实时(错过截止时间=系统故障,如电机堵转保护、气囊触发)和软实时(偶尔错过可接受,如语音命令识别)。MCU上的实时性挑战主要来自:中断优先级反转、临界区过长、以及Flash等待周期随温度/电压变化。例如,STM32L4在1.8V供电时Flash等待周期可能从0变为1,导致推理时间增加约15%。
判断方法:评估实时性必须测量最坏情况执行时间(WCET),而非平均时间。方法包括:① 在最高优先级中断中触发推理,记录最大延迟;② 人为制造最差条件(Flash擦写、DMA全速传输、外部中断风暴);③ 使用逻辑分析仪同时监控推理完成引脚和外部事件引脚,测量事件到响应的完整链路时间。
vTaskDelay或osDelay来测量推理时间——这些函数本身有调度抖动(通常1-10个tick)。应使用硬件定时器或DWT周期计数器。另外,注意编译器优化级别(-O0 vs -O2)对WCET的影响可能超过2倍。
2.4 确定性:抖动是TinyML的“隐形杀手”
核心原理:确定性指相同输入条件下,推理时间和结果是否可重复。在TinyML中,确定性包含两个维度:时间确定性(每次推理耗时一致)和数值确定性(浮点/定点运算结果一致)。时间抖动的主要来源包括:中断抢占、缓存命中率变化(MCU的Flash缓存通常只有几KB)、分支预测失效、以及动态电压频率调整(DVFS)。数值确定性则受编译器优化(如FMA融合)、累加顺序、量化参数影响。
判断方法:运行同一输入100次,记录每次的周期计数,计算标准差和最大偏差。若标准差超过平均值的10%,则系统确定性较差。对于数值确定性,使用memcmp比较两次推理的输出缓冲区(注意浮点比较需容忍ULP差异)。
__disable_irq()),但需控制临界区时间;② 将模型和权重放入紧耦合内存(TCM)或SRAM,避免Flash缓存抖动;③ 使用定点(Q格式)推理替代浮点,消除FPU舍入差异;④ 固定CPU频率,关闭DVFS和WFI(等待中断)指令。
2.5 案例拆解:工业振动监测的实时性验证
背景与约束:某工业设备需要部署一个3层1D-CNN模型(约12K参数)用于轴承故障检测。传感器为IIS3DWB加速度计(SPI接口,采样率25.6kHz),MCU为STM32H743(Cortex-M7,480MHz)。系统要求:硬实时——从振动冲击发生到报警输出必须小于5ms;确定性——抖动不超过±0.2ms;吞吐量——至少处理200帧/秒(每帧256点)。
初始现象:初步测试显示平均推理延迟为1.8ms,看似满足要求。但用逻辑分析仪监控发现,当SPI DMA正在传输时,推理时间会从1.8ms跳变到3.4ms,偶尔达到4.1ms。进一步分析发现,DMA占用了AXI总线带宽,导致CPU访问Flash时插入额外等待周期。
分析判断过程:通过DWT->CYCCNT记录每次推理的周期数,并同时记录SPI DMA的状态标志。发现当DMA传输进行中(SPI->SR的BSY位为1),推理周期数增加约85%。这是因为STM32H743的AXI SRAM和Flash共享总线矩阵,DMA的突发传输(Burst=16)会阻塞CPU的Flash预取。
实际操作步骤:
- 将模型权重从Flash复制到AXI SRAM(地址0x24000000),利用其独立端口减少总线冲突;
- 将推理函数放入ITCM(指令紧耦合内存),确保指令获取不经过AXI总线;
- 调整DMA优先级为低,并设置合理的突发长度(从16改为8);
- 在推理前后关闭可屏蔽中断(
PRIMASK),但保留SysTick用于系统心跳。
结果对比:优化后,推理延迟稳定在1.62ms±0.03ms(P99=1.71ms),满足5ms硬实时要求。端到端吞吐量从180FPS提升到240FPS(受限于SPI采样率)。代价是SRAM占用增加12KB(权重+中间缓冲区),且临界区最长达到1.7ms,需确保外部看门狗超时时间大于此值。
复盘经验:① TinyML性能优化必须从“系统总线”视角出发,而非仅看CPU计算;② 硬实时验证必须覆盖“最坏总线负载”场景,不能只测空闲状态;③ 使用TCM和SRAM分区是提升确定性的最有效手段;④ 每次修改后需重新测量WCET,因为编译器优化和链接脚本变化会显著影响时序。
2.6 常见误区与总结复盘
误区一:将延迟和吞吐量混为一谈。在TinyML中,由于单核顺序执行,降低延迟通常也能提升吞吐量,但反之不然。例如,使用批处理(Batch)可以提升吞吐量,但会增加单次延迟。MCU上批处理不常用,因为内存有限且无GPU并行加速。
误区二:忽略中断对确定性的影响。很多开发者只在“干净”环境下测量延迟,但实际系统中,定时器中断、UART接收中断、ADC转换完成中断都会抢占CPU。一个简单的修复是:在推理期间屏蔽所有优先级低于某阈值的中断,但必须计算最坏情况下的中断屏蔽时间,防止丢失关键事件。
误区三:使用浮点类型导致数值不确定。不同编译器版本、不同优化级别下,浮点运算的融合(FMA)行为可能不同,导致同一模型在不同构建中输出略有差异。对于需要严格一致性的场景(如安全认证),应使用定点推理或固定编译选项。
误区四:只测平均延迟,不测尾部延迟。在TinyML中,P99延迟往往比平均值重要得多。例如,一个语音唤醒系统平均延迟10ms,但P99达到50ms,用户会明显感到“反应迟钝”。建议在测试报告中同时列出P50/P95/P99和最大值。
- 延迟关注单次推理的完整时间,必须用分位数(P50/P95/P99)描述,而非仅平均值。
- 吞吐量是系统级指标,受传感器、DMA、预处理影响,不等于1/延迟。
- 实时性强调“截止时间前完成”,硬实时必须测量WCET,并考虑总线冲突、Flash等待等最坏情况。
- 确定性包含时间和数值两个维度,抖动来源包括中断、缓存、DVFS和编译器优化。
- 优化优先级建议:先保证确定性(固定时钟、屏蔽中断、TCM放置),再优化平均延迟,最后提升吞吐量。