外观
移动端部署
一、概念定义:在"功耗 5W"约束下跑深度学习
移动端推理指在智能手机、平板、嵌入式设备(树莓派、Jetson、IoT 模组)上执行神经网络推理。它与服务器推理的本质差异是约束维度不同:
| 约束维度 | 服务器推理 | 移动端推理 |
|---|---|---|
| 算力 | 几十 TFLOPS 起 | 单 digit TFLOPS |
| 内存 | 80–640 GB HBM | 4–16 GB 统一内存 |
| 功耗 | 几百 W | 5 W 以内(手机) |
| 散热 | 主动风冷 / 液冷 | 被动散热,几秒后降频 |
| 延迟 SLA | ms 级 | 100 ms 级(用户感知) |
| 存储 | TB 级 | 几 GB(不能塞大模型) |
移动端的"功耗墙" 是核心约束:iPhone 15 Pro 持续功耗 ~5 W,超过就降频降亮度——任何"持续 100% GPU 跑 10 秒"的设计都会触发降频。这是为什么移动端优化要关注"每焦耳能跑多少 token"而不只是"峰值每秒多少 token"。
理解移动端推理栈的关键是 硬件抽象层(HAL):上层框架(PyTorch Mobile / TFLite)→ 中间计算图(ONNX / TFLite FlatBuffer)→ 下层硬件后端(CoreML / NNAPI / Hexagon / ANE)。详见 硬件入门。
二、移动推理后端全景
| 平台 | 官方框架 | 加速后端 | 典型场景 |
|---|---|---|---|
| iOS / macOS | CoreML | Apple Neural Engine (ANE)、Metal | iOS App 内嵌推理 |
| Android | NNAPI | Hexagon DSP、NPU、Mali GPU | Android App 内嵌推理 |
| 跨平台 | PyTorch Mobile | CPU / Metal / OpenCL / Vulkan | 服务器同栈迁移 |
| 跨平台 | TensorFlow Lite | NNAPI / CoreML / GPU Delegate | TF 生态延续 |
| 跨平台 | ONNX Runtime Mobile | EP 机制(详见 ONNX Runtime) | 跨多平台兜底 |
| LLM 专项 | MediaPipe LLM Inference | GPU + 自带量化 | Google 系 LLM 工具 |
| LLM 专项 | MLC-LLM | Metal / Vulkan / OpenCL | 跨平台 LLM 编译器路径 |
| LLM 专项 | llama.cpp | Metal / Vulkan / NEON | iOS / Android 上跑 LLM |
ANE、Hexagon、NPU 的术语
- ANE (Apple Neural Engine):iPhone A 系列芯片内的 NPU,16 核架构,峰值 11 TOPS(A17 Pro);
- Hexagon DSP:高通骁龙内的 DSP/HTA(Hexagon Tensor Accelerator);
- 华为 NPU (达芬奇架构):Mate 系列内嵌 NPU,CANN 推理框架;
- 联发科 APU:天玑系列 NPU。 所有这些都叫 "NPU"(neural processing unit),但 API 与算子支持差异大——这就是 NNAPI / CoreML 抽象层的意义。
三、模型转换与量化
iOS:CoreML
python
import coremltools as ct
import torch
import torchvision
# PyTorch → CoreML
model = torchvision.models.resnet50(weights=torchvision.models.ResNet50_Weights.IMAGENET1K_V1).eval()
sample = torch.rand(1, 3, 224, 224)
traced = torch.jit.trace(model, sample)
mlmodel = ct.convert(
traced,
inputs=[ct.TensorType(shape=sample.shape, name="input")],
minimum_deployment_target=ct.target.iOS15,
compute_units=ct.ComputeUnit.ALL, # CPU+GPU+ANE 自动选
)
# 量化
mlmodel_int8 = ct.optimize.coreml.optimize_linear_quant_weights(mlmodel)
mlmodel.save("Resnet50.mlpackage")
mlmodel_int8.save("Resnet50_int8.mlpackage")CoreML 量化档位:
- float16:2× 体积压缩,几乎无损
- int8 dynamic:4× 压缩,运行时量化激活,CPU 友好
- int8 static:4× 压缩 + 加速,需要校准数据
- 4-bit palettization:8× 压缩,精度损失要评估
Android:TFLite
python
import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_keras_model(model)
# 量化选项
def representative_dataset():
for _ in range(100):
yield [np.random.rand(1, 224, 224, 3).astype(np.float32)]
converter.optimizations = [tf.lite.Optimize.DEFAULT] # 动态 int8
converter.representative_dataset = representative_dataset # 静态 int8
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8
converter.inference_output_type = tf.int8
tflite_int8 = converter.convert()
with open("model_int8.tflite", "wb") as f:
f.write(tflite_int8)TFLite 量化档位:
| 类型 | API | 体积 | 速度 | 精度 |
|---|---|---|---|---|
| FP32 (baseline) | - | 1× | 1× | 100% |
| FP16 | target_spec.supported_types = [tf.float16] | 0.5× | 1.3× | ~99.9% |
| 动态范围量化 (INT8 权重) | optimizations=[DEFAULT] | 0.25× | 1.5–2× | ~99% |
| 全 INT8 | + representative_dataset | 0.25× | 2–3× | ~98% |
| INT4 (实验) | 自定义 | 0.125× | - | ~95% |
四、NPU 加速:让人又爱又恨
理论上 NPU 是移动端最强加速器,实测体验是另一回事:
Apple Neural Engine
- 优点:CoreML 自动调度,ANE 适合卷积、矩阵乘法
- 坑:ANE 支持的算子有限,遇到不支持的算子会"切回 GPU/CPU",跨设备切换有开销
- 诊断:
puts(mlmodel.get_compute_unit()查看实际跑在哪
Qualcomm Hexagon DSP
- 优点:INT8 性能极强,骁龙 8 Gen 3 上 ResNet-50 INT8 ~3 ms
- 坑:要 Qualcomm QNN SDK / SNPE,开发链路长;只在骁龙机型上有效
- 诊断:用 Snapdragon Profiler 看 dispatch 情况
华为 NPU (达芬奇架构)
- 优点:Mate 60+ 上 INT8 性能强
- 坑:用 CANN / MindSpore Lite,与跨平台生态脱节
- 诊断:MindSpore Lite 提供 Benchmark 工具
NPU 不是银弹
- 算子覆盖率低:很多自定义 attention / 新激活函数 NPU 不支持,自动切回 CPU 反而变慢;
- 跨设备一致性差:iPhone 13 与 iPhone 15 NPU 性能差 2×,旧机型可能完全无 NPU;
- 调试难:NPU 是黑盒,性能瓶颈难定位;
- 功耗降频:持续 NPU 满载几秒后降频,长任务稳定性差。 生产经验:先用 CPU FP16 验证正确性,再上 GPU + NPU 加速;性能基准以 90 百分位而非峰值(应对降频)。
五、LLM 在移动端:2024 后的新方向
LLM 在移动端是个有挑战的事——8B 模型 INT4 也要 4 GB 内存,但 iPhone 15 Pro 总共 8GB。可行路径:
1. llama.cpp iOS / Android
最直接的方案(详见 llama.cpp):
bash
# iOS:编译 llama.cpp 为 iOS framework
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
mkdir build && cd build
cmake -DLLAMA_METAL=ON -DLLAMA_BUILD_IOS=ON ..
make
# 集成到 Xcode 项目,Swift 调用实测数据:
| 设备 | 模型 | 量化 | 速度 | 内存占用 |
|---|---|---|---|---|
| iPhone 15 Pro 8GB | Llama-3-8B | Q4_K_S | 10 tokens/s | 4.5 GB |
| iPhone 15 Pro 8GB | Phi-3-mini (3.8B) | Q4_K_M | 22 tokens/s | 2.3 GB |
| iPad Pro M4 16GB | Llama-3-8B | Q4_K_M | 35 tokens/s | 4.5 GB |
| Samsung S24 Ultra | Llama-3-8B | Q4_K_M | 12 tokens/s | 4.5 GB |
2. MLC-LLM:编译器路径
MLC-LLM 把 LLM 编译成 Vulkan / Metal / OpenCL kernel,跨 iOS / Android / WebGPU 都能跑。优势:跨平台一致;劣势:调试复杂、新模型支持滞后。
python
# MLC-LLM 编译 Llama-3-8B 到 iOS
from mlc_llm import compile_model
compile_model(
model="meta-llama/Meta-Llama-3-8B-Instruct",
quantization="q4f16_1",
target="iphone",
output_dir="dist/llama3-8b-iphone",
)3. MediaPipe LLM Inference
Google 在 2024 年推出的移动端 LLM 推理框架,支持 Gemma / Llama / Phi 等。优势:与 Android 生态深度集成;劣势:跨平台弱(iOS 支持有限)。
4. ONNX Runtime Mobile + LLM
ONNX Runtime Mobile 是 ORT 的轻量版本,能跑 LLM 但优化不如前述方案。详见 ONNX Runtime。
六、移动端 LLM 的约束清单
把 8B 模型塞进手机的清单
- 总内存:iPhone 8GB / Android 8–12GB,系统占 2–3 GB,App 占 1–2 GB,留给模型 + KV cache 4–6 GB;
- 模型体积:8B INT4 ≈ 4 GB,必须在下载时即用即解(不能解到磁盘,磁盘 IO 太慢);
- 首 token 延迟:模型加载 1–3 秒,prefill 200 token prompt 0.5–1 秒,要 UX 上显示加载状态;
- 持续生成温度:iPhone 持续 NPU 满载几秒后降频到 60% 性能,要在 benchmark 里反映;
- 电池:1000 token 生成约耗 1–2% 电量,用户感知明显;
- 隐私合规:本地推理对隐私敏感场景(医疗、金融)是优势,可作卖点;
- 首 token 优化:用 prefix caching 缓存 system prompt(llama.cpp 0.2+ 支持);
- 流式 UX:必须流式输出,否则用户等不及。
七、性能数据:基线参考
iPhone 15 Pro(A17 Pro)上的基线(详见 基准测试):
| 模型 | 类型 | 后端 | 速度 | 功耗 |
|---|---|---|---|---|
| ResNet-50 INT8 | 视觉 | ANE | 4 ms / 250 img/s | 1.5 W |
| MobileNetV3 INT8 | 视觉 | ANE | 1.5 ms / 650 img/s | 0.8 W |
| YOLOv8-n INT8 | 检测 | GPU + ANE | 8 ms | 2.5 W |
| BERT-base INT8 | NLP | ANE | 12 ms | 2.0 W |
| Whisper-tiny INT8 | 语音 | ANE | 60 ms (实时因子 0.2) | 1.8 W |
| Llama-3-8B Q4 | LLM | Metal GPU | 10 tokens/s | 4.0 W |
| Phi-3-mini (3.8B) Q4 | LLM | Metal GPU | 22 tokens/s | 2.5 W |
八、权衡与取舍
- 量化精度 vs 速度:INT4 / INT8 是必经之路,但每降一档精度要评估任务损失;
- NPU vs GPU:NPU 快但算子覆盖不全,GPU 兜底;很多模型走"NPU 部分 + GPU 部分"混合;
- 本地 vs 云端:本地低延迟、隐私好;云端模型大、能力强;混合架构(小请求本地、大请求云端)是常见模式;
- 预下载 vs 按需下载:App 体积超 200 MB 用户不愿装,模型应放首次启动后下载;
- 离线 vs 在线:离线场景(飞行模式、地铁)必须本地,但模型容量受限;
- App 上架合规:苹果对"动态下载模型"有审核规则,需提前评估。
九、与同类对比
| 方案 | 与移动端部署的关系 |
|---|---|
| llama.cpp | 移动端 LLM 首选 |
| ONNX Runtime | ORT Mobile 是跨平台兜底 |
| OpenVINO | Intel Edge 设备可用,但移动端不是主战场 |
| MLC-LLM | 跨平台 LLM 编译器路径 |
| MediaPipe | Google 移动端全栈方案 |
十、可继续追踪
- 概念页:量化、剪枝、蒸馏、权重-激活混合精度、延迟与吞吐、显存带宽
- 案例页:llama.cpp、ONNX Runtime、OpenVINO、vLLM
- 实践页:引擎对比、调优实践、基准测试、项目集、避坑指南
- 资源页:硬件入门、术语表、Awesome 集合
参考资料
- Apple. CoreML Tools 文档 — iOS 转换与量化
- Apple. Metal Performance Shaders — Metal 计算
- Google. TensorFlow Lite — Android 部署
- Google. MediaPipe LLM Inference — 移动端 LLM
- Qualcomm. QNN SDK — Hexagon DSP
- Huawei. CANN / MindSpore Lite — 华为 NPU
- MLC-LLM — 跨平台 LLM 编译器
- PyTorch Mobile — PyTorch 移动端
- ONNX Runtime Mobile — ORT 移动端裁剪版