maximum_timeflow_3.0_release 全量跑分测试报告

举报
袁睿 发表于 2026/09/26 18:24:32 2026/09/26
【摘要】 maximum_timeflow_3.0_release 全量跑分测试报告

maximum_timeflow_3.0_release 全量跑分测试报告

一、项目概述

项目 信息
项目仓库 https://atomgit.com/Harmony_timeflow/maximum_timeflow.git
分支 main
提交(HEAD) 45fdd1c
完整哈希 45fdd1caa17fbb99395ccfe2e0aae94949c8e2ac
提交时间 2026-09-21 20:41:47 +0800
提交说明 !56 merge main into main
项目版本 0.1.0
被测模型 异常检测模型 128->32->16->1(3 层全连接),已 Ed25519 签名的 .htf 格式

二、跑分环境

项目 信息
操作系统 WSL2 Ubuntu 24.04 LTS(内核 5.15.167.4-microsoft-standard-WSL2)
宿主系统 Windows 11 Pro 10.0.26200
处理器 12th Gen Intel Core i9-12900K(24 逻辑核)
内存 物理 63.8 GB,WSL2 上限 50 GB(实测可用 49Gi)
架构 x86_64
编译器 gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
构建工具 cmake 3.28.3 + ninja 1.11.1
构建类型 Release,优化级别 -O3
内核路径 avx2+fma
链接依赖 OpenSSL 3.0.13 / zlib 1.3 / libjpeg-turbo 2.1.5 / libm
分配审计 -Wl,–wrap=malloc/calloc/realloc/free(GNU ld 2.42,已验证接通)
单项迭代数 2000(项目默认值)
跑分时间 2026-09-21T13:02:35Z
单调时钟 可用
构建结果 0 警告 0 错误,28 个翻译单元

三、跑分总体结论

程序 结果 判定依据 退出码
htf_bench_inference(宿主端) PASS 0 failure(s); all measured cases validated 0
htf_bench_constrained(受限端) PASS 0 failure(s); correctness verified, zero-allocation confirmed 0

说明: 本项目的跑分程序不只是计时,还会校验测量结果——被测值与参考值不符、或分配审计在声称"零分配"的路径上发现分配,程序即退出非 0。两个程序均返回 0,且判定为 pass,即所有被测项均通过校验。

重要限定(工件中 device_figure=false): 本次跑分在 x86_64 宿主机上执行,所有时延数字均标注为 host-only,仅描述本机,不代表 riscv32 MCU 设备性能。项目自身明确禁止任何跨架构换算,本次也未做任何换算或外推。内存占用与分配次数为 portable(可移植),在任何目标上都成立。

四、htf_bench_inference 跑分明细(宿主端,2000 次迭代/项)

4.1 FP32 全连接层 GEMV(htf_dense_f32,激活=RELU)

内核路径: avx2+fma

层形状 min(ns) mean(ns) p50(ns) p95(ns) max(ns) n ops/sec
128x32 280 311.8 295.0 398.0 1049 2000 3207354
32x16 51 55.9 53.0 54.0 5875 2000 17873580
16x1 24 25.0 25.0 26.0 34 2000 40072933
1x1 18 19.3 19.0 20.0 38 2000 51912994
7x3 26 28.2 28.0 29.0 41 2000 35467910
64x64 222 239.8 226.0 246.0 9504 2000 4170385
255x129 2551 2762.4 2702.0 2940.0 26938 2000 362010

数据特征(源自工件原始数据,如实记录):

  • 32x16: max=5875 ns 为极端离群值,把 mean(55.9) 拉到 p95(54) 之上。这是工件里的真实数据,图表中该点误差棒下界按 0 处理并已标注。
  • 64x64: max=9504 ns 达 p95(246) 的 39 倍(首次调用/调度抖动所致),中位数与 p95 未受影响,稳态性能可信。

4.2 标量 vs 向量路径对比(形状 255x129)

路径 min mean p50 p95 ops/sec
强制标量 scalar 10956 11115.3 11021.0 11191.0 89966
分发 avx2+fma 2599 2791.8 2712.0 3227.0 358195
向量加速比 3.98x

限定: 该加速比仅对本机 AVX2+FMA 核心有效;riscv32 目标无此路径,走标量代码。

4.3 INT8 定点 vs FP32 浮点(同一逻辑层 128x32)

表示 min mean p50 p95 ops/sec
INT8 定点 int8_dense_act 379 385.8 384.0 387.0 2592060
FP32 浮点 dense_f32 293 306.7 300.0 322.0 3260441
时间比 mean(fp32)/mean(int8) 0.80x

可移植部分(字节数,与本机无关,任何目标都成立):

  • 真实模型权重: 4624 B int8 vs 18496 B fp32
  • INT8 节省: 13872 B saved (4.0x smaller)

说明: 本机 INT8 反而比 FP32 慢(比值 < 1),因为 AVX2+FMA 的 FP32 路径在该 CPU 上已高度优化;INT8 的真正收益在于 Flash 占用减少 4 倍、以及无需 FPU——这正是无浮点单元 MCU 上的决定性优势。

