Skip to content
cccskills
FreePublished on GitHub

metal-optimize

Guide MNN Metal backend development and optimization, from finding performance bottlenecks to changing GPU computation, combining operators, and adjusting execution scheduling. A task-based document index directs work toward relevant implementation rules, benchmarks, and correctness checks.

OriginalShow the original description

MNN Metal 后端 op/kernel 开发与优化入口。

索引各份 sub-doc:性能问题诊断流程(op 单测 + 对手基准定位真瓶颈,优化任务第一站)、kernel 开发规范与优化知识库(命名/写法/GEMV/GEMM/attention + 手段方法论)、算子融合全链路(导出图→converter→Metal 单 dispatch + 融合方法论)、运行时调度(fence/content-cache/H2D/replay + 调度方法论)、构建测试基线、env 开关注册表。

根据当前任务选择性阅读对应 sub-doc。

See how to install

Good for

  • Finding bottlenecks in Metal inference
  • Adding or modifying Metal kernels
  • Combining operators into one GPU dispatch
  • Investigating CPU waits during text generation

Files included (7)

  • SKILL.md16.7 KB
  • build-and-test.md12.7 KB
  • env-registry.md22.5 KB
  • graph-fusion.md31.6 KB
  • kernel-dev-and-optimize.md94.7 KB
  • op-bench-and-diagnosis.md31.0 KB
  • runtime-scheduling.md19.2 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

MNN Metal 优化 Skill(索引)

触发:新增或修改 Metal kernel / shader / dispatcher;LLM decode/prefill 性能优化; 算子融合(导出侧声明 + 后端单 dispatch);per-op profiling 定位瓶颈;跑 Metal LLM 测试或对拍。

边界:不读不改 schema/private/、source/internal/。

使用方式

先按任务类型定位到具体 sub-doc,本文件只做索引和路由,不承载技术内容。

记录规则(默认不记录)

每次实验的结果不需要写进 skill。 skill 是给下一个人用的操作知识,不是实验流水账。绝大多数 A/B 跑完就完了,写在 commit message 和 PR 描述里即可。

只有满足下列之一才值得写进 skill,且只写"可复用的那一句",不搬数据:

值得写写到哪写成什么
一条跨形状/跨芯片仍然成立的判据(例:"coop-tensor 路径加宽 K 赚、加宽 N 亏,因为 destination capacity 只跟 N 走")对应 sub-doc 的方法论节一句原理 + 适用边界,不带百分比
一个会让人重复踩的陷阱(编译期宏四处同步、内存别名、run_test.out 用 precision 1 静默关掉 fp16 kernel、zsh 不分词导致开关没生效)kernel-dev-and-optimize.md §1.6 或本文件"通用原则速览"症状 + 根因 + 规避写法
一个新增/删除/改名的 env 开关env-registry.md只写名称 / 默认值 / 功能 / 生效条件
一条新的路由或默认值(哪种 shape 走哪条 kernel)kernel-dev-and-optimize.md 路由速查条件 → 走哪条 kernel
一个已证伪且别人很可能重试的方向只在能提炼成可复用判据时,写进对应手段的「适用边界」"这类手段在 Z 条件下不成立,因为 Y"——不留实验档案

不要写进任何 skill 文件:

  • 单次 A/B 的百分比、ms、GB/s、tok/s、配对明细、扫点表、per-rep 方差;
  • 标定过程叙事(先测什么后测什么、哪次翻案、哪次是漂移伪影);
  • 只在一台机器一个模型上成立的数字;
  • 已回退的实验代码的实现细节。

kernel-dev-and-optimize.md 有额外的硬性约束:它记的是每个手段为什么能赚——赚在哪一类资源上(带宽 / 并行度 / 指令 / 同步)、什么条件下成立、有什么陷阱。不写任何性能数字(百分比、ms、GB/s、TFLOPS、tok/s、扫点表、配对明细),不写日期 / commit hash / 具体机型与模型名(设备与形状只以"类别"出现,如"tensor-coop 设备"、"GQA group 较大的模型"),不写反例存档与标定叙事。详见该文件开头的记录规则。

