一张写着30 tok/s的成绩表,解释不了手机端推理的真实体验。模型连续跑20分钟后还剩多少速度、背壳到几度、占掉多少内存,才决定它能不能放进产品。
这组测试记录来自2026年7月,设备是骁龙8 Gen5参考设计机和iPhone 17 Pro Max,模型为Llama 3.2 7B与Mistral Small 12B。原选题覆盖7B—14B和手机、iPad,但本轮没有14B及iPad数据,结果不作外推。
以下数据是样机在指定软件版本下的测试记录,不是芯片厂商的官方标称。框架、驱动和散热条件变化后,结果也可能变化。
位宽先决定模型能不能装下
按权重位宽粗算,INT4占用约为FP16的四分之一,INT8和FP8约为FP16的一半。放到7B模型上,FP16约14GB,INT8或FP8约7GB,INT4约3.5GB。
这只是权重体积。实际运行时的峰值内存会更高,表格中的Llama 3.2 7B INT4分别测到3.8GB和3.5GB,部署时不能只按模型文件大小预留空间。
《四种主流精度的量化算法选型与实战策略》提到,INT4将显存占用压缩至FP16的四分之一,常见做法是per-group Min-Max,group size设为128。4-bit留给误差的空间很小,离群值处理和分组方式都会影响结果。不同数值精度的基础概念,可参考53AI的量化科普。
测试条件
- 硬件:骁龙8 Gen5参考设计机,Adreno 850 GPU;iPhone 17 Pro Max,A19与16核ANE
- 模型:Llama 3.2 7B指令版、Mistral Small 12B指令版
- 格式:INT4使用Q4_K_M,INT8使用Q8_0,FP8使用对应的FP8类型
- 框架:Android端为llama.cpp,commit b3272;iOS端为MLX 0.20.0
- 速度测试:连续生成512 tokens,重复5次取平均
- 温度测试:室温25℃,记录持续运行20分钟后的背壳最高温
速度项只统计自回归生成,不含prefill。因此,这张表适合比较持续生成能力,不能直接代表首字等待时间。测试记录中,A19设备的FP8由MLX调用,并通过Core ML委托至ANE。
INT4在骁龙上优势最直接,FP8更适合A19
| 芯片 | 模型 | 量化 | 生成速度(tok/s) | 峰值内存(GB) | 20分钟背壳温度(℃) |
|---|---|---|---|---|---|
| 骁龙8 Gen5 | Llama 3.2 7B | INT4 | 30.2 | 3.8 | 41 |
| 骁龙8 Gen5 | Llama 3.2 7B | INT8 | 18.5 | 7.2 | 47 |
| 骁龙8 Gen5 | Llama 3.2 7B | FP8(GPU) | 24.1 | 7.0 | 44 |
| 骁龙8 Gen5 | Mistral Small 12B | INT4 | 16.8 | 6.4 | 43 |
| 骁龙8 Gen5 | Mistral Small 12B | INT8 | 10.3 | 12.1 | 50 |
| 骁龙8 Gen5 | Mistral Small 12B | FP8(GPU) | 14.2 | 11.8 | 46 |
| A19(ANE) | Llama 3.2 7B | INT4(MLX) | 35.1 | 3.5 | 39 |
| A19(ANE) | Llama 3.2 7B | INT8(MLX) | 22.3 | 6.9 | 44 |
| A19(ANE) | Llama 3.2 7B | FP8(ANE) | 33.0 | 6.8 | 41 |
| A19(ANE) | Mistral Small 12B | INT4(MLX) | 19.4 | 6.1 | 41 |
| A19(ANE) | Mistral Small 12B | INT8(MLX) | 12.7 | 11.8 | 47 |
| A19(ANE) | Mistral Small 12B | FP8(ANE) | 18.5 | 11.6 | 43 |
在骁龙8 Gen5上,INT4不是小幅领先。Llama 3.2 7B从INT8的18.5 tok/s提高到30.2 tok/s,峰值内存由7.2GB降到3.8GB,20分钟背壳温度也从47℃降到41℃。Mistral Small 12B的方向一致:INT4为16.8 tok/s和43℃,INT8只有10.3 tok/s,温度达到50℃。
FP8在骁龙上的表现处于两者之间。Llama 3.2 7B测到24.1 tok/s、44℃;Mistral Small 12B为14.2 tok/s、46℃。它没有INT4省内存,但速度和温度都好于本轮INT8结果。
A19上的取舍不同。Llama 3.2 7B使用FP8时为33.0 tok/s,接近INT4的35.1 tok/s;Mistral Small 12B分别为18.5和19.4 tok/s。代价是内存:两组FP8峰值分别为6.8GB和11.6GB,INT4则为3.5GB和6.1GB。
本轮MMLU对比中,FP8相对基线的分差小于0.5%,INT4为2%—3%。这个结果只能说明本次测试集上的差距,代码生成、知识问答等任务仍要用业务样本单独检查。
短跑快不够,降频要单独看
骁龙8 Gen5运行INT8时,约15分钟后出现GPU降频,瞬时生成速度从20+ tok/s降到14 tok/s。速度下降后,背壳温度也随之回落,不能把温度降低单独理解为散热表现更好。INT4在同一轮持续负载中没有出现这类明显掉速。
这也是端侧测试容易漏掉的一项:只跑几十秒,看到的是峰值;真正连续生成、做长对话或批量处理时,芯片是否降频往往比最初快两三个tok/s更重要。
llama.cpp和MLX配置
Android端使用llama.cpp b3272。下面保留本次测试中的量化配置片段,完整参数应以对应版本的帮助信息为准。
./quantize llama-3.2-7b-f16.gguf Q4_K_M llama-3.2-7b-q4_k_m.gguf
推理时选择对应的计算类型:
ggml_type compute_type = GGML_TYPE_Q4_K_M; // INT4
// 也可选择 GGML_TYPE_Q8_0 或 GGML_TYPE_FP8
FP8需要在编译时开启:
-DGGML_USE_FP8
模型加载时再选择GGML_TYPE_FP8。测试环境中,如果硬件不支持FP8计算,该路径会回退,因此比较成绩前要先确认实际使用的后端。
iOS端使用MLX 0.20.0,加载量化后的safetensors,并在模型配置中指定分组和位宽:
import mlx.core as mx
model = load_model('mlx_model')
model.quantize(group_size=128, bits=4) # INT4
INT8将bits改为8;FP8使用mx.float8。本次A19环境没有增加额外的ANE配置,MLX直接使用对应的FP8执行路径。
怎么选,先看设备最缺什么
内存紧,或者持续温度更重要,先测INT4。 本轮两颗芯片上的INT4都占用最少,背壳温度也最低。对话、离线助手和需要连续生成的功能,可以先用INT4建立可运行版本,再检查量化后的回答质量。
设备确实支持FP8,而且业务更怕量化误差,可以试FP8。 A19上的FP8速度已经接近INT4,本轮MMLU分差也更小,但内存占用接近INT8。选择它的前提不是配置文件里写了FP8,而是运行时确实走到了对应硬件后端。
硬件支持情况不明确时,把INT8留作兼容基线。 它的内存和温度表现不占优势,但实现相对直接。若FP8发生回退,先与INT8比较,通常比直接套用其他设备的成绩更可靠。
离线功能还要考虑网络本身。《生产环境中的端侧LLM推理》举过一个直观例子:本地以15 tok/s运行的7B模型,仍比断网时无法返回的云端API有用;打字助手、搜索补全和实时翻译这类同步功能中,200毫秒网络往返已经会带来明显卡顿。
上线前还应补三项检查:用llama.cpp --perplexity比较量化前后的困惑度;拿真实业务提示词复测,而不是只看MMLU;把同一负载跑满20分钟,记录降频后的速度。若关心首字延迟,还要另测prefill,因为它不在本轮速度数据里。
这组数据给出的起点很清楚:骁龙8 Gen5上优先考虑INT4;A19设备内存足够时,把FP8放进同任务复测;INT8更适合作为兼容基线。最后决定版本的,不该是峰值速度,而是模型在目标设备上持续运行后的速度、温度和回答质量。