TensorFlow Lite 如何用 benchmark_model 工具测量模型的初始化时间、推理时延与内存占用?
【免费下载链接】tensorflowAn Open Source Machine Learning Framework for Everyone项目地址: https://gitcode.com/GitHub_Trending/te/tensorflow
拿到一个 TFLite 模型后,想知道它在目标设备上初始化要花多久、每次推理的时延是多少、运行时占多少内存,可以用 TensorFlow Lite 自带的基准测试工具benchmark_model完成。该工具是一个 C++ 命令行二进制,可以在 Linux、Mac、嵌入式设备和 Android 设备上直接运行,也可以打包成 Android / iOS 应用运行。本文以原生命令行二进制为主路径,说明从获取工具、执行基准测试到读取结果的完整操作过程。
benchmark_model 测量哪些指标
根据 性能测量文档,TensorFlow Lite 基准测试工具目前测量并统计以下指标:
- 初始化时间(Initialization time)
- 热身状态下的推理时间(Inference time of warmup state)
- 稳定状态下的推理时间(Inference time of steady state)
- 初始化阶段的内存占用(Memory usage during initialization time)
- 总体内存占用(Overall memory usage)
工具会接收一个 TFLite 模型,为模型输入生成随机数据,然后按指定次数重复运行模型,最后输出聚合的时延统计(见 工具 README)。
获取 benchmark_model 二进制
有两条途径,任选其一:
途径一:下载 nightly 预编译二进制(可选路径)。性能测量文档的 “Download or build the binary” 一节列出了各平台的 nightly 预编译下载链接,包括linux_x86-64、linux_aarch64、linux_arm、android_aarch64、android_arm,以及支持 TF ops(Flex delegate)的plus_flex变体。
途径二:从源码构建(主路径)。在 TensorFlow 源码树中执行:
bazel build -c opt //tensorflow/lite/tools/benchmark:benchmark_model构建出的二进制位于bazel-bin/tensorflow/lite/tools/benchmark/benchmark_model。构建 Android 版本时使用:
bazel build -c opt --config=android_arm64 \ //tensorflow/lite/tools/benchmark:benchmark_modelAndroid 交叉编译需要先配置 NDK/SDK 构建环境(文档中的 “On Android” 一节有说明)。
两个前提需要注意:
- 基准测试工具必须用支持模型中所有 op 的 TFLite runtime 编译。如果模型包含 TF ops(flex ops),看到报错
ERROR: Select TensorFlow op(s), included in the given model, is(are) not supported by this interpreter.时,需要改用支持 TensorFlow ops 的方式构建:使用benchmark_model_plus_flex目标并加--config=monolithic标志,然后按同样的流程运行生成的benchmark_model_plus_flex。 - 如果模型包含自定义算子,报错形如
ERROR: Op type not registered 'XXXXXXXX' in binary running on localhost.,需要自行创建一个依赖自定义算子规则和//tensorflow/lite/tools/benchmark:benchmark_model_main的cc_binary目标(README 的 “Build the benchmark tool with Custom ops support” 一节给出了示例)。
在桌面设备上运行基准测试
模型文件以mobilenet_quant_v1_224.tflite为例(README 中给出的示例模型,下载地址见 工具 README),构建完成后直接运行:
bazel-bin/tensorflow/lite/tools/benchmark/benchmark_model \ --graph=mobilenet_quant_v1_224.tflite \ --num_threads=4 \ --num_runs=50 \ --report_peak_memory_footprint=true--graph是唯一必填参数。与本文测量目标相关的常用参数(完整列表见 工具 README):
| 参数 | 默认值 | 用途 |
|---|---|---|
graph | (必填) | TFLite 模型文件路径 |
num_threads | -1(平台默认) | 运行 TFLite 解释器使用的线程数 |
warmup_runs | 1 | 正式开始基准测试前的热身运行次数 |
num_runs | 50 | 正式基准测试的运行次数,调大可降低方差 |
max_secs | 150.0 | 基准测试最长运行秒数,超时后终止 |
report_peak_memory_footprint | false | 开启后周期性采样内存,输出峰值内存占用 |
memory_footprint_check_interval_ms | 50 | 峰值内存采样的间隔(毫秒),仅在开启上一项时生效 |
signature_to_run_for | "" | 模型含多个 signature 时指定要测试的 signature;不指定时会直接报错 |
enable_op_profiling | false | 开启算子级 profiling,见后文 |
注意:report_peak_memory_footprint会额外派生一个线程做周期性内存检查,README 明确说明这可能影响基准测试的时延结果,因此测内存时得到的时延数字与不开此项时不完全可比。
在 Android 设备上运行基准测试
把构建出的二进制和模型推送到设备后执行:
adb push bazel-bin/tensorflow/lite/tools/benchmark/benchmark_model /data/local/tmp adb shell chmod +x /data/local/tmp/benchmark_model adb push mobilenet_quant_v1_224.tflite /data/local/tmp adb shell /data/local/tmp/benchmark_model \ --graph=/data/local/tmp/mobilenet_quant_v1_224.tflite \ --num_threads=4文档提醒:直接在 Android 设备上 push 并执行二进制是可行做法,但与在真实 App 中执行相比可能存在细微(但可观察)的性能差异——Android 调度器会按线程和进程优先级调整行为,通过adb shell执行的普通后台二进制与前台 Activity 的优先级不同,启用多线程 CPU 执行时尤其明显。因此如果目标是精确评估 App 内表现,文档建议使用 Android benchmark app:安装 nightly 预构建 APK、adb push模型后用adb shell am start启动,再用adb logcat | grep "Inference timings"读取结果(步骤见 性能测量文档 的 “Android benchmark app” 一节)。
降低多次运行之间的方差(可选)。大多数现代 Android 手机采用 big.LITTLE 架构,不同运行结果之间方差可能较大。文档给出的做法是运行前用taskset设置 CPU affinity,例如在 Pixel 2 上用单线程跑 big core:
adb shell taskset f0 /data/local/tmp/benchmark_model \ --graph=/data/local/tmp/mobilenet_quant_v1_224.tflite \ --num_threads=1其中f0是 Pixel 2 上 big core 的 affinity mask,该值随设备不同而变化,需要按目标设备确定。
如何读取测量结果
时延指标。运行结束后工具输出一行(单位均为微秒),格式为:
Inference timings in us: Init: <初始化时间>, First inference: <首次推理>, Warmup (avg): <热身平均>, Inference (avg): <稳定状态平均>文档中给出的示例输出(示例结果,非固定预期值):
... tflite : Inference timings in us: Init: 5685, First inference: 18535, Warmup (avg): 14462.3, Inference (avg): 14575.2对应到标题中的两个目标:初始化时间看Init:字段,推理时延看Inference (avg):(稳定状态平均值);First inference和Warmup (avg)描述热身阶段,可与稳定状态对比判断冷启动开销。
内存指标。工具在结束时输出相对于工具启动时的内存增量(实现见 benchmark_model.cc):
Memory footprint delta from the start of the tool (MB): init=<初始化阶段> overall=<总体>文档明确提示:基准测试工具本身会占用内存,因此这个数字只是模型运行时实际内存占用的近似值,需自行斟酌采信。init=对应初始化阶段的内存占用,overall=对应总体内存占用。
开启--report_peak_memory_footprint=true后,还会额外输出通过周期性监测得到的峰值内存:
Overall peak memory footprint (MB) via periodic monitoring: <峰值>在 Linux 上还会附带输出结束时刻的内存状态(VmRSS、RssAnnon、RssFile + RssShmem)。
用算子级 profiling 定位慢算子(可选)
如果想知道时延花在了哪些算子上,在命令中加--enable_op_profiling=true,例如:
adb shell taskset f0 /data/local/tmp/benchmark_model \ --graph=/data/local/tmp/mobilenet_quant_v1_224.tflite \ --enable_op_profiling=true启用后工具会按算子输出执行时间统计,包括每个算子的[start]、[first]、[avg ms]、占比[cdf%]和[mem KB],以及 “Run Order”“Top by Computation Time”“Summary by node type” 三张表(工具 README 中给出了完整示例输出)。profiling_output_mode支持stdout(默认)、csv、proto三种输出格式,可用op_profiling_output_file指定导出文件。
限制与注意事项
- 内存数字是近似值:工具自身占用会叠加到测量中,文档原文即声明 “only APPROXIMATE to the actual memory footprint of the model at runtime”。
report_peak_memory_footprint的后台监测线程会引入额外开销,可能影响时延测量结果;测时延与测峰值内存时得到的数字不宜直接混用。- 部分 delegate 参数只在特定平台可用;在某个平台上运行
benchmark_model --help可打印该平台支持的全部参数。 - 工具必须编译为支持模型中所有 op 的 runtime,否则直接报错(TF ops 用
plus_flex目标,自定义算子需自行构建)。
【免费下载链接】tensorflowAn Open Source Machine Learning Framework for Everyone项目地址: https://gitcode.com/GitHub_Trending/te/tensorflow
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考