☰
TFLite Micro 持续构建产物解析:基于 size_profiling 数据的体积监控与性能回归检测
2026/10/4 1:50:11 网站建设 项目流程
  • 人工智能
  • 深度学习
  • 推理引擎
  • 本地部署
  • 嵌入式
  • 物联网

【免费下载链接】tflite-micro

Infrastructure to enable deployment of ML models to low-power resource-constrained embedded targets (including microcontrollers and digital signal processors).

项目地址:https://gitcode.com/gh_mirrors/tf/tflite-micro
点击查看免费下载

tflite-micro 的data/continuous_builds目录沉淀着一套由持续构建(Continuous Build)工作流自动生成的监控产物,其核心是若干记录二进制体积的 CSV 时序数据与配套的趋势图。本文以 data/continuous_builds/README.md 为骨架,结合仓库内真实产物与tensorflow/lite/micro/tools/metrics/下的生成脚本,系统讲解这套体积监控体系的产物格式、生成管线、三个被监控二进制的测量语义、阈值回归检测机制,以及如何在本地完整复现这套流程,帮助你掌握"用尺寸数据度量并发现性能波动"的完整实战方案。

目录结构:一次 CI 构建沉淀下来的监控产物

依据 data/continuous_builds/README.md,该目录"包含持续构建工作流自动生成的产物(artifacts),意图是监控这些产物(例如体积数据),以度量并发现任何性能波动";长期目标则是"基于这些产物,通过某种 Dashboard 持续监控这些性能数据点"。

当前仓库中实际的产物布局如下:

data/continuous_builds/ ├── README.md └── size_profiling/ └── linux_x86_64_release/ # 目标平台 + 架构 + 构建类型 ├── baseline_memory_footprint.csv ├── baseline_memory_footprint.png ├── interpreter_memory_footprint.csv ├── interpreter_memory_footprint.png ├── keyword_benchmark.csv └── keyword_benchmark.png

目录命名linux_x86_64_release由TARGET(linux)、TARGET_ARCH(x86_64)与BUILD_TYPE(release)三部分拼接而成,即"每个目标平台/构建配置"各占一个子目录。目录内每个被监控的二进制对应一对文件:.csv是可追加的时序体积记录,.png是脚本自动绘制的历史趋势图(另外两个图见 baseline_memory_footprint.png 与 interpreter_memory_footprint.png)。这套 CI 的整体机制(分层测试、审批门、Merge Queue 等)可参见 docs/continuous_integration.md。

CSV 数据格式:把二进制体积变成可追溯的时间序列

每个.csv文件都是一张扁平时序表,表头固定为:

字段含义
date采样时间戳(YYYY-MM-DD HH:MM:SS.ffffff,来自datetime.datetime.now())
sha构建时仓库 HEAD 的 40 位 Git commit SHA
textELF 可执行文件中 text 段(代码段)体积,单位字节
datadata 段(已初始化数据)体积,单位字节
bssbss 段(未初始化数据)体积,单位字节
total三者之和,即体积总量,单位字节

字段定义可在 create_size_log.py 中直接看到:脚本先按这六列创建(或复用)CSV,再把size命令输出的text、data、bss与dec四列逐一追加为一行,其中dec列被映射为total。

以baseline_memory_footprint.csv为例,仓库内首行与末行的真实数据为:

date,sha,text,data,bss,total 2022-01-10 23:04:44.309131,c53927869b2ce15345c6c1751164ca6e4aa47c02,1394,520,8,1922 ... 2022-07-14 13:15:35.665349,0e825b99b34596907f53e1fa245028576414cfd0,1433,568,8,2009

可以看到total恒等于text + data + bss(如1394+520+8=1922)。这份数据从 2022-01-10 持续采样到 2022-07-14,接近半年、整体高频(多数日期 1~2 条)的累积记录,并保留了每次采样对应的 commit SHA,使任何一次体积变化都能回溯到具体提交——这正是"可监控、可检测、可追溯"的数据基础。

生成管线:脚本如何从"编译"走到"检测"

