端侧大模型推理优化:在内存墙下榨干每一个字节
同一颗芯片,云端跑得飞起的模型搬到手机上却慢成蜗牛——2026 年端侧推理工程的核心命题只有一个:在内存墙与算力墙的双重挤压下,让每个字节和每个周期都物尽其用。 算力早已不是瓶颈,真正的敌人是带宽、是显存容量、是功耗预算。这篇文章拆解四个关键战场——量化、MoE 稀疏性、KV Cache、异构硬件——并给出可直接落地的工程决策框架。
一、为什么算力早已不是瓶颈
先做一道简单的算术题。推理一个 70B 模型,单次前向传播大约需要多少 FLOPs?按每参数 2 FLOPs 估算,约为 140 GFLOPs。以一颗 50 TOPS 的 NPU 为例,纯计算时间只需约 3ms。但实际单步推理的耗时普遍在 30–100ms,中间差了一个数量级——那部分时间,芯片在等数据从内存搬到计算单元。
这就是"内存墙"的本质:GPU/NPU 的浮点算力近几年翻了几倍,但内存带宽每年只涨 15–20%。芯片算得飞快,数据喂不进去,算力被活活饿死。放端侧场景,问题被进一步放大——手机不能插几十张卡、不能堆几百 GB 显存,它的内存、带宽、功耗、散热全是硬约束。
大模型推理是典型的访存密集型负载,而非计算密集型。 这个事实决定了整条优化路线:谁能在单位带宽内塞进更多有效计算,谁就赢。
二、量化:被误解最深的单项技术
量化的数学账非常直白:模型权重占用 = 参数量 × 每参数字节数。FP16 每参数 2 字节,INT8 是 1 字节,INT4 是 0.5 字节。
以一个 35B 模型为例:
| 精度 | 每参数字节 | 权重占用 | 16GB 手机可行性 |
|---|---|---|---|
| FP32 | 4 | 140 GB | 完全不可能 |
| FP16 | 2 | 70 GB | 不可能 |
| INT8 | 1 | 35 GB | 不可能 |
| INT4 | 0.5 | 17.5 GB | 勉强,需换出 |
| 混合 2–4bit | ~0.35 | ~12 GB | 可行 |
| 1.58bit (三元) | ~0.2 | ~7 GB | 宽裕 |
| 从 FP16 到 INT4,权重体积压到四分之一,才勉强摸到旗舰手机内存上限。 |
量化不是四舍五入
很多人以为量化就是把浮点数截断为整数。实际上,最常用的分组量化把权重按块分组,每组单独计算 scale 和 zero point:w_int = round(w_float / scale) + zero_point。分组的意义在于,不同组的权重分布差异很大,统一 scale 会让某些组精度崩掉。实践中 4bit 量化常用 group size 32 或 128,这是精度和开销的平衡点。
精度悬崖的悖论:为什么 3-bit 对小模型更致命
一个反直觉的现象:同样的量化位宽,越小的模型损失越严重。直觉上的解释是,大模型每层有更多参数冗余,单点的量化误差被周围的稠密连接吸收;小模型本身参数就稀疏,每个权重承载的信息密度更高,任何一位的丢失都会直接传导到输出。经验数据也支持这一点——4bit PTQ 对大多数对话模型够用,3bit 开始明显掉点,2bit 以下不上 QAT 基本没法看。
绕过悬崖的工程方案有两条路。
第一条是混合精度。不是所有层都同等重要:注意力层的 QKV 投影、输出投影对精度敏感,某些前馈层可以压得更狠。Synaptics 的实践给出了具体数据:84% 的层压缩到 4-bit,剩下 16%(包括语言建模头)保留 8-bit,平均位宽约 4.3 bits,结果权重压缩带来 2.7 倍的有效吞吐提升,且几乎无损精度。
第二条是误差补偿。BiLLM 类方法的核心思路是把权重矩阵分解为两部分:粗量化主干(用极低位宽表示)+ 低秩残差补偿(用一个低秩矩阵逼近量化误差)。数学上:
$$W \approx Q(W) + UV, \quad U \in \mathbb{R}^{d \times r}, V \in \mathbb{R}^{r \times d}$$
其中 $Q(W)$ 是量化后的权重,$UV$ 是秩为 $r$ 的残差近似。推理时,W @ x 被拆为 Q(W) @ x + U @ (V @ x),前者用整数计算,后者秩很小、开销可忽略。这套机制能把 2bit 量化的精度拉回到接近 4bit 的水平。下面是一个简化实现:
import torch
def quantize_with_compensation(W: torch.Tensor,
bits: int = 2, rank: int = 8,
group_size: int = 32) -> dict:
"""
量化主干 + 低秩残差补偿
W: [d_out, d_in] 原始权重
"""
d_out, d_in = W.shape
# 1. 分组量化主干
W_groups = W.reshape(-1, group_size)
scale = W_groups.abs().max(dim=1, keepdim=True).values / (2**(bits-1) - 1)
scale = torch.clamp(scale, min=1e-8)
W_q = torch.round(W_groups / scale).clamp(-(2**(bits-1)), 2**(bits-1) - 1)
W_deq = (W_q * scale).reshape(d_out, d_in)
# 2. 残差低秩近似
residual = W - W_deq
U, S, V = torch.linalg.svd(residual, full_matrices=False)
U_low, S_low, V_low = U[:, :rank], S[:rank], V[:rank, :]
compensation = U_low @ torch.diag(S_low) @ V_low
return {
"quantized": W_q.reshape(d_out, d_in).to(torch.int8),
"scale": scale.reshape(-1),
"comp_U": U_low.contiguous(), # [d_out, rank]
"comp_V": (torch.diag(S_low) @ V_low).contiguous() # [rank, d_in]
}
def matmul_lowbit(x: torch.Tensor, pack: dict) -> torch.Tensor:
"""带补偿的低比特矩阵乘"""
# 整数主干(实际部署中会进一步打包为 bit-packed 格式)
W_deq = pack["quantized"].float() * pack["scale"].unsqueeze(1)
main = x @ W_deq.t()
# 低秩补偿
comp = (x @ pack["comp_V"].t()) @ pack["comp_U"].t()
return main + comp
1-bit 的边界在哪里
2026 年骁龙峰会上,高通和 PrismML 演示了智能眼镜上运行的 1-bit 视觉语言模型:语言部分 1.7B 参数用 1-bit(占 0.43GB),视觉编码器 300M 参数用 4-bit。对比同等规模的 4-bit 模型,内存占用降低 74%,token 生成速度从 7.44 提升至 15.36 tokens/s(2.06 倍)。这说明在严格的功耗与内存约束下,1-bit 已进入工程可用区间——但前提是模型架构在训练阶段就为极低位宽做了适配,纯 PTQ 到 1-bit 仍然不现实。
三、MoE 的显存悖论与 SSD 分层
MoE(Mixture-of-Experts)架构带来了一个特殊的资源悖论:计算上轻、存储上重。每个 token 只激活 top-k 个专家(比如 3B 激活参数),但所有专家(比如 35B 总参数)都必须在某处待命。
以 Qwen3.6-35B-A3B 为例:4-bit 精度下总权重约 19.5 GB,而 16GB 内存的设备根本装不下。但计算量只相当于一个 3B 稠密模型——这是端侧设备完全负担得起的。
2026 年 9 月,两个独立团队在同一天发表了同一思路的论文:把完整专家池放在 NVMe SSD 上,推理时只把活跃工作集流式载入 RAM/VRAM。这个时间上的巧合并非偶然,它指向一个硬件事实的质变:PCIe 5.0 NVMe SSD 的顺序带宽已达 14.8 GB/s,超过了单通道 DDR3-1600 的 12.8 GB/s——三年前不存在的收敛,现在成立了。
随机小读取仍然慢,但 MoE 专家权重的访问模式是可预测的大块读取(一旦路由确定,哪些专家将被需要是明确的),这正好避开了 SSD 的短板。
Edge0 的实现把这个思路推到了极致:35B MoE 在 Mac Mini M4 Pro 上以 15–18 tokens/s 运行,峰值活跃内存控制在 3 GB 以内。它的关键组件是一个训练好的"预路由器"(prerouter),在层 N 的计算完成前就预测层 N+1 将激活哪些专家,提前发起 SSD 读取,用计算时间掩盖磁盘延迟。
另一组 SSD-LLaMA 的数据更夸张:单张 RTX 5090 + 32 GB RAM,跑万亿参数模型,速度超过 1 token/s——慢,但能跑。
四、KV Cache:真正被忽视的"内存刺客"
量化解决了"权重占多大",但推理过程中动态增长的中间状态是另一个吞显存的怪兽。KV Cache 的内存占用可以精确计算:
$$\text{KV Cache} = 2 \times L \times H_{kv} \times D \times S \times \text{bytes}$$
其中 $L$ 是层数,$H_{kv}$ 是 KV 头数(GQA 中少于 Q 头数),$D$ 是每头维度,$S$ 是序列长度。以 Llama 3 70B(L=80, H_kv=8, D=128)为例,FP16 下每个 token 占约 160 KB;单条 128K 上下文请求,KV Cache 就要吃掉约 20 GB,10 个并发请求就是 200 GB——比模型权重本身还大好几倍。
这里有一个被大多数教程忽略的不对称性:Prefill 阶段是计算密集型,Decode 阶段是内存带宽密集型。Prefill 处理整个输入序列,大量并行矩阵乘法,算力是瓶颈;Decode 每次只算一个 token,却要读取全部历史 KV,带宽才是瓶颈。这决定了优化策略必须分阶段设计。
2026 年生产环境的共识组合拳:
| 优化手段 | 缓存压缩倍数 | 代价 |
|---|---|---|
| GQA | ~8× | 需要短暂上训练 |
| MLA (DeepSeek 路线) | ~16× | 需要从头训练 |
| KV Cache INT8 | ~2× | 精度轻微损失 |
| PagedAttention | ~2× (有效) | 工程复杂度 |
| Prefix Caching | ~1.5× | 仅对共享前缀有效 |
| DeepSeek V4.1 Flash 已经把 KV Cache 压到了 FP4,这在长上下文场景下是巨大的解放。而 2026 年主流前沿模型普遍采用混合层间注意力:少数层用完整 softmax 注意力保留精确记忆,多数层用线性/SSM 注意力以近线性内存代价承载长上下文——这也是 Llama 4 和 Qwen3.8 系列的共同路线。 |
五、NPU 与 GPU:架构差异决定策略
同样的模型、同样的量化位宽,在 GPU 和 NPU 上的最佳部署策略截然不同,根源在于两者对"权重驻留"的假设不同。
GPU 推理假设权重常驻显存。NVIDIA 的 HBM 有极大带宽(H100 约 3 TB/s),一旦权重装进去,后续访存几乎免费。这套逻辑在云端成立,在端侧被打破:12GB 或 24GB 的显存装不下动辄几十 GB 的量化模型,只能靠分层换入换出——但 PCIe 带宽(约 32 GB/s)远低于 HBM,每一步 Decode 都在等数据。
NPU 是流式架构。它的设计哲学是:权重像流水一样从内存流过计算单元,不需要驻留。Apple Neural Engine、高通 Hexagon、MediaTek APU 都是这个思路。这正好匹配 MoE + SSD 分层的访问模式。实测数据也印证了这条分界:
| 平台 | NPU/引擎 | 算力 | 8B Q4 tokens/s | 功耗 |
|---|---|---|---|---|
| NVIDIA Jetson Orin 32GB | Ampere GPU | 200 TOPS | 18–25 | 30W |
| Apple M3 Max | ANE + GPU | — | 65–75 | 30W |
| iPhone 15 Pro (A17) | ANE | 18 TOPS | 14–18 | 5W |
| Pixel 8 Pro (Tensor G3) | TPU | 4 TOPS | 8–12 | 4W |
| Snapdragon 8 Gen 3 | Hexagon NPU | 45 TOPS | 18–25 | 5W |
| Raspberry Pi 5 | 仅 CPU | — | 2–3 | 8W |
| 值得注意的一个工程细节:NPU 在"最佳能效"模式下吞吐量会下降 30–40%;而散热对持续性能的影响常被低估——机身表面温度下降 5°C,可持续 TOPS 提升约 8%。移动端的推理优化不只是软件问题,固件、驱动、散热设计都会进入优化路径。 |
六、落地的工程决策框架
把以上技术收敛成一份可以直接执行的决策路径。
量化选择,按精度需求分档:
- 4-bit PTQ + group size 128:默认安全选项,绝大多数对话场景可用
- 混合精度(关键层 8-bit,FFN 层 4-bit):对输出质量敏感的场景
- 2-bit + 低秩补偿:内存极度紧张、可接受轻微质量损失
- 1.58-bit:仅适合训练阶段做过适配的模型(BitNet 类)
MoE 端侧部署,按内存条件分档: - 总权重 < 可用内存:直接常驻,无需优化
- 总权重 > 内存但激活参数 < 内存:SSD 分层 + 预路由
- 激活参数也超内存:放弃端侧,走云端
上下文长度,按 KV Cache 预算倒推: - 短上下文(< 8K):INT8 KV Cache 即可
- 中等(8–32K):GQA + PagedAttention + INT8
- 超长(> 32K):MLA 架构模型或 FP4 KV Cache,必要时 YaRN 外推
硬件选型,按场景分档: - 手机聊天:Snapdragon 8 Gen 3+ 或 iPhone 15 Pro+
- 笔记本本地开发:Apple M3 Max(MLX 生态)或 AMD Strix Halo(RyzenAI)
- 工业机器人:Jetson Orin
- 极端内存约束的可穿戴:探索 1-bit 方案
工具链:llama.cpp 的 QNN 后端(高通)、RyzenAI-SMI + ONNX Runtime(AMD)、OpenVINO GenAI(Intel)、MLX/Core ML(苹果)。跨平台部署走 ONNX 格式,量化用onnxruntime.quantization.matmul_4bits_quantizer做 W4A8 混合精度。
一个可直接套用的端侧部署流程:
# 1. 导出 ONNX
optimum-cli export onnx \
--model meta-llama/Llama-3.2-1B-Instruct \
--opset 17 --dtype fp16 \
llama-3.2-1b-onnx/
# 2. 混合精度量化
python -m onnxruntime.quantization.matmul_4bits_quantizer \
--input llama-3.2-1b-onnx/ \
--output llama-3.2-1b-onnx-int4/ \
--block_size 32
# 3. 端侧运行(以 Android 为例)
# Kotlin: ORTSession 加载量化后的 model.onnx
实测数据:Pixel 8 Pro 上 SmolLM3 1.7B Q4 达到 12 tokens/s,首 token 延迟 150 ms;Snapdragon 8 Gen 3 上 Llama 3.2 3B Q4 达到 18 tokens/s,首 token 延迟 95 ms。
七、一个常被忽略的提醒
量化后的模型一定要做实际任务评测,不能只看困惑度(perplexity)。困惑度是数学上的距离,但实际任务中,一个 perplexity 只差 0.1 的模型可能在特定指令遵循上表现完全不同。建议的评测集至少覆盖:指令遵循、多轮对话记忆、代码生成、长文档摘要——这些场景对量化误差的敏感度差异极大。
回到开头的那个问题。7B 模型在手机上跑不动,从来不是因为芯片算力不够,而是内存带宽和容量在物理上锁死了上限。2026 年的端侧推理工程,本质上是一场围绕这几个硬约束的系统级腾挪:量化换空间、MoE 换带宽、KV Cache 压缩换上下文、NPU 流式架构换功耗。每一项单独看都不惊艳,组合起来才让 35B 参数住进 3 GB 内存成为现实。
端侧推理的真正护城河不在模型大小,而在对每个字节的极致管理。 当 SSD 顺序带宽追平内存、当 1-bit 量化进入工程可用区间、当 NPU 成为手机的标配算力,云端与端侧的分界线正在被重新划定。

浙公网安备 33010602011771号