# ohos_model_benchmark **Repository Path**: ybf521/ohos_model_benchmark ## Basic Information - **Project Name**: ohos_model_benchmark - **Description**: ohos ohos_model_benchmark run test. - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-05-28 - **Last Updated**: 2026-07-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # AI Model Benchmark for HarmonyOS 跨推理框架的 AI 模型基准测试工具,可在 HarmonyOS 设备上对比 HIAI (CANN NPU)、MindSpore Lite、MNN、ONNXRuntime、NCNN、TFLite 六种推理后端的性能表现与输出精度。 ## 功能特性 - 支持六种推理后端:**HIAI (CANN NPU)**、**MindSpore Lite**、**MNN**、**ONNXRuntime (ORT)**、**NCNN**、**TFLite** - 支持 CPU / NPU 设备切换(HIAI 仅 NPU,MSLite 可选 CPU 或 NPU,其余后端仅 CPU) - 多轮基准测试(1~100 次),输出每个阶段的 min / avg / max 延时统计 - **设备端精度对比**:在推理过程中直接计算与 ONNXRuntime 参考输出的余弦相似度、RMSE、MAE、最大绝对误差,并自动标注质量等级(excellent / good / acceptable / poor) - **输出 Dump**:可将推理输出数据导出至设备文件,供离线分析 - **参考数据输入**:从 rawfile 目录按模型输入 Tensor 名称加载输入参考数据,找不到则用 0.5 常量填充 - **NCNN 双文件支持**:自动加载 `.ncnn.param` + `.ncnn.bin` 双文件,内部拼接为统一缓冲区 - 异步执行,运行时显示进度动画,不阻塞 UI - **AutoRun 批量测试**:一键运行 `models/` 下所有模型的基准测试(按后缀自动识别后端,HIAI 走 NPU、MSLite 同时跑 CPU 与 NPU、其余走 CPU),并将性能数据导出为 Excel 报表(基于 libxlsxwriter) - Python 精度对比工具:基于 ONNXRuntime 参考输出,支持 2-way 和 3-way 对比,生成 KDE / Scatter / Violin / Q-Q 图 ## 架构概览 ``` ┌──────────────────── ArkTS UI Layer ─────────────────────┐ │ Index.ets → 配置 (Backend / Device / Model / Runs) │ │ 开关 (Dump / AccuracyCMP) │ │ → RunFullBenchmarkAsync() via libentry.so NAPI │ └──────────────────────────┬──────────────────────────────┘ │ NAPI 桥接 ┌──────────────────────────▼──────────────────────────────┐ │ C++ Native Layer │ │ napi_init.cpp │ │ ├── RunFullBenchmarkAsync (异步, 多轮聚合) │ │ │ 参数: rawfile路径, ResourceManager, backend, │ │ │ enableNpu, enableDump, enableAccuracyCmp, │ │ │ runCount, callback │ │ └──────────→ ModelFactory::Create(config) │ │ └──────────→ BenchmarkTool::ComputeAccuracyMetrics() │ │ └──────────→ GetInputNames → 加载参考数据 │ └──────────────────────────┬──────────────────────────────┘ │ 工厂模式 ┌──────────┬──────────┼──────────┬──────────┬──────────┐ ▼ ▼ ▼ ▼ ▼ ▼ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ HIAI │ │ MSLite │ │ MNN │ │ ORT │ │ NCNN │ │TFLite │ │ (.om) │ │.ms/.mi │ │ (.mnn) │ │(.onnx) │ │.ncnn.* │ │.tflite │ │ NPU │ │CPU/NNRT│ │ CPU │ │ CPU │ │ CPU │ │ CPU │ │CANNKit │ │MSLite │ │MNN Lib │ │ORT Lib │ │NCNN Lib│ │TF Lite │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ All implement ModelManagerBase interface: LoadModelFromBuffer / LoadModelFromFile → FillInputData → RunModel → GetOutputData → UnloadModel / DumpModelOutput + GetInputCount / GetInputElementCounts / GetInputNames / GetOutputNames ``` > AutoRun 模式通过 `RunAutoBenchmarkAsync` 复用上述 `ExecuteBenchmark` 流程,对 `models/` 下所有模型批量执行并导出 Excel,详见下文 [AutoRun 批量测试与 Excel 导出](#autorun-批量测试与-excel-导出) 章节。 ## 支持的模型格式 | 后端 | 模型格式 | 设备 | |---------|-------------------------------|---------------| | HIAI | `.om` | NPU | | MSLite | `.ms` / `.mindir` | CPU / NPU (NNRT) | | MNN | `.mnn` | CPU | | ORT | `.onnx` | CPU | | NCNN | `.ncnn.param` + `.ncnn.bin` | CPU | | TFLite | `.tflite` | CPU | > **NCNN 注意**:NCNN 后端需要两个文件(`.ncnn.param` + `.ncnn.bin`),NAPI 层会自动拼接:8字节 header 存储 param 文件大小,后接 param 数据,再接 bin 数据,作为统一的缓冲区传入 `LoadModelFromBuffer`。 ## 基准测试阶段 每轮测试按以下顺序执行,分别计时: | 阶段 | 说明 | |---------------|------------------------------------| | LoadModel | 从 rawfile 加载模型数据到内存 | | InitTensors | 填充输入数据(参考数据或 0.5 常量) | | RunModel | 执行一次推理 | | GetResult | 获取输出数据 | | Unload | 释放模型资源 | | **Sum** | 上述阶段耗时总和 | ## 精度对比 ### 设备端精度对比 开启 **AccuracyCMP** 开关后,应用在最后一轮推理时: 1. 从 rawfile 的 `reference_data/` 目录加载 ONNXRuntime 参考输出 2. 调用 `BenchmarkTool::ComputeAccuracyMetrics()` 计算: - **余弦相似度** (Cosine Similarity) - **RMSE** (Root Mean Square Error) - **MAE** (Mean Absolute Error) - **最大绝对误差** (Max Absolute Error) 3. 自动标注质量等级:`excellent` (>0.99)、`good` (>0.95)、`acceptable` (>0.90)、`poor` (≤0.90) 4. 结果面板以颜色标签展示每个输出 Tensor 的精度指标 ### 输入数据来源 输入数据文件按模型输入 Tensor 名称命名,与输出参考数据共用 rawfile 的 `reference_data/` 目录(按 Tensor 名称区分)。文件命名规则: - 路径格式:`reference_data/.txt` - `sanitized_tensor_name` = 原始 Tensor 名称中所有非字母数字字符替换为 `_` 示例: - Tensor 名为 `x` → `reference_data/x.txt` - Tensor 名为 `input_images:0` → `reference_data/input_images_0.txt` - Tensor 名为 `data` → `reference_data/data.txt` 推理时自动根据模型输入 Tensor 名称查找对应文件: - 若找到匹配文件,加载其数据作为该输入 Tensor 的填充值 - 若未找到,使用 0.5 常量填充 ### 参考输出数据搜索 根据模型文件名自动搜索参考输出,支持去除量化后缀(`_quant`、`_fp16`、`_int8`、`_qat`、`_sym`)后的匹配。 搜索顺序: 1. 优先:`reference_data/_.txt` 2. 回退:`reference_data/.txt` ## AutoRun 批量测试与 Excel 导出 **AutoRun** 一键对 `rawfile/models/` 下所有模型执行基准测试,无需逐个手动选择后端与模型。 ### 工作流程 1. 点击 **AutoRun All Models** 按钮 2. Native 层扫描 `models/` 目录,按文件后缀自动识别后端(`.om→HIAI`、`.ms/.mindir→MSLite`、`.mnn→MNN`、`.onnx→ORT`、`.ncnn.param→NCNN`、`.tflite→TFLite`;`.ncnn.bin` 随 `.param` 自动加载) 3. 对每个模型复用单模型基准流程(`ExecuteBenchmark`),执行 `runCount` 轮推理,收集各阶段 min/avg/max 与精度 4. 设备选择:HIAI 仅跑 NPU,MSLite 同时跑 CPU 与 NPU(每个设备各产出一行结果),其余后端仅跑 CPU;**Dump / AccuracyCMP 跟随界面当前开关状态** 5. 全部完成后,通过 `tools/excel_writer`(基于 libxlsxwriter)将结果写入 Excel 报表 ### Excel 报表 - 输出路径:`<应用沙箱 filesDir>/benchmark_.xlsx`(界面结果栏显示完整路径) - 每个模型一行,列含义: | 列 | 说明 | |----|------| | Backend / Model / RunCount / Device | 后端、模型文件名、运行轮数、设备(NPU/CPU) | | LoadModel / InitTensors / RunModel / GetResult / Unload / Sum 各 min/avg/max (ms) | 六阶段延时统计 | | Status / Error | OK / FAIL 与失败原因 | | AvgCosine / WorstQuality / AccuracyDetails | 精度汇总(仅 AccuracyCMP 开启时填充) | | InputShapes / OutputShapes | 各输入/输出 Tensor 的 shape(如 `[1,3,224,224]`,多 Tensor 以 `;` 分隔) | > libxlsxwriter 默认用系统临时目录组装 xlsx,OHOS 沙箱下 `/tmp` 可能不可写,因此 `tools/excel_writer.cpp` 通过 `workbook_new_opt` 将 `tmpdir` 设为输出目录。 > > **构建注意**:`libxlsxwriter.a` 为静态库,链入 `entry.so`(动态库)时需为 arm64-v8a + `-fPIC` 编译;`libz.so.1` 为其动态依赖,由 `libs/arm64-v8a/zlib/` 提供并随 hap 打包。 ## 配置参数 (ModelConfig) | 字段 | 类型 | 默认值 | 说明 | |--------------------|---------|------------------------------|------------------------| | `backend_type` | enum | HIAI | 推理后端类型 | | `enable_npu` | bool | false | 是否启用 NPU | | `enable_dump_output` | bool | false | 是否导出推理输出 | | `enable_accuracy_cmp` | bool | false | 是否启用精度对比 | | `enable_fp16` | bool | false | 是否启用 FP16 推理 | | `thread_num` | int32 | 1 | 推理线程数 | | `enable_npu_cache` | bool | false | 是否启用 NPU 模型缓存 | | `cache_dir` | string | `/data/storage/el2/base/cache/` | 缓存目录路径 | | `cache_version` | string | `"1"` | 缓存版本号 | | `cache_model_tag` | string | `"model_tag"` | 缓存模型标签 | | `band_mode` | string | `"normal"` | 执行模式 | | `execute_device` | string | `"npu"` | 执行设备 | | `mnn_forward_type` | int32 | 0 | MNN 前向计算类型 | ## 环境要求 - **DevEco Studio** (HarmonyOS 开发 IDE) - **HarmonyOS SDK**: API 6.0.0(20) - **BiSheng 编译器**: 用于 C++ 原生层编译 - **目标设备**: HarmonyOS 手机/平板 (arm64-v8a) - **Python 3.x** (仅精度对比脚本需要) ## 构建与运行 ### 1. 构建项目 1. 用 DevEco Studio 打开本项目 2. Hvigor 构建系统将自动完成: - 编译 ArkTS UI 代码 - 通过 CMake + BiSheng 编译器构建 C++ 原始层(C++17 标准,`c++_static` STL) - 链接 MNN、MindSpore Lite NDK、CANN/HiAI、ONNXRuntime、NCNN、OpenMP、TFLite、libxlsxwriter、zlib 等预置库 - 打包 rawfile 中的模型资源与参考数据 - 使用 `build-profile.json5` 中的签名配置签名 3. 构建产物为 `.hap` (HarmonyOS Ability Package) > **TFLite 构建注意**:CMakeLists.txt 中需要 `--allow-multiple-definition`(解决 TFLite 静态库重复符号)和 `--start-group/--end-group`(解决 TFLite 静态库循环依赖)。 ### 2. 运行测试 1. 将 `.hap` 部署到 HarmonyOS 设备或模拟器 2. 应用自动扫描 `rawfile` 的 `models/` 目录,按所选后端的模型后缀名过滤模型文件 3. 选择:**后端** → **设备** → **模型文件** → **运行次数** (1~100) 4. 可选开启:**Dump**(导出输出)、**AccuracyCMP**(精度对比) 5. 点击 **Run Benchmark**,异步 NAPI 调用在后台线程执行多轮推理 6. 结果面板显示每个阶段的 min / avg / max 延时 (ms) 7. 若开启 AccuracyCMP,精度面板显示各输出 Tensor 的余弦相似度等指标与质量标签 8. 也可点击 **AutoRun All Models**,一键对 `models/` 下所有模型依次跑基准测试(Dump / AccuracyCMP 跟随当前开关;HIAI 走 NPU、MSLite 同时跑 CPU 与 NPU、其余走 CPU) 9. AutoRun 完成后,性能数据导出为 Excel 报表 `<应用沙箱 filesDir>/benchmark_<时间戳>.xlsx`,界面显示路径与各模型各设备 `Sum` 平均耗时汇总 ### 3. 精度对比(Python 脚本) ```bash # 生成 ONNXRuntime 参考输出(按 Tensor 名称加载输入数据) python python/scripts/benchmark_file_input.py --model model.onnx --input_dir ./input_data --output_dir ./output_data # 生成随机 float32 输入数据(可自定义 shape 和输出文件名) python python/scripts/gen_input.py # 2-way 精度对比(验证目录) python python/valid/torch_ohos_accuracy_cmp.py # 3-way 精度对比(如 NPU vs NPU-量化 vs ONNXRuntime) python python/scripts/torch_ohos_accuracy_cmp3.py ``` Python 精度对比脚本输出余弦相似度矩阵、RMSE、MAE、最大绝对误差,并生成 KDE / Scatter / Violin / Q-Q / Bland-Altman 图。 ## 项目结构 ``` ohos_model_benchmark/ ├── entry/ │ ├── src/main/ │ │ ├── ets/ │ │ │ ├── pages/Index.ets # 主界面 (配置/运行/结果/精度展示) │ │ │ ├── entryability/EntryAbility.ets # 应用生命周期 │ │ │ ├── entrybackupability/EntryBackupAbility.ets # 数据备份扩展 │ │ │ └── utils/FileUtils.ets # 文件读写工具 │ │ ├── cpp/ │ │ │ ├── napi_init.cpp # NAPI 桥接 (异步接口 + NCNN双文件拼接) │ │ │ ├── engine/ │ │ │ │ ├── model_manager_base.h # 抽象接口 + ModelConfig + BackendType │ │ │ │ ├── model_factory.h # 工厂模式创建后端实例 │ │ │ │ └── backend/ │ │ │ │ ├── cann/ # HIAI/CANN NPU 后端 │ │ │ │ ├── mslite/ # MindSpore Lite 后端 │ │ │ │ ├── mnn/ # MNN 后端 │ │ │ │ ├── ort/ # ONNXRuntime 后端 │ │ │ │ ├── ncnn/ # NCNN 后端 │ │ │ │ └── tflite/ # TFLite 后端 (+ tflite_compat.cpp) │ │ │ ├── tools/ │ │ │ │ ├── benchmark_tool.h # AccuracyResult + 精度计算/数据加载工具 │ │ │ │ ├── benchmark_tool.cpp # ComputeAccuracyMetrics / LoadDataFromBuffer 等实现 │ │ │ │ ├── excel_writer.h # Excel 报表数据结构 + 写表接口 │ │ │ │ └── excel_writer.cpp # 基于 libxlsxwriter 写性能/精度报表 │ │ │ ├── third_party/ # 第三方头文件 (mnn/ort/ncnn/openmp/tensorflow/flatbuffers/libxlswriter) │ │ │ └── CMakeLists.txt # C++17 + c++_static + TFLite链接特殊处理 │ │ ├── resources/rawfile/ │ │ │ ├── models/ # 所有后端模型统一存放,按后缀名区分后端 │ │ │ │ ├── *.om # HIAI 模型 │ │ │ │ ├── *.ms # MSLite 模型 │ │ │ │ ├── *.mnn # MNN 模型 │ │ │ │ ├── *.onnx # ORT 模型 │ │ │ │ ├── *.ncnn.param + *.ncnn.bin # NCNN 模型 (双文件) │ │ │ │ └── *.tflite # TFLite 模型 │ │ │ └── reference_data/.txt # 输入/输出参考数据 (按Tensor名称区分) │ │ └── module.json5 │ ├── libs/arm64-v8a/ │ │ ├── mnn/ # MNN 预置库 (libMNN.so, libMNN_Express.so) │ │ ├── ort/ # ONNXRuntime 预置库 (libonnxruntime.so.1) │ │ ├── ncnn/ # NCNN 预置库 (libncnnd.so.1) │ │ ├── openmp/ # OpenMP 预置库 (libomp.so) │ │ ├── tflite/ # TFLite 静态库 (~110 .a files) │ │ ├── xlsxwriter/ # libxlsxwriter 静态库 (libxlsxwriter.a) │ │ └── zlib/ # zlib 动态库 (libz.so.1, libxlsxwriter 依赖) │ ├── oh-package.json5 │ └── build-profile.json5 ├── python/ │ ├── scripts/ │ │ ├── benchmark_file_input.py # ONNXRuntime 参考输出 (按Tensor名称加载输入) │ │ ├── gen_input.py # 生成随机 float32 输入数据 │ │ └── torch_ohos_accuracy_cmp3.py # 3-way 精度对比 │ └── valid/ │ ├── torch_ohos_accuracy_cmp.py # 2-way 精度对比 │ └── feature.txt # 验证参考数据 ├── build-profile.json5 ├── hvigorfile.ts └── hvigor/ ``` ## 依赖说明 ### 原生 C++ 依赖 | 库 | 用途 | |-------------------------|-------------------------------| | `libace_napi.z.so` | C++ 与 ArkTS 桥接 (NAPI) | | `libhilog_ndk.z.so` | HarmonyOS 日志 | | `mindspore_lite_ndk.so` | MindSpore Lite 推理 SDK | | `librawfile.z.so` | 读取 rawfile 资源 | | `hiai_foundation` | HiAI / CANN 基础库 | | `libneural_network_core.so` | 神经网络运行时核心 | | `libMNN.so` + `libMNN_Express.so` | MNN 推理库 (预置) | | `libonnxruntime.so.1` | ONNXRuntime 推理库 (预置) | | `libncnnd.so.1` | NCNN 推理库 (预置) | | `libomp.so` | OpenMP 线程库 (预置) | | `libtensorflow-lite.a` + 依赖 | TFLite 推理 (静态链接, 预置) | | `libxlsxwriter.a` | Excel 报表生成 (静态链接, 预置) | | `libz.so.1` | zlib 压缩库, libxlsxwriter 依赖 (预置) | ### ArkTS 依赖 | 包 | 用途 | |------------------------|--------------------| | `@kit.AbilityKit` | UIAbility / ResourceManager | | `@kit.PerformanceAnalysisKit` | Hilog | | `@kit.ArkUI` | 窗口管理 | | `@kit.CoreFileKit` | 文件 I/O / 备份扩展 | ## 许可证 Apache License 2.0