概览¶
概述¶
本文介绍在 SF32 上部署端侧 AI 的工程流程:选择器件、按实际执行路径准备模型、规划内存,并在整机能耗预算内调度推理。本文以 AI 加速器架构中的硬件知识为基础;如果希望先了解加速器的作用和限制,建议先阅读该文。
SDK 通过 NNACC(神经网络加速器)HAL 提供加速运算接口,并分别提供 HAL 示例和 RT-Thread 驱动示例。这两个示例验证的是单个逐通道卷积算子(depthwise convolution),并非完整的已训练模型部署流程。先用示例确认单个算子能够正确运行,再单独选择并验证模型运行时、转换工具和各层的实现方式。
下文引用的实现细节仅适用于 SDK v2.5.1。无论是这些细节,还是系列层面的 NNACC 可用性,都不能保证特定型号一定支持,也不能保证存在完整模型的运行时或转换工具、算子兼容、自动 CPU 回退或摄像头输入。请针对具体的 SDK 版本与配置、芯片修订版、运行时和开发板逐项核实。
如果你负责 AI 功能的产品决策和部署,可以用本文梳理几个关键问题:设备需要在本地完成哪些判断、可用的内存和能耗预算是多少,以及面对真实传感器数据时功能应如何表现。它与加速器一文互为补充,后者说明硬件的能力边界。
明确产品必须在本地完成的判断¶
先定义产品需要作出的判断,再选择模型:
- 设备必须在不经过手机或云端往返的情况下,自主完成哪些分类或检测?
- 判断依赖哪些传感器——运动、音频、生物特征、摄像头,还是多种传感器的组合?
- 需要多频繁地作出判断?端到端响应延迟(latency)应控制在什么范围内?
- 端侧模型判断错误会造成什么后果——误报和漏报,哪一种代价更高?
- 模型将来是否需要现场更新?如果需要,采用什么更新方式?
这些答案会影响后续所有设计:模型大小、内存预算、器件选型,以及两次推理之间系统可以进入多深的低功耗状态。
选择合适的 SF32 器件¶
不同 SF32 器件面向的 AI 工作负载并不相同:
| 需求 | 典型器件方向 |
|---|---|
| 成本优化型产品中的轻量级、低频分类 | SF32LB52x——保持模型紧凑,并以 CPU 执行为主。 |
| 具有基础传感器融合需求的 BLE 可穿戴设备 | SF32LB55x |
| 同时运行 UI,并需要更丰富的传感器或多媒体流水线 | SF32LB56x |
| 边缘 AI 为主要功能:运行较大模型、使用所选器件支持的摄像头输入,或满足严格的延迟要求 | SF32LB58x |
上表只是选型评估的起点,并不保证模型一定能装入内存或高效运行。应结合完整工作负载,核实具体型号的内存、传感器接口、加速器实例和 SDK 支持情况。SDK v2.5.1 NNACC 文档记载:SF32LB55x 和 SF32LB56x 的 HCPU 各有一个 NNACC;SF32LB58x 的 HCPU 和 LCPU 各有一个 NNACC。该文档没有说明 SF32LB52x 或 SF32LB57x 是否配备 NNACC;应将其视为尚未确认,不能把未列出解读为不具备。所列数量本身也不能说明模型是否兼容或能效如何。整体选型思路请参阅器件系列定位。
模型开发工作流程¶
无论具体应用是什么,将模型部署到 SF32 硬件通常都遵循相同流程:
- 在工作站上训练或选择模型。训练数据必须真实反映传感器在实际环境中看到的输入;干净的实验室数据与带噪声的真实传感器输入往往表现差异明显。
- 在考虑加速器专用转换之前,先通过架构选择、剪枝或量化等方法,使模型满足嵌入式约束。
- 导出模型并映射算子,使其符合所选推理运行时,以及目标 SDK 实际支持的算子、数据布局和数值格式。仅有 NNACC HAL,并不意味着已有整模型转换工具或计算图运行时。
- 转换和量化后进行数值验证;不要假定桌面端精度会原样保留。
- 将预处理、推理和后处理集成到固件中——模型调用只是完整流水线中的一个环节。
- 在真实硬件上分析延迟(latency)、内存、功耗和精度,而不是只依赖仿真结果。
- 在真实的组合负载下测试——推理运行时,蓝牙(Bluetooth)、显示和传感器也应同时工作,而不是逐项隔离测试。
常见的集成问题是只优化模型,却没有测量预处理、缓冲和后处理。这些环节的开销可能与加速后的推理相当,因此应分析完整处理路径。
明确运行时约束¶
转换模型前,应明确记录固件必须满足的运行时约束:
| 约束项目 | 必须确定的内容 |
|---|---|
| 输入形状 | 采样窗口、图像尺寸、通道数和张量布局。 |
| 数值格式 | 整数位宽、缩放因子与零点处理方式、校准数据集。 |
| 算子集合 | 哪些层必须在 NNACC 上运行,哪些层允许回退到 CPU。 |
| 延迟目标 | 完整流水线的端到端延迟,而不只是加速器执行时间。 |
| 内存上限 | 权重、激活值、输入/输出张量,以及预处理和后处理缓冲区。 |
| 更新策略 | 模型能否通过 OTA 更换,以及如何验证新模型。 |
这些约束应由机器学习和固件负责人共同评审。如果模型的张量形状、数据格式或算子组合发生变化,而固件没有同步更新,问题往往表现为精度下降或延迟不稳定,而不是明确的构建错误。
审查算子与回退路径¶
选模型之前,应逐项核实算子、参数和实际执行路径。CPU 实现或自动回退必须由所选运行时明确提供;不支持的运算也可能直接导致模型无法部署。即使模型很小,频繁在 CPU 上执行的层或反复发生的数据布局转换,仍可能拖慢整个流水线。
| 类别 | 含义 | 处理方式 |
|---|---|---|
| 硬件加速 | 目标器件的 NNACC 路径可直接支持。 | 热点层优先采用。 |
| CPU 回退 | 所选运行时或固件提供了经过验证的 CPU 实现。 | 实测其开销;只有完整流水线满足目标时才接受。 |
| 需要转换 | 需要转换布局、数据类型或格式。 | 将转换开销计入延迟和功耗预算。 |
| 不支持 | 目标运行时无法执行。 | 替换该层或更改模型架构。 |
验收标准不能只是“模型可以运行”,而应是“在与产品现场输入相同的数据分布下,完整流水线同时满足精度、延迟、内存和能耗目标”。
量化与内存预算¶
微控制器 AI 常采用紧凑的量化模型,通常使用 8 位整数而非浮点数。数值格式应以实际执行路径支持的格式为准。确定模型架构前,内存预算必须覆盖以下全部项目,而不能只计算权重:
| 内存占用项 | 说明 |
|---|---|
| 模型权重 | 量化可显著减小体积,但权重仍是基础占用。 |
| 输入张量 | 大小由传感器窗口、图像分辨率或音频帧长度决定。 |
| 中间激活值 | 很容易被低估;某些架构的激活值甚至大于权重。 |
| 输出张量 | 通常较小,但仍必须纳入预算。 |
| 预处理和后处理缓冲区 | 滤波、分帧、特征提取和阈值判断均需要工作内存。 |
| 其他并发功能的内存占用 | UI、蓝牙和音频缓冲区会同时竞争相同的 SRAM/PSRAM。 |
量化可以降低内存和计算开销,但转换后必须用有代表性的传感器数据重新验证精度。SDK v2.5.1 文档列出了三个加速接口:arm_convolve_1x1_HWC_q7_fast_nonsquare、arm_convolve_HWC_q7_basic_nonsquare 和 arm_depthwise_separable_conv_HWC_q7_nonsquare。HAL 配置使用 8 位缓冲区,以及偏置和输出移位参数;这不等于任意现代 int8 模型的零点和逐通道缩放因子都能直接兼容。应核实数值结果是否等价,并为每个未受支持的层明确 CPU 实现、转换或拒绝部署的处理路径。
缓冲区的内存位置与内存层级¶
即使计算能力足够,内存带宽仍可能限制 AI 性能。在配有 SRAM、Flash、PSRAM 和 STAR-MC1 指令/数据缓存的 SF32 器件上,应同时核实内存是否可访问,以及缓冲区放置位置带来的开销:
- 将频繁访问的张量和中间缓冲区放在 CPU 与所选加速器实例都能访问的内存中,并满足对齐和数据布局要求。
- 只有所选执行路径支持时,才能将大型权重或低频访问资源放在外部存储器中。如果需要复制到加速器可访问的内存,应将复制开销同时计入内存、延迟和能耗预算。
- 传输期间,共享缓冲区只能由 CPU 或加速器/DMA 中的一方使用。硬件访问前,按完整缓存行对齐范围准备缓冲区:对包含 CPU 写入输入数据的缓存行执行 clean 操作,并按 SDK 的设备写入规则处理输出区域中的脏缓存行。等待硬件完成后,再对输出范围执行 invalidate,交回 CPU 使用。硬件持有缓冲区期间,不要修改该缓冲区,也不要修改与它共用缓存行的其他数据。
v2.5.1 HAL 实现会检查各缓冲区是否跨越 1 MiB(1,048,576 字节)地址窗口,并要求输入和偏置位于同一窗口。应验证实际分配的地址,不能只看剩余内存总量。阻塞启动接口通过轮询等待完成;中断方式则需要正确的 IRQ 处理和完成通知。应检查返回值,并在应用层设计故障恢复和有时限的等待机制,不能假定模型运行时已经提供超时保护。
有关此类混合访问模式下的缓存与内存系统注意事项,请参阅 STAR-MC1。
内存容量规划表¶
固件集成前应填写内存容量规划表,并采用最坏情况数据,而不是平均值估算:
| 缓冲区 | 容量决定因素 | 首选存放位置 |
|---|---|---|
| 原始输入窗口 | 采样率 × 通道数 × 窗口时长 × 每个样本的字节数,再加上布局填充 | 如果由外设采集,应使用 DMA 可访问的内存。 |
| 预处理工作区 | 滤波、FFT/MFCC、归一化、缩放或裁剪 | 每次推理都要复用时,放入高速 SRAM。 |
| 模型权重 | 量化后的模型大小 | 若运行时支持,可放入 Flash/PSRAM;仅将热点部分放入 SRAM。 |
| 激活值 | 最大的中间张量 | 加速器可访问的高速内存。 |
| 输出和后处理 | 类别、边界框、分数和平滑状态 | SRAM;通常较小,但对延迟敏感。 |
| 共存缓冲区 | 音频、显示、蓝牙和日志 | 同时预算,不要等 AI“装得下”之后再算。 |
还要为栈、堆、RTOS 对象、日志和 OTA 预留空间。只有在禁用所有其他子系统后才能装入的模型,不具备产品化条件。
构建完整流水线¶
加速器只是从传感器输入到产品判断这一完整流水线中的一个阶段。下面介绍三类常见输入路径。
音频与语音¶
关键词识别、唤醒词触发和音频事件分类,都需要先完成麦克风采集、分帧和特征提取,之后才能开始推理。流水线的采集和缓冲部分请参阅音频概览。只有先高效地采集并缓冲输入音频,加速器才能发挥作用。
运动与传感器融合¶
手势识别、活动分类和生物信号分析通常使用加速度计、陀螺仪或其他传感器的数据流。先分别测量传感器工作、采集、预处理和推理的能耗,再判断主要耗电环节。在延迟和信号覆盖要求允许时,批量处理和中断驱动采集可以减少唤醒,但不能一概认定它们比模型开销更重要。调度建议请参阅低功耗概览。
摄像头与图像输入¶
摄像头输入可能带来较大的采集、缓冲、带宽和推理开销;实际负载取决于分辨率、帧率、传感器工作方式和模型架构。在精度允许时,可以缩小图像或只处理感兴趣区域。应按嵌入式约束选择模型,不能假定桌面端视觉模型可以原样部署。
面向功耗的推理调度¶
应根据检测覆盖范围和响应时间要求选择调度方式。产品需要定期判断时,周期推理是合理方案;只有不会漏掉必要信号时,才适合用事件条件控制是否启动推理。
- 在适合的场景下,由有效的新数据触发推理,例如传感器越过阈值或完整音频帧就绪。需要周期处理时应保留该方式;调整触发条件后,重新验证漏检情况和最坏响应时间。
- 在延迟要求允许时批量处理样本,避免运行大量小规模推理。
- 如果器件和 SDK 支持,应把轻量级常开感知任务放到低功耗处理器上,避免每个样本都唤醒主应用 CPU。
- 在明确的测量时间窗口内,对实测供电功率(供电电压×电流)进行时间积分,得到每次推理的能耗。功能能耗预算还应包括采集、预处理、后处理,以及唤醒和睡眠切换。加快处理可能降低工作期间的能耗,也可能让系统更早睡眠,但实际收益取决于电流、存储器访问和其他系统活动。
完整的系统级功耗建议请参阅低功耗概览。对于需要连续或近乎连续运行的 AI 功能,应将其作为配套文档使用。
精度、延迟与功耗的权衡¶
下表列出常见的设计取舍,并不代表固定的因果关系。作出取舍时,应实测模型精度和完整流水线的能耗:
| 优先目标 | 典型设计压力 |
|---|---|
| 更高精度 | 更大的模型、更多输入特征、更长的窗口和更多内存。 |
| 更低延迟 | 缩短采集窗口、加快执行或提高判断频率;同时验证对精度和能耗的影响。 |
| 更低功耗 | 降低推理频率、采用紧凑模型、优化内存布局,并在两次运行之间尽可能进入低功耗睡眠。 |
开始调优前,应先确定产品真正需要偏向哪一端。例如,手势检测器通常可以用少量延迟换取更长续航;语音触发通常不能容忍明显延迟,同时还必须避免误唤醒造成额外耗电。
模型更新与现场验证¶
如果 AI 功能可能在产品发布后继续改进,应尽早设计模型更新能力:
- 在可行时,将模型与固件分别管理版本,并在模型包中记录预期的输入规范。
- 激活前验证模型包的来源真实性、完整性,以及与运行时和输入规范的兼容性。激活流程应能应对更新中断;启动验证失败时,应能回退到已验证可用的版本。
- 将校准数据、阈值和后处理常量与需要它们的模型版本一起保存。
- 记录足以诊断数据漂移的现场统计信息,同时避免不必要地保存敏感的原始传感器数据。
- 每次更新模型后,重新执行功耗和共存测试。即使模型精度提高,如果导致系统更频繁地唤醒,仍属于产品回归。
调试 AI 性能与精度¶
| 现象 | 重点检查方向 |
|---|---|
| 模型可以运行,但精度低于工作站结果 | 量化或校准不匹配,或者训练数据不能代表真实传感器噪声。 |
| 推理速度低于预期 | 各层实际是否在 CPU 上执行,以及布局转换、内存带宽或调度竞争。 |
| 系统始终无法进入预期的睡眠深度 | 不必要的唤醒、未关闭的驱动或时钟、电源管理锁,或尚未完成的加速器事务。 |
| 功能单独运行正常,但在完整产品中失效 | 未在组合负载下测试,即蓝牙、显示和传感器没有同时工作。 |
| 模型“很快”,但功耗仍然很高 | 只测量延迟,没有测量每次推理能耗;两次运行之间编解码器或传感器路径仍保持工作。 |
| 共享缓冲区偶发产生无效输出 | 缓存行准备、脏缓存行风险、过早复用、缺少完成通知,或 CPU 与硬件同时访问。 |
常见错误¶
- 尚未检查目标运行时实际加速哪些算子,就先确定模型架构。
- 直接移植桌面级模型,而不是从一开始就按嵌入式约束进行设计。
- 忽略中间激活值的内存开销,只为模型权重预留空间。
- 未验证推理频率和触发条件是否满足输入覆盖范围与响应时间要求。
- 只在干净的实验室数据上验证精度,从未覆盖真实环境或传感器噪声。
- 隔离测试 AI 功能,直到整机集成后才发现共存问题。
- 只优化模型延迟,忽略外围的预处理和后处理阶段。
AI 功能启动调试检查清单¶
- 明确产品需要在本地作出的判断,以及可接受的延迟、精度和功耗权衡。
- 根据模型大小和内存需求选择 SF32 器件,而不只是依据成本目标。
- 先使用最小测试模型,再使用量产模型,构建并验证完整流水线(采集 → 预处理 → 推理 → 后处理)。
- 转换并量化实际模型,然后使用符合真实情况的传感器数据验证精度。
- 同时预算权重、输入/输出张量和中间激活值所需的内存。
- 验证所有 CPU 与加速器共享缓冲区的缓存一致性处理。
- 验证周期或事件驱动调度是否满足检测覆盖范围、最坏延迟和实测能耗预算。
- 在蓝牙、显示和传感器同时工作的组合系统负载下,分析每次推理的能耗。
- 每次更改量化方式、模型或调度策略后,重新验证精度和功耗。
要点¶
- 从产品判断和传感器数据出发,而不是从模型架构出发;模型只是完整流水线中的一个阶段。
- 先按系列定位建立候选清单,再核实具体型号、SDK、算子映射、内存分配和并发工作负载。
- 应为完整流水线规划内存,包括权重、张量、激活值以及预处理和后处理缓冲区,不能只看模型文件大小。
- 根据检测覆盖要求选择周期或事件驱动推理,并测量完整功能的能耗,不能把模型速度直接当作功耗结论。
- 使用符合真实现场情况的数据验证精度,并在组合系统负载下测试完整功能,而不能只做隔离测试。
最后更新: