Fast On-device LLM Inference with NPUs

llm.npu:用手机 NPU 加速端侧 LLM Prefill

Daliang Xu, Hao Zhang, Liming Yang, Ruiqi Liu, Gang Huang, Mengwei Xu, Xuanzhe Liu
Peking University, Beijing University of Posts and Telecommunications
ASPLOS 2025
Presenter: wzw
Date: 2026-04-06

TL;DR

  • 瓶颈: 端侧真实 workload 往往不是 decode-bound,而是 prefill-bound
  • 方法: llm.npu 用 chunk-sharing graph + shadow outlier execution + out-of-order subgraph scheduling,把 INT8 MatMul 主路径推给手机 NPU。
  • 结果: 平均 22.4x prefill speedup、30.7x energy saving,1024-token 场景最高 43.6x 提速。

为什么先救 Prefill

  • Figure 1 的关键信号很直接: UI automation、邮件回复、chat summary 里,prefill 占总时延 88.3%–98.8%(CPU)
  • 就算换成 mobile GPU,prefill 仍占 54.2%–91.7%;随着 prompt 变长,占比还会继续上升。
  • 论文的选题判断因此很准: 端侧长 prompt LLM,先救 prefill 比先救 decode 更值钱

NPU 很强但不能直上

路径 数据类型 延迟 含义
NPU INT8 0.9 ms baseline
CPU INT8 4.2 ms 4.6x
GPU FP16 1.7 ms 1.9x
NPU FP16 252 ms 193x
  • Mobile NPU 适合 INT8 SIMD MatMul,但对 FP16 极弱。
  • LLM 直接上 NPU 会遇到三道鸿沟: dynamic prompt shapeoutlier 破坏 per-tensor quantizationAttention/Norm 仍要 float
  • 对 Gemma-2B,单次 graph build 约 360 ms,graph optimization 约 11.54 s;若每个 prompt length 都重编译,系统直接不可用。

llm.npu 总体结构

  • Preparation: W8A8 量化,预构建 fixed-length chunk graphs,离线 profile outlier 与子图时延。
  • Execution: Linear/FFN 走 NPU,Attention/LayerNorm/outlier compensation 走 CPU/GPU,再用调度把 bubble 压缩掉。
  • 核心目标不是 “all-on-NPU”,而是 最大化 NPU-friendly 工作占比,同时控制异构边界成本

机制1:Chunk-sharing

  • 先把变长 prompt 切成固定长度 chunk,保留 decoder-only 的因果依赖。
  • 再把子图拆成 static operatorsdynamic operators: 前者跨 chunk 共享,后者按 chunk 单独保留。
  • 这样解决的不是算子速度,而是 NPU graph 准备成本与常驻内存爆炸

为什么它有效

  • 在 Qwen1.5-1.8B 上,144 个子图里有 120 个可以共享。
  • prompt=1024chunk=256 时,chunk-sharing graph 最多可减少 75% 内存,即 7.2 GB
  • 论文经验上把 chunk length 选为 256,平衡 NPU 利用率与 padding 浪费。
  • 这一步让 “dynamic prompt 触发反复 graph rebuild” 变成 “固定 graph 复用 + 少量动态 attention path”。

机制2:Shadow outlier

  • 论文不做 per-group MatMul,而是把超出量化范围的极少数 activation outlier 抽出,交给 CPU/GPU 补算。
  • 主路径仍保持 NPU 上的 per-tensor W8A8 MatMul,从而避免 group quantization 在手机 NPU 上的巨大低效。
  • 直觉上它是在把一个“全张量精度问题”改写成“极少数通道的稀疏补偿问题”。

为什么 outlier 路线可行

  • Figure 10 显示单次推理通常只有 0.1%–0.3% channel 含 outlier,也就是约 5–15 个通道
  • 因此 CPU shadow execution 足够稀疏,理论上可以被 NPU 主路径隐藏。
  • 为降低副作用,作者再加两步: hot-channel cachingtop-85% unimportant layers pruning

Shadow 的代价也不小

  • 若简单实现,CPU 侧要再保留一份 MatMul 权重,内存几乎翻倍。
  • CPU-NPU reduction synchronization 甚至可吃掉 29.7% end-to-end latency20.1% energy
  • 论文通过 “少量 hot channels 常驻 + 其余权重按需取回” 把 shadow memory overhead 再降 34.3%
  • 所以这个机制真正聪明之处不是公式,而是 把稀疏补偿工程化到可部署