4.4 端到端引擎 htf_engine_run(已签名 .htf 模型,STRICT 验签)

引擎配置: native fp32 avx2+fma layers=3 in=128 out=1 arena=1152B

模型形状: in=128 out=1 layers=3

量化参数: in scale=0.0409732 zp=-6, out scale=0.00194258 zp=-128

路径 min mean p50 p95 ops/sec
FP32 engine_run (3 layers, avx2+fma) 339 398.1 352.0 444.0 2512023
INT8 engine_run (in=128 out=1, packed int8) 495 502.5 502.0 507.0 1990040

推理期堆分配(经 --wrap 精确计数):

  • FP32: 0 over 2000 runs
  • INT8: 0 over 2000 runs
  • FP32 申请字节: 0 B requested

内存占用(可移植):

  • arena 已分配: 1152 B
  • 占 128 KB 预算: 1152 B = 1.1 KB of a 128 KB budget

4.5 受限平台适配性(可移植数字,非本机时延)

  • arena 落在 128 KB 预算内: 1152 B of 131072 B budget (0.88%)
  • 64 字节 arena 上限: refused at load (ok)
  • INT8 模型加载: quantised=1, arena=1152 B
  • LiteOS-M 子系统静态足迹: ROM 22.3 KB(其中 18.8 KB 为权重表),静态 RAM 约 1 KB + 2 KB 任务栈

4.6 分配审计自检

通过(计数通路已验证接通)

含义:审计在报告任何"零"之前先自检,证明计数钩子真的生效,因此"零分配"是实测结果,而非"没测到"伪装成的零。

五、htf_bench_constrained 跑分明细(受限端,2000 次迭代)

链接范围: 仅 platform/liteos_m 的 3 个翻译单元:htf_ai_lite.c / htf_ai_model.c / float_weights_output.c。不链接 OpenSSL、不链接宿主引擎、无文件 I/O(权重编译期内置)——即真正随固件出货到设备的那部分代码。

5.1 模型几何

项目 详情
模型 3 layers, in=128 out=1
第 0 层 128x32 w=0x55911f3306e0 b=yes
第 1 层 32x16 w=0x55911f334760 b=yes
第 2 层 16x1 w=0x55911f334fa0 b=yes
静态缓冲校验 widest=128, static buffer=128 (fits)
权重表(Flash) 4624 weights = 18496 B fp32
推理暂存 RAM 1024 B = 1.0 KB (2 x 128 floats)

5.2 数值正确性

测试项 结果
异常概率 got 0.471768856, numpy golden 0.471768826, diff 2.98e-08 (tol 0.001)
softmax 常量回归检查 not triggered
黄金值来源 tools/gen_liteos_golden.py 用 numpy 独立算出,与被测 C 代码无共享实现,故 C 的缺陷无法自我验证

5.3 堆分配审计(整生命周期,经 --wrap 精确计数)

测量项 详情 值
审计自检 counting path verified passed
堆分配次数 whole lifecycle 0 malloc, 0 calloc, 0 realloc over init+2000 runs+deinit
申请堆字节 whole lifecycle 0 B
释放次数 whole lifecycle 0
判定 allocation-free inference CONFIRMED by measurement

意义: init + 2000 次推理 + deinit 全程零堆分配,核心改用 2 块静态 BSS 缓冲。这决定了"128 KB 设备能否跑"——没有第 N 次调用因堆碎片而失败的风险。

5.4 推理时延(本机,非设备数字)

项目 详情
运行于 host (NOT a device figure)
测量项 min mean p50 p95 max ops/sec
完整前向传播 128->1 (3 layers) 1561 1599.1 1575.0 1676.0 9562 625363
  • 单次推理时延: 1.599 us mean, 1.676 us p95
  • device_figure: False(工件字段,编译期决定,不可用命令行伪造)

六、正确性与内存安全验证(配套测试套件,26 项全通过)

跑分程序自身会校验测量结果;此外还完整运行了项目的测试套件:

6.1 分组 A:单元测试 (unit) — 12 项全部 Passed

  • test_cpu_features
  • test_version
  • test_status
  • test_format
  • test_arena
  • test_kernels
  • test_kernels_int8
  • test_crypto
  • test_model_loader
  • test_engine
  • test_liteos_real_model
  • test_transformer

6.2 分组 B:黄金值测试 (golden) — 4 项全部 Passed

对 numpy 独立参考实现校验,覆盖引擎、模型加载器、LiteOS-M 真实模型、Transformer

6.3 分组 C:跑分冒烟 (benchmark) — 2 项全部 Passed

  • bench_constrained_smoke
  • bench_inference_smoke

6.4 分组 D:valgrind 内存检查 — 12 项全部 Passed(0 泄漏 0 非法访问)

  • –leak-check=full --errors-for-leak-kinds=definite --track-origins=yes
  • –error-exitcode=1,即发现泄漏会使测试变红而非静默通过

6.5 合计

ctest 26/26 通过,100% tests passed, 0 tests failed