runtime-scheduling.md 只记录优化方法与原理:保留开销来源、适用条件、安全边界、代码入口与验证方式;不写任何实测数据或实验叙事,包括耗时、吞吐、占比、实测计数、A/B 结果及测试通过数量。详见该文件开头的记录规则。

env-registry.md 有额外的硬性约束:它只是"当前存在哪些开关、默认什么、干什么、什么条件下生效"的查询表。任何环境变量带来的性能收益或损失,一律不许写进那个文件——包括百分比、配对结果、转正/证伪结论、commit hash、日期、设备与模型名。详见该文件开头的约束清单。

Sub-doc 结构

文件何时阅读内容
op-bench-and-diagnosis.md比对手慢但不知道慢在哪;或已知某 kernel 慢,想知道"还剩多少空间 / 往哪改 / 何时收工"——任何优化任务的第一站诊断流程:为什么必须「op 单测(信噪比)+ 对手基准(绝对标尺)」两件一起上;怎么造 op 单测(5 条构造要求、品质因子选 GB/s 还是 TFLOPS);怎么造对手镜像(6 项可比性核对、惰性图 donation 陷阱);三种诊断的选用(绝对标尺 / 固定-流式分解 t=a+b·N / 消融阶梯);标定尺度分工表(路径开关认 e2e、kernel 内部旋钮认 op 单测);验证(改归约顺序不能 byte-compare、env 覆盖当零重建基线);收工判据;度量卫生 + 配对脚本模板;现成资产清单;5 个案例总表
kernel-dev-and-optimize.md写或改任何 Metal kernel 之前都先读第一部分;做 kernel 层性能优化时读第二部分第一部分 开发规范:核心原则、dispatcher 结构、shader 组织与 kernel 命名约定、变量/宏名必须等于真实物理量、编译期宏与 pipeline 缓存 key 的四处同步、Execution 骨架与注册、9 个通用陷阱(A–I)、packed weight 设计、修改流程、正确性验证、tensor API cooperative tensor 布局、Apple GPU 杠杆。<br>第二部分 优化知识库(只写机制与原理,不含数字 / 日期 / 反例存档):优化总纲与 decode 画像、kernel 内部消融阶梯(逐类删工作定位内部瓶颈 + 地板值 vs 对手)、GEMV(deferred dequant / 双 SG / pre-scaling / split-K / GEMV_2OCQUAD_PER_SG / W2W3 / 短序列缺口)、GEMM(fused Q4 / M64 / in-shader 阈值)、Attention(causal-tri / FA / tensor-API tc / 单 pass SDPA / SDPA_QH_PER_TG / QSPLIT / GQA / 路由速查)、其他 kernel(RMSNorm 小 batch / LinearAttention scan 演进 / gated norm)、§2.5 kernel 手段方法论(原理/适用/陷阱/验证,选题与方案评审用)
graph-fusion.md要让多个算子合成一次 dispatch;改 FusedLinear / GatedRMSNorm;排查"融合没命中 / 融合后输出错"融合全链路:Python 导出期声明分组 → converter LN 吸收 → geometry 兜底拆分 → Metal setupFusion 装配 leader/follower。含内存别名铁律与 STATIC re-home、链式门控依赖、GatedRMSNorm 独立链路、已删除的后端图匹配历史、排查清单、§9 融合方法论(同构投影合并 / 打包 grid / 正确性门槛)
runtime-scheduling.md怀疑 decode 有 CPU 阻塞 / GPU 空泡;改 resize 时机、commit 节奏、H2D、Encode Replayper-backend fence、content-cache、队内 H2D 上传、采样去框架化(host ArgMax/topK)、完成等待自旋、commit cadence、Encode Replay(安全模型 / attention 与 LinearAttention 接入 / KV 悬垂指针坑)、调度类改动的验证套路、§9 调度方法论(同步点治理 / 自动阈值 / 开关收敛纪律)
build-and-test.md改完代码要 build / 跑测试 / 对拍cmake 编译命令、模型导出命令、性能测试命令、CPU/Metal 对拍
env-registry.md查 / 新增 / 删除 Metal 相关环境变量开关env 集中登记,只有名称 / 默认值 / 功能 / 生效条件四列:attention prefill、attention decode、LayerNorm、decode GEMV、量化 GEMM、融合、调度、profiling。含新增开关规范。⛔ 禁止写入任何性能数字与实验叙事