体积产物的生成与检测由tensorflow/lite/micro/tools/metrics/下三个脚本接力完成,全程可在本地复现。

入口脚本:create_size_log_x86.sh

create_size_log_x86.sh 是面向 x86-64 Linux release 构建的入口,流程如下:

  1. 清理本地构建与第三方依赖下载缓存:make -f tensorflow/lite/micro/tools/make/Makefile clean clean_downloads;
  2. 下载第三方依赖:make -f tensorflow/lite/micro/tools/make/Makefile third_party_downloads;
  3. 指定三个被监控的二进制(见第 35 行):
    BINARY_LIST="keyword_benchmark,baseline_memory_footprint,interpreter_memory_footprint" python3 tensorflow/lite/micro/tools/metrics/create_size_log.py --build_type=release --target=linux --target_arch=x86_64 --binary_list=${BINARY_LIST}
  4. 对产物目录执行阈值检测与绘图(第 47-48 行):
    LOG_DIR="${ROOT_DIR}/data/continuous_builds/size_profiling/${TARGET}_${TARGET_ARCH}_${BUILD_TYPE}" python3 tensorflow/lite/micro/tools/metrics/detect_size_increase_and_plot_history.py --input_dir=${LOG_DIR} --output_dir=${LOG_DIR} --binary_list=${BINARY_LIST}
  5. 若脚本检测到体积增长超阈值则退出码非 0,脚本打印Size increase may exceed threshold并exit -1,从而让 CI 任务失败、触发人工介入;否则输出Size does not increase or size increase does not exceed threshold。

构建与采样:create_size_log.py

create_size_log.py 的_build_and_profile对每个二进制依次执行"构建 → 测量 → 追加记录":

  • 构建:_build_a_binary调用make -f tensorflow/lite/micro/tools/make/Makefile <binary_name> BUILD_TYPE=... TARGET=... TARGET_ARCH=...;
  • 测量:_profile_a_binary对gen/<target_dir>/bin/<binary_name>执行 GNU binutils 的size命令(源码第 51、61 行),把输出按空白切分为 DataFrame,再以build_info(当前时间 +git rev-parse HEAD得到的 SHA)补全date与sha后追加写回 CSV(report.to_csv(csv_path, index=False, header=False, mode='a'))。

脚本支持的参数与默认值如下(均可覆盖):

参数默认值说明
--binary_listkeyword_benchmark,baseline_memory_footprint,interpreter_memory_footprint逗号分隔的二进制列表
--build_typerelease构建类型
--targetlinux主机目标平台
--target_archx86_64目标架构

脚本依赖 Python 3 与pandas(源码第 20 行import pandas as pd)。

阈值检测与绘图:detect_size_increase_and_plot_history.py

detect_size_increase_and_plot_history.py 承担"回归检测 + 可视化"双重职责,两个关键常量定义在第 22-27 行:

# 仅回溯最近 60 天的体积历史 SIZE_HISTORY_DEPTH = 60 # text 与 total 段单次增量超过该阈值(字节)即判定失败 SIZE_THRESHOLD_SETTING = { "text": 512, "total": 512, }

检测逻辑为:读取 CSV 最后 60 行,用size_log[section_name].diff()求最近一次增量,若text或total的最近增量超过 512 字节,则收集一条失败消息;所有二进制的消息汇总后抛出RuntimeError,脚本退出非 0。也就是说,这套机制检测的是"最近一次提交导致的体积突增是否越过阈值",而不是绝对体积上限。

绘图部分(第 39-56 行)为每个二进制生成一张 3×2 的子图:三行分别对应text、data、total,左列为绝对体积(纵轴Abs Sz(bytes),折线o-),右列为逐次增量(纵轴Incr Sz (bytes)),并以Source: <binary_name>与采样起止日期作为总标题,保存为<binary_name>.png。本仓库linux_x86_64_release/目录下的三张 PNG 正是该脚本的输出(依赖matplotlib)。

三个被监控的二进制:测量方法论

为什么偏偏监控这三个二进制?它们的语义与测量方法论在 tensorflow/lite/micro/examples/memory_footprint/README.md 中有完整说明,核心思路是用"减法"把 TFLite Micro 的体积开销拆解开。

baseline_memory_footprint:无操作基线

构建 memory_footprint 下的baseline_memory_footprint目标(构建规则见 Makefile.inc),得到的是一个"无操作应用"(no-op application),通常只包含平台相关的初始化代码。它被视为与 TFLM 无关的固定开销基线。

interpreter_memory_footprint:TFLM 框架

同目录下的interpreter_memory_footprint(源码 interpreter_memory_footprint.cc)会拉入创建解释器实例所需的全部 TFLM 框架代码(解释器、内存规划器等),但刻意不注册任何内核,因此该二进制无法真正执行推理。两个体积之差即为 TFLM 框架(Framework)的代码量估算:interpreter_memory_footprint − baseline_memory_footprint。

keyword_benchmark:完整应用与内核开销

keyword_benchmark.cc(构建规则见 Makefile.inc)基于带打乱权重/偏置的关键词检测模型(tensorflow/lite/micro/models/keyword_scrambled.tflite),仅用于平台性能与体积测量而非精度验证。它包含框架 + 该模型所需内核 + 系统库,因此:

  • keyword_benchmark − interpreter_memory_footprint≈ 该应用引入的内核代码量;
  • 其运行逻辑封装在 micro_benchmark.h 的MicroBenchmarkRunner模板类中——它通过RecordingMicroAllocator与RecordingMicroInterpreter创建解释器、AllocateTensors()分配张量、Invoke()执行推理,并提供PrintAllocations()打印内存分配明细。

一个值得注意的方法论细节:由于baseline/interpreter目标未注册内核,MicroMutableOpResolver 产生的代码量会被计入"内核开销"而非"框架开销";文档明确这是为了简单、稳健并纳入系统库贡献而有意为之的取舍。文档还给出过参考快照:按此法测得 64 位 x86 平台 TFLM 框架约 20411 字节(旧数据快照,仅作参考)。

差值方法论总结

TFLM 框架代码量 ≈ interpreter_memory_footprint − baseline_memory_footprint 关键字模型内核代码量 ≈ keyword_benchmark − interpreter_memory_footprint

文档同时提醒:完整应用通常还包含 FlatBuffer 格式的 TFLite 模型与内存 arena,它们一般落在 ELF 的 data 段,同样是整体内存占用的重要部分,但不属于本文讨论的代码量范畴。

从数据看趋势:仓库内 CSV 揭示的体积演变

仓库内三份 CSV 记录了 2022-01 至 2022-07 的真实演变,可以直接观察到几次阶梯式增长(与提交 SHA 一一对应):

baseline_memory_footprint.csv(单位字节):

时间点textdatabsstotal
2022-01-10139452081922
2022-01-31143356882009
2022-07-14143356882009

interpreter_memory_footprint.csv:

时间点textdatabsstotal
2022-01-102259914642424087
2022-01-312375616002425380
2022-03-092623216482427904
2022-04-272764818242429496
2022-07-142761618242429464

keyword_benchmark.csv:

时间点textdatabsstotal
2022-01-1081657156822400105625
2022-01-3183141169622448107285
2022-03-0985877174422448110069
2022-04-2787277192022480111677
2022-06-1688645192022480113045
2022-07-1288597192022480112997

几个可验证的观察点:

  • 框架开销:按差值法,2022-01-10 时框架约为24087−1922=22165字节,到 2022-07-14 增至29464−2009=27455字节,半年内框架体积增长了约 5KB;
  • 内核开销:keyword_benchmark 与 interpreter 之差从 2022-01-10 的105625−24087=81538字节增至 2022-07-14 的112997−29464=86533字节;
  • bss 差异:keyword_benchmark 的 bss 段(约 22.4KB 起步)显著大于前两者(8~24 字节),这与完整应用携带的大规模静态缓冲区形态一致(具体段归属可结合 memory_footprint README 中"模型与 arena 通常落在 data 段"的说明进一步分析);
  • 每次跃迁都伴随新的sha字段,例如 interpreter 在 2022-01-31 的746f880a...提交后从 24087 跳到 25380,体现了"体积变化可回溯到具体提交"的设计意图。