七、交付内容清单

7.1 图表(7 张 PNG)

全部由 JSON 工件解析数据生成:

  • 图1_FP32全连接层_各形状时延与吞吐.png — 7 种层形状的 min/mean/p95 与吞吐
  • 图2_标量与AVX2向量路径对比.png — 加速比可视化
  • 图3_INT8与FP32对比.png — 时延对比 + Flash 字节对比
  • 图4_端到端引擎_FP32与INT8.png — 引擎时延 + 可移植数字表
  • 图5_受限端完整前向传播时延分布.png — min/mean/p50/p95/max 分布
  • 图6_可移植内存足迹与零分配结论.png — 内存足迹对数图 + 零分配判定
  • 图7_数值正确性校验.png — 实测 vs numpy 黄金值

7.2 HTML 报告(2 份自包含报告)

CSS 与图表全内联,离线可看:

  • 跑分报告_交互图表_plotly.html — 交互式,可悬停查看数值(约 16 MB)
  • 跑分报告_轻量版_svg.html — 纯 SVG 零依赖,约 35 KB,便于分享

两份均由项目自带的 benchmark/report/report.py 渲染,含诚实性徽标:

  • portable: 74 处
  • host-only: 18 处
  • device-measured: 0 处

并在 <head> 写入 provenance meta 标签:

  • htf-bench-commits = 45fdd1c
  • htf-bench-device-figures = false

7.3 数据/JSON 工件(唯一事实来源,报告与图表都由它生成)

  • 20260921-x86_64-inference-2000.bench.json — 37 条记录(13 timing/16 metric/8 note)
  • 20260921-x86_64-constrained-2000.bench.json — 20 条记录(1 timing/17 metric/2 note)

格式 htf-bench/1,命名遵循项目 benchmark/results/README.md 规范

7.4 数据/CSV(机器可读,12 列固定格式)

  • inference.csv — 38 行
  • constrained.csv — 24 行

列:kind, section, metric, detail, value, min_ns, mean_ns, p50_ns, p95_ns, max_ns, n, ops_per_sec

7.5 数据/文本输出(跑分程序 stdout 原文,便于逐项核对)

  • htf_bench_inference_完整输出.txt
  • htf_bench_constrained_完整输出.txt

八、复现方法

环境: WSL2 Ubuntu 24.04 LTS(本次新装,已配 50 GB 内存上限)

依赖: build-essential cmake ninja-build pkg-config libssl-dev zlib1g-dev libjpeg-dev python3-numpy python3-matplotlib python3-plotly valgrind

git clone https://atomgit.com/Harmony_timeflow/maximum_timeflow.git
cd maximum_timeflow
cmake -G Ninja -S . -B build -DCMAKE_BUILD_TYPE=Release \
      -DHTF_ENABLE_OPENSSL=ON -DHTF_BUILD_BENCHMARKS=ON -DHTF_BUILD_TESTS=ON
ninja -C build htf_fixtures htf_bench_inference htf_bench_constrained
ninja -C build

./build/benchmark/htf_bench_inference --iters 2000 \
    --model-fp32 build/tests/fixtures/real_model_fp32.htf \
    --model-int8 build/tests/fixtures/real_model_int8.htf \
    --json 结果目录/日期-x86_64-inference-2000.bench.json
./build/benchmark/htf_bench_constrained --iters 2000 \
    --json 结果目录/日期-x86_64-constrained-2000.bench.json
