INT4量化实战:把7B模型塞进手机,踩坑全记录
上周把 Llama 3.1 8B 做了 INT4 量化,装进 iPhone 15 Pro 跑推理。过程挺曲折,把踩的坑都记下来。
# INT4量化实战:把7B模型塞进手机,踩坑全记录
上周把 Llama 3.1 8B 做了 INT4 量化,装进 iPhone 15 Pro 跑推理。过程挺曲折,把踩的坑都记下来,给想端侧落地的兄弟避避雷。
为什么要 INT4
FP16 的 7B 模型权重占 14GB,手机直接炸。INT8 能压到 7GB 左右,勉强跑但推理速度慢得感人。INT4 能把权重压到 3.5GB,这在大多数手机上是可行的。代价是精度损失——但实测下来,对于大多数日常问答场景,INT4 和 FP16 的输出几乎无差别。
工具选型:llama.cpp 还是 MLX?
llama.cpp(跨平台首选)
llama.cpp 的 GGUF 格式是目前生态最成熟的方案。量化脚本 quantize 支持多种方法:
# Q4_K_M:质量与体积的最佳平衡点
./llama-quantize input.gguf output-q4_k_m.gguf Q4_K_M
# Q4_0:最老的量化方式,兼容性最好但效果一般
./llama-quantize input.gguf output-q4_0.gguf Q4_0
# Q5_K_M:质量接近 Q6_K,体积却接近 Q4
./llama-quantize input.gguf output-q5_k_m.gguf Q5_K_M
量化后的对比数据(Llama 3.1 8B):
MLX(Apple Silicon 专属)
如果你只跑在 Apple 设备(Mac/iPhone/iPad)上,MLX 的量化体验更丝滑:
import mlxlm
# 直接量化并导出
mlxlm.convert(
"meta-llama/Llama-3.1-8B-Instruct",
mlx_path="./llama-8b-mlx",
quantize=True,
q_group_size=32, # INT4 推荐 32
q_bits=4 # 4-bit 量化
)
MLX 的亮点是支持 dynamic dispatch——模型按层拆分到不同设备(CPU/GPU/Neural Engine),不需要你手动配置。
踩坑记录
坑1:量化后回答质量暴跌
最开始我用 Q2_K 量化,结果模型开始胡言乱语。Q2 级别的量化会严重破坏模型的注意力分布。**经验法则:不要低于 Q3_K_M**,日常使用 Q4_K_M 足矣。
坑2:手机上跑起来发热爆炸
iPhone 15 Pro 跑 Q4_K_M 量化模型,30 秒后机身温度明显上升,降频导致推理速度从 18 tok/s 掉到 8 tok/s。解决方法:
# 限制并发线程数,避免满载
./llama-cli -m model.gguf -c 2048 -ngl 35 --threads 4
# -ngl 控制 GPU 加载层数,iPhone 建议 30-35 层
坑3:KV Cache 溢出
手机端上下文窗口不能设太大。默认 4096 在 8GB RAM 手机上跑会 OOM。**改成 2048 或 1024**,虽然能记住的上下文少了,但至少不崩。
坑4:中文表现比英文差
Q4 量化对多义词和中文理解的影响更大。如果你的场景主要是中文对话,建议用 Q5_K_M 或 Q6_K,多花 1-2GB 体积换来明显的质量提升。
推荐方案
| 场景 | 推荐配置 |
|------|----------|
| iPhone 日常对话 | MLX Q4_K_M,上下文 2048 |
| Android 端侧推理 | llama.cpp GGUF Q4_K_M |
| Mac 本地开发 | MLX Q5_K_M,上下文 8192 |
| 追求极限速度 | Q3_K_M + 限制上下文 1024 |
最后说两句
端侧量化的核心矛盾就是:体积 vs 质量 vs 速度,三者只能选其二。INT4 是目前比较中庸的选择——比 FP16 快 3 倍,体积缩小 4 倍,质量损失在可接受范围内。等你把模型真正塞进手机后,会发现发热和内存管理才是真正的挑战。
如果你们也在做端侧部署,欢迎交流踩坑经验。