快速任务→sub-doc 索引

想做的事优先读
新加一个 Metal op / kernel(该叫什么名、写在哪、怎么注册)kernel-dev-and-optimize.md §1.3 / §1.5
加一个编译期变体宏kernel-dev-and-optimize.md §1.4(四处必须同步)
新加 quant bit / 改 dispatcher 路径kernel-dev-and-optimize.md §1.2 / §1.6 / §1.7
想知道 Metal 的坑(宏 alias / weight byte order / getDequantScale coef)kernel-dev-and-optimize.md §1.6
Apple GPU 优化杠杆选择(sg_matrix / sg_reduce / tensor API)kernel-dev-and-optimize.md §1.11 / §1.10
比对手慢,但不知道慢在哪op-bench-and-diagnosis.md——优化任务第一站,含完整诊断流程
要新建一个 op 级 speed 单测 / 对手镜像op-bench-and-diagnosis.md §1 / §2(5 条构造要求 + 6 项可比性核对)
差距随规模(ctx/seq)变化,不知道是固定开销还是流式速率op-bench-and-diagnosis.md §3.2 固定/流式分解 t = a + b·N
旋钮该在 op 单测还是 e2e 上标定op-bench-and-diagnosis.md §4 尺度分工表
决定要不要投入某个优化方向(先看这条)kernel-dev-and-optimize.md §2.0——先自测 GPU busy vs wall;若已 GPU-bound 且 occupancy 受限,<5us 级 GPU 节省不兑现为 wall
已知某 kernel 慢,但不知道它内部哪一段慢kernel-dev-and-optimize.md §2.0「kernel 内部消融阶梯」——逐类删工作读差值,得到分项成本表 + 地板值
优化选题 / 方案评审 / 复盘优化方向方法论三节:kernel-dev-and-optimize.md §2.5、graph-fusion.md §9、runtime-scheduling.md §9(只讲原理/适用/陷阱/验证,不含数字)
GEMV 优化(decode 主战场)kernel-dev-and-optimize.md §2.1
GEMM / prefill 优化kernel-dev-and-optimize.md §2.2
Attention 优化 / 想知道当前走哪条路径kernel-dev-and-optimize.md §2.3(§2.3.8 是路由速查)
改 prefill_flash_attn_tc(coop-tensor prefill attention)机制见 kernel-dev-and-optimize.md §2.3.4;FATC 开关默认值与生效条件见 env-registry.md
LinearAttention(Qwen3.5 gated delta rule)kernel-dev-and-optimize.md §2.4.2 / §2.4.3
算子融合:为什么没命中 / 融合后输出错graph-fusion.md §8 排查清单
新模型结构要加融合graph-fusion.md §1(导出侧声明)+ §4(后端装配)
融合后输出逐次不同graph-fusion.md §4.3 内存别名
decode 每 token 的 CPU 阻塞 / 同步开销runtime-scheduling.md
Encode Replay 相关(新 op 要不要接入 / 为什么被 ban)runtime-scheduling.md §7
cmake 编译选项 / 模型导出命令build-and-test.md
查某个 env 开关的默认值和语义env-registry.md

选题决策路径

瓶颈在哪?
├─ 还不知道 / 只知道"比对手慢"          → op-bench-and-diagnosis.md(造 op 单测 + 对手镜像,再做固定/流式分解)
├─ 每 token 固定开销大(dispatch 多 / CPU 段长) → 融合方法论 graph-fusion.md §9 / 调度方法论 runtime-scheduling.md §9
├─ 权重带宽未吃满(decode GEMV)               → kernel 方法论 §2.5.3/§2.5.4
├─ attention 随 KV 变慢                        → kernel 方法论 §2.5.4/§2.5.5/§2.5.8
├─ GPU→CPU 同步密集                            → runtime-scheduling.md §9.2/§9.1
├─ 知道是哪个 kernel,不知道它内部哪段慢       → 消融阶梯 kernel-dev-and-optimize.md §2.0
└─ 不确定                                      → 先 profile(§2.0 GPU busy vs wall)