python3 benchmark/report/report.py 结果目录/*.bench.json -o 报告.html
ctest --test-dir build --output-on-failure -j$(nproc)

注意: Windows 原生(MSVC)无法构建本项目,跑分程序硬依赖 GNU ld 的 -Wl,–wrap=malloc 实现分配审计,且测试框架用到 GCC/Clang 的 attribute((constructor))。必须用 GCC/Clang 工具链。

九、诚实性声明

  • 所有数字均为本机实测,来自跑分程序 --json 产出的原始工件,未经手工编辑。
  • 未做任何跨机器归一化、换算或外推;宿主机时延一律标注 host-only。
  • device_figure=false:本次未在 riscv32 设备上实测,因此不提供任何"设备时延"。编造一个 MCU 数字是不诚实的——项目文档明确要求如此,本次严格遵守。
  • 内存占用、Flash 字节数、堆分配次数为 portable 结论,在任何目标上都成立。
  • 时延数字会随机器、温度、后台负载波动;同一份代码重跑数值会略有差异,但零分配、正确性校验、内存预算这类结论是确定性的,不随重跑变化。

十、JSON 工件完整数据

10.1 htf_bench_constrained JSON 工件(20260921-x86_64-constrained-2000.bench.json)

{
  "format": "htf-bench/1",
  "env": {
    "program": "htf_bench_constrained",
    "iterations": 2000,
    "clock_available": true,
    "device_figure": false,
    "kernel_path": "n/a (LiteOS-M core, no runtime dispatch)",
    "arch": "x86_64",
    "model_fp32": null,
    "model_int8": null,
    "version": "0.1.0",
    "git_hash": "45fdd1c",
    "timestamp_utc": "2026-09-21T13:02:36Z"
  },
  "entries": [
    {"kind": "metric", "section": "Constrained target: model geometry (LiteOS-M core)", "metric": "model", "detail": "built-in weights, no file I/O", "value": "3 layers, in=128 out=1"},
    {"kind": "metric", "section": "Constrained target: model geometry (LiteOS-M core)", "metric": "layer 0", "detail": "shape / operands present", "value": "128x32 w=0x55911f3306e0 b=yes"},
    {"kind": "metric", "section": "Constrained target: model geometry (LiteOS-M core)", "metric": "layer 1", "detail": "shape / operands present", "value": "32x16 w=0x55911f334760 b=yes"},
    {"kind": "metric", "section": "Constrained target: model geometry (LiteOS-M core)", "metric": "layer 2", "detail": "shape / operands present", "value": "16x1 w=0x55911f334fa0 b=yes"},
    {"kind": "metric", "section": "Constrained target: model geometry (LiteOS-M core)", "metric": "static buffer sizing", "detail": "ping-pong scratch", "value": "widest=128, static buffer=128 (fits)"},
    {"kind": "metric", "section": "Constrained target: model geometry (LiteOS-M core)", "metric": "weight table", "detail": "in flash (.rodata)", "value": "4624 weights = 18496 B fp32"},
    {"kind": "metric", "section": "Constrained target: model geometry (LiteOS-M core)", "metric": "inference scratch RAM", "detail": "static BSS, allocated once at link time", "value": "1024 B = 1.0 KB (2 x 128 floats)"},
    {"kind": "metric", "section": "Constrained target: numerical correctness", "metric": "anomaly probability", "detail": "recorded input vector", "value": "got 0.471768856, numpy golden 0.471768826, diff 2.98e-08 (tol 0.001)"},
    {"kind": "metric", "section": "Constrained target: numerical correctness", "metric": "softmax-constant regression", "detail": "output must not be 1.0", "value": "not triggered"},
    {"kind": "metric", "section": "Constrained target: heap allocation audit", "metric": "audit self-test", "detail": "counting path verified", "value": "passed"},
    {"kind": "metric", "section": "Constrained target: heap allocation audit", "metric": "heap allocations", "detail": "whole lifecycle", "value": "0 malloc, 0 calloc, 0 realloc over init+2000 runs+deinit"},
    {"kind": "metric", "section": "Constrained target: heap allocation audit", "metric": "heap bytes requested", "detail": "whole lifecycle", "value": "0 B"},
    {"kind": "metric", "section": "Constrained target: heap allocation audit", "metric": "heap frees", "detail": "whole lifecycle", "value": "0"},
    {"kind": "metric", "section": "Constrained target: heap allocation audit", "metric": "VERDICT", "detail": "allocation-free inference", "value": "CONFIRMED by measurement"},
    {"kind": "note", "section": "Constrained target: heap allocation audit", "text": "zero heap allocations across init, 2000 inferences and deinit. The core uses 2 static BSS buffers instead. This is what makes the run path safe on a device whose heap cannot be relied on: there is no allocation to fail on the Nth call, and no fragmentation to accumulate over a device's uptime."},
    {"kind": "metric", "section": "Constrained target: inference timing (THIS machine)", "metric": "running on", "detail": "architecture", "value": "host (NOT a device figure)"},
    {"kind": "note", "section": "Constrained target: inference timing (THIS machine)", "text": "these timings describe this host. They are not a prediction of MCU latency and must not be quoted as one. Cross-compile this file for the target and run it there for real device numbers."},
    {"kind": "timing", "section": "Constrained target: inference timing (THIS machine)", "metric": "full forward pass", "detail": "128->1, 3 layers", "min_ns": 1561.0, "mean_ns": 1599.1, "p50_ns": 1575.0, "p95_ns": 1676.0, "max_ns": 9562.0, "n": 2000, "ops_per_sec": 625363.10},
    {"kind": "metric", "section": "Constrained target: inference timing (THIS machine)", "metric": "per-inference latency", "detail": "this machine", "value": "1.599 us mean, 1.676 us p95"},
    {"kind": "metric", "section": "Run verdict", "metric": "BENCH RESULT", "detail": "pass", "value": "0 failure(s); correctness verified, zero-allocation confirmed"}
  ]
}

10.2 htf_bench_inference JSON 工件(20260921-x86_64-inference-2000.bench.json)

{
  "format": "htf-bench/1",
  "env": {
    "program": "htf_bench_inference",
    "iterations": 2000,
    "clock_available": true,
    "device_figure": false,
    "kernel_path": "avx2+fma",
    "arch": "x86_64",
    "model_fp32": "build/tests/fixtures/real_model_fp32.htf",
    "model_int8": "build/tests/fixtures/real_model_int8.htf",
    "version": "0.1.0",
    "git_hash": "45fdd1c",
    "timestamp_utc": "2026-09-21T13:02:35Z"
  },
  "entries": [
    {"kind": "note", "section": "FP32 dense GEMV (htf_dense_f32), activation=RELU", "text": "kernel path in this process: avx2+fma"},
    {"kind": "timing", "section": "FP32 dense GEMV (htf_dense_f32), activation=RELU", "metric": "dense_f32 relu", "detail": "128x32 avx2+fma", "min_ns": 280.0, "mean_ns": 311.8, "p50_ns": 295.0, "p95_ns": 398.0, "max_ns": 1049.0, "n": 2000, "ops_per_sec": 3207353.82},
    {"kind": "timing", "section": "FP32 dense GEMV (htf_dense_f32), activation=RELU", "metric": "dense_f32 relu", "detail": "32x16 avx2+fma", "min_ns": 51.0, "mean_ns": 55.9, "p50_ns": 53.0, "p95_ns": 54.0, "max_ns": 5875.0, "n": 2000, "ops_per_sec": 17873580.17},
    {"kind": "timing", "section": "FP32 dense GEMV (htf_dense_f32), activation=RELU", "metric": "dense_f32 relu", "detail": "16x1 avx2+fma", "min_ns": 24.0, "mean_ns": 25.0, "p50_ns": 25.0, "p95_ns": 26.0, "max_ns": 34.0, "n": 2000, "ops_per_sec": 40072932.74},
    {"kind": "timing", "section": "FP32 dense GEMV (htf_dense_f32), activation=RELU", "metric": "dense_f32 relu", "detail": "1x1 avx2+fma", "min_ns": 18.0, "mean_ns": 19.3, "p50_ns": 19.0, "p95_ns": 20.0, "max_ns": 38.0, "n": 2000, "ops_per_sec": 51912993.82},
    {"kind": "timing", "section": "FP32 dense GEMV (htf_dense_f32), activation=RELU", "metric": "dense_f32 relu", "detail": "7x3 avx2+fma", "min_ns": 26.0, "mean_ns": 28.2, "p50_ns": 28.0, "p95_ns": 29.0, "max_ns": 41.0, "n": 2000, "ops_per_sec": 35467910.41},
    {"kind": "timing", "section": "FP32 dense GEMV (htf_dense_f32), activation=RELU", "metric": "dense_f32 relu", "detail": "64x64 avx2+fma", "min_ns": 222.0, "mean_ns": 239.8, "p50_ns": 226.0, "p95_ns": 246.0, "max_ns": 9504.0, "n": 2000, "ops_per_sec": 4170385.26},
    {"kind": "timing", "section": "FP32 dense GEMV (htf_dense_f32), activation=RELU", "metric": "dense_f32 relu", "detail": "255x129 avx2+fma", "min_ns": 2551.0, "mean_ns": 2762.4, "p50_ns": 2702.0, "p95_ns": 2940.0, "max_ns": 26938.0, "n": 2000, "ops_per_sec": 362010.41},
    {"kind": "timing", "section": "Scalar vs vector path, same shape", "metric": "dense_f32 (forced scalar)", "detail": "255x129 scalar", "min_ns": 10956.0, "mean_ns": 11115.3, "p50_ns": 11021.0, "p95_ns": 11191.0, "max_ns": 31353.0, "n": 2000, "ops_per_sec": 89965.69},
    {"kind": "timing", "section": "Scalar vs vector path, same shape", "metric": "dense_f32 (dispatched)", "detail": "255x129 avx2+fma", "min_ns": 2599.0, "mean_ns": 2791.8, "p50_ns": 2712.0, "p95_ns": 3227.0, "max_ns": 16521.0, "n": 2000, "ops_per_sec": 358194.61},
    {"kind": "metric", "section": "Scalar vs vector path, same shape", "metric": "vector speedup", "detail": "mean(scalar)/mean(vector)", "value": "3.98x"},
    {"kind": "note", "section": "Scalar vs vector path, same shape", "text": "speedup is specific to THIS machine's AVX2+FMA core; a riscv32 target has no such path and runs the scalar code."},
    {"kind": "timing", "section": "INT8 packed vs FP32, same logical layer", "metric": "int8_dense_act", "detail": "128x32 int8 relu", "min_ns": 379.0, "mean_ns": 385.8, "p50_ns": 384.0, "p95_ns": 387.0, "max_ns": 630.0, "n": 2000, "ops_per_sec": 2592060.26},
    {"kind": "timing", "section": "INT8 packed vs FP32, same logical layer", "metric": "dense_f32", "detail": "128x32 fp32 relu", "min_ns": 293.0, "mean_ns": 306.7, "p50_ns": 300.0, "p95_ns": 322.0, "max_ns": 5499.0, "n": 2000, "ops_per_sec": 3260440.75},
    {"kind": "metric", "section": "INT8 packed vs FP32, same logical layer", "metric": "int8 vs fp32 time", "detail": "mean(fp32)/mean(int8), this host", "value": "0.80x"},
    {"kind": "metric", "section": "INT8 packed vs FP32, same logical layer", "metric": "real model weights", "detail": "128->32->16->1, per layer summed", "value": "4624 B int8 vs 18496 B fp32"},
    {"kind": "metric", "section": "INT8 packed vs FP32, same logical layer", "metric": "flash saved by INT8", "detail": "same model, weights only", "value": "13872 B saved (4.0x smaller)"},
    {"kind": "note", "section": "INT8 packed vs FP32, same logical layer", "text": "byte figures are properties of the representation and hold on any target; the time ratio above is specific to this host."},
    {"kind": "metric", "section": "End-to-end engine on the real model (FP32 path)", "metric": "engine", "detail": "active configuration", "value": "native fp32 avx2+fma layers=3 in=128 out=1 arena=1152B"},
    {"kind": "metric", "section": "End-to-end engine on the real model (FP32 path)", "metric": "model shape", "detail": "signed .htf", "value": "in=128 out=1 layers=3"},
    {"kind": "metric", "section": "End-to-end engine on the real model (FP32 path)", "metric": "heap allocations during inference", "detail": "malloc+calloc+realloc", "value": "0 over 2000 runs"},
    {"kind": "metric", "section": "End-to-end engine on the real model (FP32 path)", "metric": "heap bytes during inference", "detail": "sum of requested sizes", "value": "0 B requested"},
    {"kind": "note", "section": "End-to-end engine on the real model (FP32 path)", "text": "zero allocations measured over 2000 inferences: the arena is sized once at load and reused. This is what makes the run path safe on a device whose heap cannot be relied on."},
    {"kind": "timing", "section": "End-to-end engine on the real model (FP32 path)", "metric": "engine_run fp32", "detail": "3 layers, avx2+fma", "min_ns": 339.0, "mean_ns": 398.1, "p50_ns": 352.0, "p95_ns": 444.0, "max_ns": 18633.0, "n": 2000, "ops_per_sec": 2512023.17},
    {"kind": "metric", "section": "End-to-end engine on the real model (FP32 path)", "metric": "arena allocated", "detail": "tensor scratch, sized at load", "value": "1152 B"},
    {"kind": "metric", "section": "End-to-end engine on the real model (FP32 path)", "metric": "arena as share of 128 KB", "detail": "typical LiteOS-M RAM", "value": "1152 B = 1.1 KB of a 128 KB budget"},
    {"kind": "note", "section": "End-to-end engine on the real model (FP32 path)", "text": "arena_bytes is a property of the model shape and the arena planner, not of this machine; it is the number to compare against a device's RAM budget."},
    {"kind": "metric", "section": "End-to-end engine on the real model (INT8 path)", "metric": "quantisation params", "detail": "calibrated at pack time", "value": "in scale=0.0409732 zp=-6, out scale=0.00194258 zp=-128"},
    {"kind": "metric", "section": "End-to-end engine on the real model (INT8 path)", "metric": "heap allocations during INT8 inference", "detail": "malloc+calloc+realloc", "value": "0 over 2000 runs"},
    {"kind": "timing", "section": "End-to-end engine on the real model (INT8 path)", "metric": "engine_run int8", "detail": "in=128 out=1, packed int8", "min_ns": 495.0, "mean_ns": 502.5, "p50_ns": 502.0, "p95_ns": 507.0, "max_ns": 527.0, "n": 2000, "ops_per_sec": 1990039.85},
    {"kind": "note", "section": "End-to-end engine on the real model (INT8 path)", "text": "INT8 reuses the same arena as the FP32 path: codes are 1 byte per element against 4 for float, so no second allocation is needed."},
    {"kind": "note", "section": "Constrained-platform fit (portable numbers, not host timing)", "text": "no emulator is available in this environment (qemu absent), so NO device latency is reported here. Claiming one would be invented. Cross-compile benchmark/htf_bench_constrained for the target and run it there for real device timings; htf_bench_inference needs OpenSSL and the host engine and does not run on the device."},
    {"kind": "metric", "section": "Constrained-platform fit (portable numbers, not host timing)", "metric": "arena within 128 KB budget", "detail": "hard cap enforced at load", "value": "1152 B of 131072 B budget (0.88%)"},
    {"kind": "metric", "section": "Constrained-platform fit (portable numbers, not host timing)", "metric": "64 B arena cap", "detail": "expected refusal", "value": "refused at load (ok)"},
    {"kind": "metric", "section": "Constrained-platform fit (portable numbers, not host timing)", "metric": "INT8 model loaded", "detail": "packed weights, dequant-free run", "value": "quantised=1, arena=1152 B"},
    {"kind": "note", "section": "Constrained-platform fit (portable numbers, not host timing)", "text": "for the LiteOS-M subsystem the measured static footprint is ROM 22.3 KB (18.8 KB of it the weight table) and static RAM ~1 KB plus a 2 KB task stack; see docs/ohos_subsystem.md and the ohos_subsystem gate, which re-measures it with the product's own flags."},
    {"kind": "metric", "section": "Run verdict", "metric": "BENCH RESULT", "detail": "pass", "value": "0 failure(s); all measured cases validated"}
  ]
}

十一、CSV 数据完整记录

11.1 constrained.csv(24 行)

kind section metric detail value min_ns mean_ns p50_ns p95_ns max_ns n ops_per_sec
metric Constrained target: model geometry (LiteOS-M core) model built-in weights, no file I/O 3 layers, in=128 out=1
metric Constrained target: model geometry (LiteOS-M core) layer 0 shape / operands present 128x32 w=0x563215e0f6e0 b=yes
metric Constrained target: model geometry (LiteOS-M core) layer 1 shape / operands present 32x16 w=0x563215e13760 b=yes
metric Constrained target: model geometry (LiteOS-M core) layer 2 shape / operands present 16x1 w=0x563215e13fa0 b=yes
metric Constrained target: model geometry (LiteOS-M core) static buffer sizing ping-pong scratch widest=128, static buffer=128 (fits)
metric Constrained target: model geometry (LiteOS-M core) weight table in flash (.rodata) 4624 weights = 18496 B fp32
metric Constrained target: model geometry (LiteOS-M core) inference scratch RAM static BSS, allocated once at link time 1024 B = 1.0 KB (2 x 128 floats)
metric Constrained target: numerical correctness anomaly probability recorded input vector got 0.471768856, numpy golden 0.471768826, diff 2.98e-08 (tol 0.001)
metric Constrained target: numerical correctness softmax-constant regression output must not be 1.0 not triggered
metric Constrained target: heap allocation audit audit self-test counting path verified passed
metric Constrained target: heap allocation audit heap allocations whole lifecycle 0 malloc, 0 calloc, 0 realloc over init+2000 runs+deinit
metric Constrained target: heap allocation audit heap bytes requested whole lifecycle 0 B
metric Constrained target: heap allocation audit heap frees whole lifecycle 0
metric Constrained target: heap allocation audit VERDICT allocation-free inference CONFIRMED by measurement
note Constrained target: heap allocation audit zero heap allocations across init, 2000 inferences and deinit. The core uses 2 static BSS buffers instead. This is what makes the run path safe on a device whose heap cannot be relied on: there is no allocation to fail on the Nth call, and no fragmentation to accumulate over a device’s uptime.
metric Constrained target: inference timing (THIS machine) running on architecture host (NOT a device figure)
note Constrained target: inference timing (THIS machine) these timings describe this host. They are not a prediction of MCU latency and must not be quoted as one. Cross-compile this file for the target and run it there for real device numbers.
timing Constrained target: inference timing (THIS machine) full forward pass 128->1, 3 layers 1563.0 1607.5 1577.0 1647.0 21589.0 2000 622066.95
metric Constrained target: inference timing (THIS machine) per-inference latency this machine 1.608 us mean, 1.647 us p95
metric Run verdict BENCH RESULT pass 0 failure(s); correctness verified, zero-allocation confirmed

11.2 inference.csv(38 行)

kind section metric detail value min_ns mean_ns p50_ns p95_ns max_ns n ops_per_sec
note FP32 dense GEMV (htf_dense_f32), activation=RELU kernel path in this process: avx2+fma
timing FP32 dense GEMV (htf_dense_f32), activation=RELU dense_f32 relu 128x32 avx2+fma 299.0 320.8 305.0 404.0 1481.0 2000 3117051.52
timing FP32 dense GEMV (htf_dense_f32), activation=RELU dense_f32 relu 32x16 avx2+fma 49.0 50.4 50.0 51.0 59.0 2000 19835956.64
timing FP32 dense GEMV (htf_dense_f32), activation=RELU dense_f32 relu 16x1 avx2+fma 24.0 25.0 25.0 26.0 94.0 2000 39959241.57
timing FP32 dense GEMV (htf_dense_f32), activation=RELU dense_f32 relu 1x1 avx2+fma 18.0 19.7 20.0 20.0 21.0 2000 50873756.77
timing FP32 dense GEMV (htf_dense_f32), activation=RELU dense_f32 relu 7x3 avx2+fma 26.0 27.9 28.0 29.0 43.0 2000 35889245.79
timing FP32 dense GEMV (htf_dense_f32), activation=RELU dense_f32 relu 64x64 avx2+fma 221.0 226.8 225.0 244.0 383.0 2000 4410094.71
timing FP32 dense GEMV (htf_dense_f32), activation=RELU dense_f32 relu 255x129 avx2+fma 2621.0 2799.3 2768.0 2917.0 16182.0 2000 357236.25
timing Scalar vs vector path, same shape dense_f32 (forced scalar) 255x129 scalar 10969.0 11215.6 11040.0 11597.0 69482.0 2000 89161.14
timing Scalar vs vector path, same shape dense_f32 (dispatched) 255x129 avx2+fma 2556.0 2759.9 2714.0 2838.0 22340.0 2000 362327.44
metric Scalar vs vector path, same shape vector speedup mean(scalar)/mean(vector) 4.06x
note Scalar vs vector path, same shape speedup is specific to THIS machine’s AVX2+FMA core; a riscv32 target has no such path and runs the scalar code.
timing INT8 packed vs FP32, same logical layer int8_dense_act 128x32 int8 relu 383.0 392.0 388.0 390.0 8753.0 2000 2550773.14
timing INT8 packed vs FP32, same logical layer dense_f32 128x32 fp32 relu 292.0 296.2 295.0 310.0 323.0 2000 3375892.08
metric INT8 packed vs FP32, same logical layer int8 vs fp32 time mean(fp32)/mean(int8), this host 0.76x
metric INT8 packed vs FP32, same logical layer real model weights 128->32->16->1, per layer summed 4624 B int8 vs 18496 B fp32
metric INT8 packed vs FP32, same logical layer flash saved by INT8 same model, weights only 13872 B saved (4.0x smaller)
note INT8 packed vs FP32, same logical layer byte figures are properties of the representation and hold on any target; the time ratio above is specific to this host.
metric End-to-end engine on the real model (FP32 path) engine active configuration native fp32 avx2+fma layers=3 in=128 out=1 arena=1152B
metric End-to-end engine on the real model (FP32 path) model shape signed .htf in=128 out=1 layers=3
metric End-to-end engine on the real model (FP32 path) heap allocations during inference malloc+calloc+realloc 0 over 2000 runs
metric End-to-end engine on the real model (FP32 path) heap bytes during inference sum of requested sizes 0 B requested
note End-to-end engine on the real model (FP32 path) zero allocations measured over 2000 inferences: the arena is sized once at load and reused. This is what makes the run path safe on a device whose heap cannot be relied on.
timing End-to-end engine on the real model (FP32 path) engine_run fp32 3 layers, avx2+fma 337.0 353.8 342.0 354.0 10652.0 2000 2826495.57
metric End-to-end engine on the real model (FP32 path) arena allocated tensor scratch, sized at load 1152 B
metric End-to-end engine on the real model (FP32 path) arena as share of 128 KB typical LiteOS-M RAM 1152 B = 1.1 KB of a 128 KB budget
note End-to-end engine on the real model (FP32 path) arena_bytes is a property of the model shape and the arena planner, not of this machine; it is the number to compare against a device’s RAM budget.
metric End-to-end engine on the real model (INT8 path) quantisation params calibrated at pack time in scale=0.0409732 zp=-6, out scale=0.00194258 zp=-128
metric End-to-end engine on the real model (INT8 path) heap allocations during INT8 inference malloc+calloc+realloc 0 over 2000 runs
timing End-to-end engine on the real model (INT8 path) engine_run int8 in=128 out=1, packed int8 498.0 517.6 511.0 517.0 13265.0 2000 1931919.17
note End-to-end engine on the real model (INT8 path) INT8 reuses the same arena as the FP32 path: codes are 1 byte per element against 4 for float, so no second allocation is needed.
note Constrained-platform fit (portable numbers, not host timing) no emulator is available in this environment (qemu absent), so NO device latency is reported here. Claiming one would be invented. Cross-compile benchmark/htf_bench_constrained for the target and run it there for real device timings; htf_bench_inference needs OpenSSL and the host engine and does not run on the device.
metric Constrained-platform fit (portable numbers, not host timing) arena within 128 KB budget hard cap enforced at load 1152 B of 131072 B budget (0.88%)
metric Constrained-platform fit (portable numbers, not host timing) 64 B arena cap expected refusal refused at load (ok)
metric Constrained-platform fit (portable numbers, not host timing) INT8 model loaded packed weights, dequant-free run quantised=1, arena=1152 B
note Constrained-platform fit (portable numbers, not host timing) for the LiteOS-M subsystem the measured static footprint is ROM 22.3 KB (18.8 KB of it the weight table) and static RAM ~1 KB plus a 2 KB task stack; see docs/ohos_subsystem.md and the ohos_subsystem gate, which re-measures it with the product’s own flags.
metric Run verdict BENCH RESULT pass 0 failure(s); all measured cases validated

十二、HTML 报告说明

12.1 交互式图表报告(benchmark_report_interactive_charts_plotly.html)

  • 基于 Plotly.js v2.24.1 渲染交互式图表
  • 支持悬停查看数值、缩放、平移等交互操作
  • 文件大小约 16 MB(包含内联的 Plotly.js 库)
  • 报告包含以下章节:
    • Provenance(来源信息)
    • Portable facts(可移植事实)
    • Timing(时序数据)
    • Comparisons and derived figures(比较与派生数据)

12.2 轻量版 SVG 报告(benchmark_report_lite_version_svg.html)

  • 纯 SVG 图表,零外部依赖
  • 文件大小约 35 KB,便于分享
  • 包含与交互式报告相同的数据内容
  • 图表以 SVG 形式内联,无需 JavaScript 渲染

两份 HTML 报告均包含以下诚实性标识:

  • portable(绿色徽标):表示该数据为可移植数据,在任何目标平台上成立
  • host-only(灰色徽标):表示该数据仅描述测试主机,不代表目标设备性能
  • device-measured(深绿色徽标):表示该数据来自目标设备实测(本次为 0 处)
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。