端侧大模型推理优化:在内存墙下榨干每一个字节

同一颗芯片,云端跑得飞起的模型搬到手机上却慢成蜗牛——2026 年端侧推理工程的核心命题只有一个:在内存墙与算力墙的双重挤压下,让每个字节和每个周期都物尽其用。 算力早已不是瓶颈,真正的敌人是带宽、是显存容量、是功耗预算。这篇文章拆解四个关键战场——量化、MoE 稀疏性、KV Cache、异构硬件——并给出可直接落地的工程决策框架。

flowchart TD A[大模型推理的内存墙] --> B1[权重显存] A --> B2[KV Cache 增长] A --> B3[带宽瓶颈] B1 --> C1[量化压缩<br/>FP16→INT4/1.58bit] B1 --> C2[MoE 稀疏激活<br/>SSD 分层存储] B2 --> C3[GQA/MLA 架构] B2 --> C4[分页与量化缓存] B3 --> C5[NPU 流式推理] B3 --> C6[算子融合与换入换出] C1 & C2 & C3 & C4 & C5 & C6 --> D[端侧可用的推理系统]

一、为什么算力早已不是瓶颈

先做一道简单的算术题。推理一个 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 成为手机的标配算力,云端与端侧的分界线正在被重新划定。

posted @ 2026-10-08 15:43  汤姆百宝箱  阅读(8)  评论(0)    收藏  举报