通用原则速览(细节见 kernel-dev-and-optimize.md)

  1. shader 是嵌入的 C++ 字符串(R"metal(...)metal"; 在 *Shader.hpp 里),不是独立 .metal 文件;公共头靠字符串拼接共享。改完直接 make。
  2. 变体用 preprocessorMacros,不用 function constants。加宏必须同步改四处:shader #ifdef、pipeline 缓存 key、宏字典、onResize 的 grid/threadgroup。
  3. dispatcher 要先摸清:一个 op 常有多条 kernel,扩之前先决定支持哪几条 + 让其他路径显式 fallback。
  4. Apple GPU ≠ Android:M3/M4/M5 之间都不能互推,更不能推 Vulkan/OpenCL。设备分档看 architecture.name / isSupportTensorApi()。
  5. 正确性 oracle 先于性能:fp32(precision: high)bit-identical 是最强证据;fp16 greedy 对拍是次强。token 级一致不等于 bit 级一致。错误 kernel 一样能"变快",对拍通过之前测出的收益都不可信。
  6. 融合必查内存别名:把前驱折进后继时,前驱的输入可能已被分配器复用为后继的输出。
  7. A/B 必须交替配对:热态漂移能造出 3 倍虚假收益;profile build 的绝对数字是伪影。 7b. zsh 不对未加引号的参数展开分词。run() { env $3 ./bench; } 传 "A=1 B=2" 时,env 会把整串当成一个赋值(A="1 B=2"),第二个变量静默丢失——A/B 看起来"没差异",实则探针根本没打开。本次就因此误判过一轮。多变量用 ${=3} 强制分词,或直接写 A=1 B=2 ./bench 前缀。任何"改动没效果"的结论,先确认开关真的传进去了。
  8. 先定位瓶颈段再动手:GPU busy vs wall、kernel 计时 vs e2e、带宽兑现率是三种不同口径;优化必须对准真正的那一段,否则 kernel 变快 e2e 不动。 8b. kernel 内部要归因就逐类删工作,别正向猜:临时开关删掉一类工作(输出故意错),一路删到只剩 MMA/FMA,读相邻差值得到分项成本表和地板值。然后拿地板值和对手比,不要拿总时间比——对手 ≈ 你的地板 ⇒ 差距 100% 在重叠效率(该做批量预发射 / 提高计算:访存比);对手 < 你的地板 ⇒ 差距在算法与工作量,改重叠白费力。见 kernel-dev-and-optimize.md §2.0。探针必须防 DCE(删一小段却省掉半个 kernel = 下游被整体消掉,不是发现)。 8c. 标定尺度按开关类型分:路径开关(走不走 kernel X)认 e2e——防"kernel 级快 / e2e 平"的伪收益;已确认在关键路径上的 kernel 内部参数(nsg / tile / batch)反过来——先用该 kernel 占 100% 的 op test 标定,再用 e2e 验证无回退。否则会把 e2e 分辨不出的旋钮标错:MNN_METAL_DECODE_SDPA_NSG 的某一档默认值就因为标在 e2e 上而长期是错的——attention 在那个场景只占 e2e 一小片,e2e 根本分辨不出这个旋钮;改用 op test 一测就分出胜负。 8d. 对手基准要先做两件事:固定/流式分解 + 确认惰性图没改语义。(a) 差距随规模变化时,先拿两个干净规模点拟合 t = a + b·N 分出每次固定开销 a 和流式速率 b——曾据此发现 MNN decode attention 的 b 已胜对手基准,差距全在 a,于是所有内层 ILP 方向都不用试了。(b) 惰性图框架里,把 N 步攒成一张图再 eval 会改变 in-place donation 语义:原地 slice 更新退化成整份拷贝,我据此把对手基准的 KV append 误判成 O(ctx)(比真实贵 ~30×)。量"每步"成本必须每步 eval。
  9. 布局是全局不变量:数据布局改动牵动所有读写方,必须原子落地,中间状态不可运行。 9b. simdgroup MMA 的两个乘数都必须是 half,只有累加器用 float。把任一乘数提升成 float 会掉到 float MMA 速率——fused attention 的 PV 曾因此慢 1.4×(见 kernel 方法论 §2.3.9)。
  10. 证伪不建档,只留可复用判据:负向/中性实验绝大多数跑完就完了(写在 commit / PR 里即可)。只有当它能提炼成一句跨形状仍成立的判据时才进 skill,且写成对应手段的「适用边界」——"这类手段在 Z 条件下不成立,因为 Y"。百分比、配对明细、翻案与标定叙事一律不进 skill(见上文"记录规则")。
  11. 名字必须等于真实物理量:改任何后端算子 / kernel 代码时,先核对沿途变量、成员、宏、env 名是否就是它实际装的那个量(不只是自己新加的名字)。名字骗人不会报错——编译、对拍、单测全都通过,但基于它写的分档、阈值、门控会一起错。最贵的一次是把分档自变量写成"head 数",而 kernel 真正的并行度是 dispatch 的 threadgroup 数(batch*head_num/qh),默认值换个模型就反向。名字与索引算术不符就改名(宏名 / 缓存 key / 宏字典三处同步)。见 kernel-dev-and-optimize.md §1.3「变量 / 字段 / 宏名必须等于真实物理量」。