机制3:乱序调度

  • 简单 overlap CPU/GPU 与 NPU 还不够,论文测得 critical-path bubble rate 高达 37%
  • 做法是把每个 chunk 再切成 subgraph;只要依赖满足,就允许后续 chunk 的 ready subgraph 提前执行。
  • heuristic 很 systems: 优先减少 NPU stall,因为 prefill 阶段 NPU 才是主要关键路径。

一次 Prefill 如何流动

  1. 收到变长 prompt 后,runtime 先按固定 chunk=256 切分请求。
  2. 每个 chunk 进入共享的 static subgraph;attention 等 dynamic path 选择对应维度子图。
  3. Linear/FFN 等 INT8-friendly 子图送入 NPU;Attention/Norm/outlier 走 CPU/GPU。
  4. 调度器不按 chunk 严格顺序,而是谁更能减少 NPU stall 就先跑谁。
  5. 最终把每个 chunk 的结果因果拼接,得到正确的 prefill 输出。

系统开销与代价

项目 结果 含义
代码实现 10K+ C/C++/asm 强工程系统
总内存 最多 1.32x baseline 不是轻量部署
shadow 额外内存 0.6%–1% 总内存 算法本身开销小
GPU-NPU 协同 E2E 再降 80–90 ms 但当前未完整实现
适配性 绑定 QNN + Hexagon 跨平台迁移有成本
  • 这篇论文付出的“硬件账单”不是 area,而是 memory、runtime complexity、backend 绑定与实现复杂度

实验方法

  • 设备: Redmi K70 Pro (Snapdragon 8 Gen 3, 24GB) 与 Redmi K60 Pro (Snapdragon 8 Gen 2, 16GB)。
  • 模型: Qwen1.5-1.8B, Gemma-2B, Phi-2-2.7B, LLaMA-2-7B, Mistral-7B
  • Baseline: llama.cpp, MNN, TFLite, MLC-LLM, PowerInfer-v2
  • 任务: LongBench、DroidTask、Persona-Chat;accuracy 用 LAMBADA/MMLU/WinoGrande/OpenBookQA/HellaSwag
  • 默认设置: chunk=256,outlier pruning rate=85%,decode 仍走 MLLM CPU backend。

Prefill 性能很强

  • 1024-token 场景下,llm.npu 相比 llama.cpp-CPU / MNN-CPU / MLC-GPU / TFLite-GPU 可达 7.3x–43.6x speedup。
  • 对同样用 NPU 的 PowerInfer-v2,仍有 3.28x–5.6x 优势,说明赢点不是 “用了 NPU” 本身,而是三层重构。
  • prompt 越长收益越大,和论文对 prefill bottleneck 的分析完全一致。

节能也成立

  • 在 Redmi K60 Pro 上,1024-token 场景对 llama.cpp-CPU / MLC-GPU / TFLite-GPU 可节能 1.85x–59.52x
  • 这说明论文不是靠“同时开更多硬件单元硬堆性能”,而是在利用 NPU 的整数能效优势
  • 对端侧系统来说,这个结果和 speedup 一样关键,因为电量与发热直接影响可部署性。

E2E 与精度怎么看

  • LongBench / DroidTask: prompt 长、输出短,端到端收益明显,可到 1.4x–32.8x
  • Persona-Chat: 输出 token 多,decode 占比高,因此 llm.npu 对 PowerInfer-v2/TFLite 只剩约 1.1x 优势。
  • Accuracy: 相对 FP16,llm.npu 在五个 benchmark 上平均退化约 -1.2% / -0.0% / -0.1% / -0.5% / +0.2%
  • 相比之下,SmoothQuant 平均可掉 -5.1%-14.9%K-Quant 最差平均可到 -31.3%

消融说明真因

  • naive NPU offload 反而会 2.55x–2.68x,说明这不是“把算子搬去 NPU”就自然成立的系统。
  • chunk-sharing graph 贡献 1.46x–5.09xshadow outlier 再给 3.91x–8.68x
  • out-of-order execution 继续把 prefill latency 降 18%–44%,负责榨干异构协同效率。

我的评价

  • 优点: 问题画像很准,三层机制正好对应 dynamic shape、outlier quantization、异构调度三道鸿沟。
  • 边界: 它更像 “Fast On-device LLM Prefill with NPUs”,并没有真正解决 decode。
  • 代价: 强绑定 Qualcomm Hexagon + QNN,整体内存最高仍有 1.32x
  • 后续: 做完整 GPU-NPU 协同,再叠加 prefix cache / KV cache / speculative decoding