2、基础知识:TinyML在线推理与离线推理的区别、实时性要求、资源约束
TinyML 的核心应用场景是让机器学习模型在微控制器(MCU)等极低功耗设备上持续运行,完成对传感器数据的实时处理。在进入环形缓冲区与连续窗口更新的具体实现之前,必须先厘清一个根本性问题:在线推理(Online Inference)与离线推理(Offline Inference)在 TinyML 语境下究竟有何本质差异? 这种差异决定了数据流架构、内存管理策略以及算法设计的选择。本章将从执行模式、实时性指标、资源约束三个维度展开,为后续实现连续窗口更新打下坚实的理论基础。
2.1 核心原理:两种推理范式的本质差异
离线推理(Offline Inference)在 TinyML 中通常指模型在非实时约束下对已完整采集的数据集进行批量处理。典型场景包括:开发阶段在 PC 上对传感器日志进行回放分析、设备端对存储在 Flash 中的历史数据进行周期性诊断、或者将数据上传至云端后由服务器完成推理。其核心特征是数据完整性——推理引擎在启动时已经拥有全部输入数据,因此可以执行全局归一化、排序、多遍扫描等操作,而不必担心数据流中断。
在线推理(Online Inference)则要求模型在数据持续到达的过程中实时产出结果。MCU 上的传感器以固定频率(如 IMU 的 100Hz、麦克风的 16kHz)不断产生新样本,推理引擎必须在一个严格的时间预算内完成当前窗口的处理,并立即输出结果。其核心特征是数据流的有界性——系统无法保存全部历史数据,只能维护一个固定大小的滑动窗口,窗口外的数据被永久丢弃。这种"边到边"的处理模式,正是环形缓冲区存在的根本原因。
从系统架构角度看,两种推理模式对内存、计算和功耗的要求截然不同。离线推理可以"先收集、后计算",因此允许使用较大的内存缓冲区,甚至可以将数据暂存至外部 Flash;而在线推理必须在每个采样间隔内完成"读取-更新-推理-输出"的完整链路,任何一步的延迟超标都会导致数据丢失或推理结果过期。
2.2 实时性要求:从"快"到"可预测"
实时性(Real-time)在 TinyML 中有两层含义:延迟上限和延迟抖动。对于唤醒词检测(如"Hey Siri"),系统必须在 200ms 内给出响应,否则用户体验会明显下降;对于工业异常监测,从异常发生到报警输出的延迟必须小于设备保护动作的机械时间常数。但更重要的是确定性——推理时间不能出现大的波动,否则即使平均延迟很低,偶发的长延迟也会导致数据覆盖或控制失效。
实时性要求直接决定了数据缓冲策略。假设 IMU 以 100Hz 输出数据,每个样本间隔为 10ms。若模型推理需要 8ms,则系统只有 2ms 的余量用于数据读取、特征提取和结果输出。此时,如果采用"采集完一批再处理"的离线模式,缓冲区会迅速溢出;而在线模式通过流水线重叠(在传感器采集下一个样本的同时,对当前窗口进行推理)可以隐藏部分处理延迟。
| 维度 | 离线推理 | 在线推理 |
|---|---|---|
| 延迟要求 | 秒级~分钟级,无硬性上限 | 毫秒级~百毫秒级,有硬性截止时间 |
| 数据访问 | 随机访问完整数据集 | 顺序访问有界滑动窗口 |
| 内存模型 | 峰值内存 = 数据集大小 | 固定内存 = 窗口大小 × 通道数 × 字节数 |
| 计算模式 | 可多遍扫描、全局优化 | 单遍扫描、增量更新 |
| 失败代价 | 重新运行即可 | 数据永久丢失,推理结果过期 |
| 典型场景 | 模型训练、日志分析、固件升级 | 唤醒词、手势识别、预测性维护 |
2.3 资源约束:MCU 上的"不可能三角"
TinyML 设备通常基于 Cortex-M 系列 MCU,典型配置为:Flash 256KB~1MB,SRAM 64KB~256KB,主频 48MHz~240MHz。与云端 GPU 或手机 SoC 相比,这些资源极其有限。在线推理系统必须在三个相互制约的目标之间寻找平衡:内存占用(决定窗口大小和模型复杂度)、计算延迟(决定能否满足实时性)、功耗预算(决定电池寿命)。
以 1D 卷积神经网络(用于振动信号分类)为例:输入窗口为 128 个样本、3 轴加速度数据(即 128×3=384 个浮点数),若使用 float32 存储,仅输入缓冲区就需要 1536 字节。加上中间特征图、模型权重和输出层,总内存需求可能达到 20~50KB。在 64KB SRAM 的 MCU 上,这已经占用了 30%~80% 的内存。因此,量化(int8)和环形缓冲区复用成为必然选择——前者将内存占用减少 4 倍,后者避免每次推理都重新分配缓冲区。
计算资源方面,Cortex-M4 系列带有 FPU(浮点单元),但浮点运算仍然比整数运算慢 3~5 倍。对于 16kHz 的音频流,每 20ms 窗口(320 个样本)需要完成一次推理,若模型包含 3 层卷积,总乘加操作数约为 50 万次。在 80MHz 主频下,这大约需要 6~10ms,勉强满足实时性要求。若改用 int8 量化,计算时间可缩短至 2~3ms,为系统留出更多余量。
2.4 案例拆解:可穿戴设备上的连续活动识别
让我们通过一个具体的工程案例来理解上述概念。假设我们要在 STM32L4 系列 MCU(Cortex-M4F,80MHz,64KB SRAM)上实现一个连续活动识别系统,用于区分"静止/走路/跑步"三种状态。加速度计以 50Hz 采样,每 2 秒输出一个分类结果(即窗口长度为 100 个样本)。
初始方案(离线思路):开发者首先尝试将 2 秒内的 100 个样本全部存入数组,然后调用模型推理。问题很快暴露:当系统需要连续运行时,每 2 秒就要分配一次 100×3×4=1200 字节的缓冲区,且推理期间无法采集新数据,导致数据丢失。更严重的是,如果模型推理时间超过 20ms(采样间隔),传感器 FIFO 溢出,数据被硬件丢弃。
改进方案(在线思路):改用环形缓冲区,容量为 128 个样本(略大于窗口长度,留出余量)。每次新样本到达时,写入环形缓冲区头部;当缓冲区中有效样本数达到 100 时,触发一次推理。推理时,从环形缓冲区中按顺序读取最近 100 个样本,形成窗口数据。推理完成后,不删除旧数据,而是通过覆盖机制自然淘汰过期样本。
关键参数对比:
| 指标 | 离线方案 | 在线方案(环形缓冲区) |
|---|---|---|
| 内存占用 | 1200B(每次分配)+ 碎片 | 128×3×2=768B(int16 量化,静态分配) |
| 数据丢失率 | 推理期间丢失 10~20 个样本 | 0(推理与采集并行) |
| 延迟抖动 | ±50ms(受内存分配影响) | ±5ms(固定时间片) |
| CPU 占用 | 峰值 100%,平均 30% | 峰值 60%,平均 40% |
实现要点:环形缓冲区使用写指针和读指针管理。写指针由中断服务程序(ISR)更新,读指针由推理任务更新。当两者相等时表示缓冲区为空;当写指针追上读指针时表示缓冲区已满(此时可选择覆盖最旧数据或丢弃新数据)。在本案例中,由于窗口长度(100)小于缓冲区容量(128),读指针始终落后于写指针至少 28 个样本,确保推理任务有足够的数据可用。
复盘经验:这个案例揭示了在线推理设计的三个核心原则:① 缓冲区大小 = 窗口长度 + 处理延迟余量;② 数据采集与推理必须解耦(通过中断+主循环或 RTOS 任务);③ 内存分配必须静态化,避免运行时 malloc。这些原则将在后续章节中通过环形缓冲区的具体实现进一步展开。
2.5 常见误区与总结复盘
误区一:认为在线推理只是"更快地做离线推理"。实际上,在线推理改变了数据访问模式、内存模型和算法设计。离线推理可以多次遍历数据,而在线推理必须单遍完成;离线推理可以使用全局统计量,而在线推理只能使用窗口内的局部统计量。
误区二:忽视延迟抖动的影响。即使平均推理时间满足实时性要求,偶发的长延迟(如缓存未命中、中断抢占)也可能导致数据覆盖。解决方法是预留 20%~30% 的 CPU 余量,并使用双缓冲或环形缓冲区吸收抖动。
误区三:在 MCU 上使用浮点模型而不做量化。浮点运算在 Cortex-M4F 上虽然可用,但功耗和延迟代价高昂。对于在线推理,int8 量化几乎是强制要求——不仅减少内存带宽,还能利用 SIMD 指令加速。
误区四:动态分配内存。MCU 上的堆空间有限且容易碎片化。在线推理系统必须使用静态分配的环形缓冲区、特征缓冲区和输出缓冲区。所有内存需求应在编译时确定。
总结:在线推理与离线推理的本质区别在于数据流的有界性和时间确定性。TinyML 设备必须在有限的内存和计算资源下,以可预测的延迟持续处理传感器数据流。环形缓冲区正是为了解决"有界数据存储"和"连续窗口更新"这两个核心问题而引入的基础数据结构。理解这些基础知识,是后续实现高效在线推理系统的前提。