相关 Skills

  • skills/general-debug/ — 正确性 bug / 回归诊断入口(按症状分册);Metal 常用的两册是 general-debug/memory-aliasing.md(§1 内存别名 / 生命周期,含融合引入的别名竞争)与 general-debug/gpu-oob.md(§6 shader 越界 / command buffer 故障)
  • skills/opencl-optimize/、skills/vulkan-optimize/、skills/cpu/ — 其他后端
  • skills/support-new-llm/ — 新增 LLM 模型的完整流程
  • skills/test-ci/ — 单测 / 回归测试

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

add-new-op

FreeSummary

Add new operators to MNN through a staged workflow covering data definitions, output shapes, computation, and tests. It prioritizes combining existing operators, with CPU implementations and additional hardware backends used when needed.

  • Adding a new operator to MNN
  • Implementing output shape calculations
  • Combining existing operators for new operations
alibaba/MNN16.2KUpdated Oct 16, 2026

bugfix

FreeSummary

Triage incorrect MNN outputs and regressions by matching symptoms to focused debugging guides. Use backend comparisons, minimal reproductions, and controlled experiments to investigate memory issues, quantization, concurrency, numeric limits, caches, and inconsistent results across runs.

  • Investigating garbled or degraded MNN output
  • Comparing results across execution backends
  • Tracking regressions after optimization changes
alibaba/MNN16.2KUpdated Oct 16, 2026

cpu

FreeSummary

Find the right workflow for MNN CPU work, from investigating slow execution to implementing calculation routines and planning tests. Compare ARM, x86_64, and RISC-V backend structures before choosing the relevant guidance.

  • Choosing where to start an MNN CPU performance investigation
  • Finding guidance for CPU kernel implementation
  • Comparing ARM, x86_64, and RISC-V backend structures
alibaba/MNN16.2KUpdated Oct 16, 2026

cpu-kernel

FreeSummary

Develop or port CPU kernels, the low-level calculation routines used by MNN. Follow staged implementation guidance, check data layout agreements, register functions, and verify correctness across processor instruction sets and numerical precision settings.

  • Implementing or porting an MNN CPU kernel
  • Adding support for a processor instruction set
  • Changing packed data layouts or tile sizes
alibaba/MNN16.2KUpdated Oct 16, 2026

cpu-optimize

FreeSummary

Find why MNN CPU inference is slow by examining threads, scheduling, memory layout, and the processor instruction path actually used. Operator-level measurements and comparisons with other inference frameworks help identify which layer needs improvement across ARM, x86_64, and RISC-V.

  • Investigate slow CPU operators or LLM inference
  • Diagnose thread count and memory usage anomalies
  • Locate the cause of a performance regression
alibaba/MNN16.2KUpdated Oct 16, 2026

Optimize and troubleshoot MNN's Hexagon DSP backend, which runs computation on a dedicated processor. The workflow uses device measurements to identify bottlenecks, compare v79 and v81 architectures, verify correctness, and investigate crashes or memory usage.

  • Finding bottlenecks in Hexagon operators
  • Checking changes on v79 and v81 devices
  • Investigating cDSP crashes and device disconnects
alibaba/MNN16.2KUpdated Oct 16, 2026

See all skills by alibaba

Report a problem with this skill