为 MNN 框架新增算子。包含 Schema 定义、形状计算、几何计算、后端实现、单元测试的完整 TDD 流程。分 5 步执行,每步有独立测试标准。
日本語の概要は準備中です。原文の説明を表示しています。
Run MNN tests / benchmarks on host or real devices. Covers two parallel tracks — (1) the regression / CI suite (static checks, host-side tests, on-device Android arm64 matrix via ./test.sh + test_stages.json) and (2) one-command iOS real-device LLM benchmarking (prefill/decode tok/s, branch comparison). Use when the user asks to run the tests, run CI, smoke-test a build, verify a change on a device, benchmark on-device (Android or iPhone/iPad), or add / select / retune a test stage.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
This skill is an index. Pick the document that matches the task and follow it:
| Document | Use when |
|---|---|
test-suite.md | Run the regression / CI suite — static checks, host (local) tests, the on-device Android arm64 matrix (./test.sh + test_stages.json); add / select / retune a test stage; audit stale CI scripts; add a new test. |
ios-llm-bench.md | Benchmark LLM prefill/decode speed on a real iPhone/iPad (ios_llm_bench.sh); compare branches on iOS Metal/CPU; verify Metal kernel changes on device. |
The two tracks are independent: Android/host regression testing goes through
test.sh, while iOS LLM benchmarking goes through
transformers/llm/engine/ios/ios_llm_bench.sh.
| File | Role |
|---|---|
test.sh | Bash driver. static, local (host CPU), and android <serial> modes. |
test_stages.json | Declarative stage matrix. Edit this to add / drop / retune stages — no shell edits needed for the common cases. It is self-documenting via its _documentation block. |
docs/testing.md | 中文测试文档:阶段说明、字段表、新增算子测试流程。 |
# Static checks only:
./test.sh static
# Host regression (CPU only): build + unit suite + smoke + LLM smoke.
./test.sh local
# Full on-device matrix on the attached arm64 device:
./test.sh android <serial> # e.g. ./test.sh android R5CY71BJJ9D
<serial> comes from adb devices (the script prefers adbk and falls back
to adb). If the device shows as unauthorized, the user must tap Allow USB
debugging on the phone first.
Android mode takes an optional filter as the third argument:
./test.sh android <serial> cpu # CPU unit + lowmem + llm
./test.sh android <serial> opencl # OpenCL unit (image+buffer) + opencl smoke
./test.sh android <serial> vulkan # Vulkan unit + vulkan smoke
./test.sh android <serial> gpu # opencl + vulkan
./test.sh android <serial> unit # all unit/op stages only
./test.sh android <serial> lowmem # only the low-memory matrix
./test.sh android <serial> android-ci # bench + smoke + llm only (no unit/lowmem)
Valid filters: all (default) · cpu · opencl · opencl-image ·
opencl-buffer · vulkan · gpu · unit · lowmem · android-ci.
═══ stage: <name> ═══ block, then a
PASS / FAIL / SKIP line.total / passed / failed / skipped and one line
per stage. SKIP is not a failure — it means the prerequisite was absent
(e.g. a GPU library, a model, or a missing build artefact).logs/test-<UTC-timestamp>/<stage>.log — read the named log of a failing
stage for the trailing output. rc=137 ≈ OOM-kill, rc=139 ≈ SIGSEGV.A zero exit code only proves that a backend context ran; it does not prove that the requested input shape selected the intended dynamic context. For a shape-sensitive device test, record and validate the runtime-observed input shape (for example, from a backend dump manifest or the runner's input tensor) before treating the test as dynamic-shape coverage.
| Var | Mode | Meaning |
|---|---|---|
ANDROID_NDK | android | NDK root. Falls back to $HOME/android-ndk-r21. |
ANDROID_EXTRA_CMAKE | android | Extra cmake flags appended to the build (e.g. -DMNN_SME2=OFF) — handy for bisecting a backend regression. |
LLM_MODEL_DIR | both | Path to an existing on-disk MNN-format LLM model. When set, that directory is used as-is and nothing is downloaded. Defaults to models/<repo-basename>/. |
LLM_MODEL_REPO | both | Model repo id for the LLM smoke test. Default taobao-mnn/Qwen2.5-0.5B-Instruct-MNN. |
LLM_MODEL_SOURCE | both | Download source when LLM_MODEL_DIR is unset: huggingface (default) or modelscope. |
LLM_MODEL_URL_BASE | both | Override the resolve URL prefix outright (wins over LLM_MODEL_SOURCE). |
MNN_TEST_SKIP | both | Comma list of exact test names to skip (also set per-stage via the JSON skip field). |
LLM model provisioning is lazy: the download (or LLM_MODEL_DIR check) is
deferred until the llm stage actually runs, and a provisioning failure skips
only that stage. So the unit / smoke / bench stages run fine with no
network.
# Already have the model on disk → no download attempt at all:
LLM_MODEL_DIR=/path/to/Qwen2.5-0.5B-Instruct-MNN ./test.sh local
# huggingface.co unreachable (e.g. mainland China) → fetch from ModelScope:
LLM_MODEL_SOURCE=modelscope ./test.sh android <serial>
For the built-in default model the ModelScope org is remapped automatically
(taobao-mnn/* → MNN/*); an explicitly-set LLM_MODEL_REPO is used verbatim.
For backend or tensor-layout optimizations, do not stop at operator tests. Run
an end-to-end llm_demo correctness smoke with a short prompt and another
prompt long enough to cross backend prefill branch thresholds. This catches
real exported-graph layout bugs where an op test covers only the output format,
but the graph also changes an input tensor format.
For answer-level comparisons between two macOS Metal runtimes:
MTLCreateSystemDefaultDevice() may return nil, after which
llm_demo prints Init Metal Error / Can't Find type=1 backend, use 0 instead and silently produces a plausible CPU answer. Run in a GPU-visible
context and fail the case on either fallback marker.tmp_path / working directory
so cache reuse cannot cross the A/B boundary.llm_demo normally
treats every non-empty line as a separate prompt; if one file is intended to
be one long prompt, flatten or use an explicitly one-line-aware runner and
record the transformed-input checksum.Editing test_stages.json is the supported way to
add, drop, or retune unit / lowmem / smoke / bench stages. Every parameter
(forward type, precision, gpuMode, thread count, tag, memory mode,
dynamic-quant option, KleidiAI flag, per-stage skip list, smoke model list,
benchmark args) lives there, and the _documentation block at the top of the
file explains every field and every skip entry's rationale.
android.stages (or local.stages). See docs/testing.md § "增加专门阶段".skip array and document why under _documentation.skip_rationale.docs/testing.md § "新增 smoke 模型或 bench 阶段".When asked to clean up old CI or test scripts, build a usage map before recommending deletion:
git ls-files plus targeted rg/git grep over broad filesystem
scans, so generated build directories and local experiments do not look like
maintained CI surface.test.sh / test_stages.json..gitignore,
test_stages.json self-documentation, developer docs, skill docs, and code
comments in the same change so the old entrypoint disappears completely.For bugfixes, first apply the unit-test submission policy: keep development-only tests local, and commit a new test only when its necessity has been reviewed and justified.
See test-suite.md § "Adding a new test" for the full steps.
Two traps worth knowing up front: test/CMakeLists.txt globs sources at
configure time, so a new test file needs a cmake re-run before it exists in
run_test.out; and run_test.out prints an all-passed line even when the filter
matched nothing, so confirm passed:N.
For deeper work on operators themselves, see the
add-new-op skill.
docs/testing.md is the authoritative deep reference — read it for the per-stage
breakdown, the stage-object field table, and worked examples.
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
为 MNN 框架新增算子。包含 Schema 定义、形状计算、几何计算、后端实现、单元测试的完整 TDD 流程。分 5 步执行,每步有独立测试标准。
日本語の概要は準備中です。原文の説明を表示しています。
MNN 各类正确性/回归 bug 的排查入口,按 bug 类别分册组织,本文件只做症状分流。分册:内存别名与生命周期(arena reuse、`MemChunk`、融合引入的别名竞争)、量化误差与导出侧权重损坏(低 bit 打包、导出分块、PyTorch MPS/CUDA 大张量静默错误)、host 侧并发/线程竞争(共享所有权的引用计数被写坏、析构链崩溃、TSAN A/B 与编译期哨兵)、fp16 表示能力不足(长序列复读、position 塌缩,以及「实时计算→预计算查表」重构的三类陷阱)、GPU shader 越界与 command buffer 故障、后端 kernel 隐式假设违反(causal mask、layout 约定)、持久化缓存误信(weight-mmap sync 自我污染、跨模型缓存复用)、逐 run 不同的非确定性(未初始化内存/堆垃圾依赖、多线程动态分发×异构 kernel)。用户报告 MNN 输出乱码/退化、单测或 golden 对不上、改动后回归、换后端结果不同、开某开关才错、结果每次跑都不一样、或崩在析构链上且只在后台线程异步释放时偶现时使用。
日本語の概要は準備中です。原文の説明を表示しています。
MNN CPU 后端(ARM / x86_64 / RISC-V 三侧)的总入口,只做分流不承载技术内容。下分 `optimize/`(为什么慢、该改哪一层)与 `kernel/`(这条 kernel 怎么写对、怎么被选中)两个分支,`shared/` 放两者共用的构建测试跑分命令、env 开关注册表与 RISC-V 开发板远端验证纪律。做 CPU 侧的工作但还不确定该进哪个分支,或需要三侧结构差异对照(第二张函数表按什么分、二级表怎么构造、`Precision_Low` 语义、ISA A/B 怎么做——「三侧不同构对照表」全树唯一一份,就在本文件)时读这里。
日本語の概要は準備中です。原文の説明を表示しています。
MNN CPU 后端 kernel 开发分支(`skills/cpu/` 下,另一分支是 `cpu/optimize` 性能归因)。覆盖标量 oracle → C++ SIMD → intrinsic → 汇编的四级实现阶梯、pack/kernel ABI 契约(tile、cell stride、后处理参数)、CoreFunctions 派发表注册与二级表安全构造、跨 ISA × 精度的正确性门禁,以及 AArch64 / x86_64 / RISC-V 三份实现参考。为 CPU 后端新写或移植 kernel(NEON / SSE / AVX / RVV intrinsic 或 .S 汇编)、新增一层 ISA、改 pack mode 或 tile 参数、把 kernel 挂进函数表时使用。已定位到 kernel 才进本分支。
日本語の概要は準備中です。原文の説明を表示しています。
MNN CPU 后端性能归因分支(`skills/cpu/` 下,另一分支是 `cpu/kernel` kernel 开发)。按五层(Runtime 线程 / Executor 调度 / Layout 内存 / Dispatch 函数表 / Kernel ISA)定位瓶颈,含 bound 类型判定、op 级实验回路、跨框架 op 对 op 对比、跨层不一致的事后定位,以及 ARM / x86_64 / RISC-V 三侧「我到底跑在哪条 ISA 路径上」的诊断面。CPU 上算子或 LLM prefill/decode 慢、线程数或内存占用异常、出现性能回归、要与外部推理框架逐算子对比时使用。
日本語の概要は準備中です。原文の説明を表示しています。
MNN Hexagon/HVX/HMX DSP 后端(`source/backend/hexagon`)的优化、重构、构建与回归验证。覆盖设备实测的相位分解、测量纪律、v79/v81 双架构差异、常见瓶颈模式、已否证方向与 cDSP crash 诊断。
日本語の概要は準備中です。原文の説明を表示しています。