本地复现:把监控管线跑起来

在仓库根目录按以下步骤即可完整复现整套体积监控(需要make、GNUsize、Python 3、pandas、matplotlib):

# 1. 清理构建缓存并下载第三方依赖 make -f tensorflow/lite/micro/tools/make/Makefile clean clean_downloads make -f tensorflow/lite/micro/tools/make/Makefile third_party_downloads # 2. 构建三个二进制、用 size 采样并追加到 CSV python3 tensorflow/lite/micro/tools/metrics/create_size_log.py \ --build_type=release --target=linux --target_arch=x86_64 \ --binary_list=keyword_benchmark,baseline_memory_footprint,interpreter_memory_footprint # 3. 回溯最近 60 天历史、检测 text/total 增量是否超过 512 字节阈值,并生成趋势图 python3 tensorflow/lite/micro/tools/metrics/detect_size_increase_and_plot_history.py \ --input_dir=data/continuous_builds/size_profiling/linux_x86_64_release \ --output_dir=data/continuous_builds/size_profiling/linux_x86_64_release \ --binary_list=keyword_benchmark,baseline_memory_footprint,interpreter_memory_footprint

产物写入data/continuous_builds/size_profiling/linux_x86_64_release/(二进制位于gen/linux_x86_64_release/bin/)。如需监控其他平台,可仿照 create_size_log_x86.sh 把--target/--target_arch换成目标配置(例如 ARM Cortex-M 平台),并保持输出目录命名规则一致。想单独运行基准本身,也可直接使用 benchmarks README 中的make -f tensorflow/lite/micro/tools/make/Makefile run_keyword_benchmark等目标。

长期愿景:以产物为数据源的性能 Dashboard

data/continuous_builds/README.md 明确写到:"长期目标是通过基于这些产物的 Dashboard 来监控这些性能数据点。"当前这套 CSV + PNG 的落地形态已经为这一目标铺好了路:

  • 时序友好:记录以追加方式持续累积,天然是按时间排序的序列数据,可直接喂给时序数据库或图表组件;
  • 可追溯:每条记录携带 commit SHA,异常体积跃迁可一键定位到具体提交;
  • 阈值化:512 字节的 text/total 增量阈值已内置到检测脚本中,Dashboard 可以在此基础上做趋势告警、跨平台对比与长期漂移分析。

换句话说,现阶段"持续构建 → 采样体积 → 追加 CSV → 检测阈值 → 输出趋势图"的闭环,已经是一个轻量、可扩展、可本地复现的性能监控雏形。

小结

本文以 data/continuous_builds/README.md 为线索,完整还原了 tflite-micro 持续构建体积监控体系的三个层次:产物层(linux_x86_64_release/下的 CSV 与 PNG,字段为date/sha/text/data/bss/total)、管线层(create_size_log_x86.sh→create_size_log.py采样 →detect_size_increase_and_plot_history.py阈值检测与绘图)、语义层(baseline/interpreter/keyword_benchmark三个二进制的减法方法论)。这套体系的价值在于:把"体积与性能波动"从一次性的静态检查,变成了可追溯、可阈值告警、可持续观测的动态闭环——这既是文档所述意图的直接落地,也是未来 Dashboard 化监控的现成数据源。

  • 人工智能
  • 深度学习
  • 推理引擎
  • 本地部署
  • 嵌入式
  • 物联网

【免费下载链接】tflite-micro

Infrastructure to enable deployment of ML models to low-power resource-constrained embedded targets (including microcontrollers and digital signal processors).

项目地址:https://gitcode.com/gh_mirrors/tf/tflite-micro
点击查看免费下载

相关推荐

上一篇:极致优化:Emscripten WebAssembly压缩全攻略(gzip/brotli/wasm-gzip)
下一篇:终极Atuin指南:如何与tmux和screen完美集成提升终端效率

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询