先说结论:
- 24G 卡追求质量:Q8SLIM,22.3 GiB 全进显存,29 tok/s,这是 7900XTX 上能摸到的最高参数规格。
- 24G 卡追求速度:IQ4_XS,39.6 tok/s,质量验证全过,日常用体感和 Q4_K_M 没区别。
- 质量底线:IQ2_XXS(8.1 GiB),再往下 IQ1_S 数学就崩了。
- 8G 卡:27B 纯属超纲,IQ1_S 能跑但别指望质量,真想跑 27B 老老实实上 16G 以上显存。
- MTP 必开:特别是部分卸载场景,65% 的提速不要白不要。
现在开源模型更新得太快了,前脚刚把一个 27B 玩明白,后脚新版又出来了。这回看上的是 ModelScope 上面的 Qwen3.8-27B。这个模型有点意思:它是多模态架构,官方标识的 model_type 是 qwen3_5,内部结构是 linear_attention 和 full_attention 交替混搭的,一共 64 层主干,外带一层 MTP(Multi-Token Prediction,多 token 预测)。而且它原生就带了 MTP 权重,这对后面提速很关键,咱后面细说。
手头两块卡:一块 AMD 7900XTX,24G 显存;一块 NVIDIA RTX 4070,8G 显存。这回就把这个模型从 f16 一路量化到 IQ1_S,十三个版本全做出来,每个都验证 MTP 层还在不在,大于 8G 的挨个在 7900XTX 上跑,小于 8G 的丢给 4070,速度和答案正确性都验一遍。下面把整个流程和坑都摊开讲讲。
一、先把模型弄下来
模型地址是 https://modelscope.cn/models/Qwen/Qwen3.8-27B,下载直接走 ModelScope 是最省事的,用它的 SDK 就行。这里我下载的路径在 C:/Users/frede/models/Qwen3.8-27B,后面代码示范都是这个目录。
from modelscope import snapshot_download
snapshot_download('Qwen/Qwen3.8-27B', local_dir='C:/Users/frede/models/Qwen3.8-27B')
原始权重是 18 个 safetensors 分片,总共 52G 左右,下了差不多四个小时。这里提醒一句,网络不稳的话别用多线程下载器硬抢,单线程流式反而稳,断了能接着续。
二、转成 GGUF
llama.cpp 的转换脚本直接用:
python convert_hf_to_gguf.py C:/Users/frede/models/Qwen3.8-27B --outtype f16 --outfile Qwen3.8-27B-f16.gguf
出来一个 50.9 GiB 的 f16 GGUF,866 个张量。这里有个值得注意的点:转换完之后我专门检查了一下张量列表,发现 blk.64.nextn.* 这一组的四个张量都在——这就是 MTP 层,第 65 层(编号 64)专门用来预测未来 token 的。转换脚本没有把它扔掉,这意味着后面所有量化版本理论上都能保留投机解码的能力。
三、量化阶梯:一口气做十三个
量化用 llama-quantize,普通 K 系量化(Q8_0、Q6_K、Q5_K_M、Q4_K_M、Q3_K_M)直接从 f16 转就行。但 IQ 系列(IQ4_XS、IQ3_XS、IQ2_M、IQ2_XS、IQ2_XXS、IQ1_S)不一样,它们是重要性矩阵量化,必须先算 imatrix。
算 imatrix 得有校准语料。我把自己博客上三百七十篇文章拼在一起,凑了 2MB 的 calib.txt,肥水不流外人田,用自己的语料校准自己的模型,语义分布也对付了。这里参考意义就不大了,大家到时候自行探索。
# 先用 Q5_K_M 跑 imatrix(256 个 chunk)
llama-imatrix -m Qwen3.8-27B-Q5_K_M.gguf -f calib.txt -o imatrix.gguf -ngl 15 -c 512 -b 256 --chunks 256
# 带 imatrix 的量化
llama-quantize --imatrix imatrix.gguf Qwen3.8-27B-f16.gguf Qwen3.8-27B-IQ4_XS.gguf IQ4_XS
最后做出来的完整阶梯长这样(全部验证过包含 MTP 层):
| 量化版本 | 体积 | 说明 |
|---|---|---|
| f16 | 50.9 GiB | 源文件 |
| Q8_0 | 27.0 GiB | 8.50 BPW,超过 24G 显存 |
| Q8SLIM | 22.3 GiB | 混合量化,见下文 |
| Q6_K | 20.9 GiB | |
| Q5_K_M | 18.2 GiB | 5.72 BPW |
| Q4_K_M | 15.7 GiB | 4.92 BPW |
| IQ4_XS | 14.3 GiB | imatrix |
| Q3_K_M | 12.6 GiB | 3.95 BPW |
| IQ3_XS | 11.4 GiB | imatrix |
| IQ2_M | 9.5 GiB | imatrix |
| IQ2_XS | 8.7 GiB | imatrix |
| IQ2_XXS | 8.1 GiB | imatrix |
| IQ1_S | 6.9 GiB | imatrix |
IQ1/IQ2 的一个坑
第一次做 IQ2 和 IQ1 的时候直接报错退出,提示缺少重要性矩阵。查了半天才发现根因:算 imatrix 的时候模型是普通模式跑的,MTP 那层(blk.64)根本没被执行过,所以 imatrix 里没有它的数据。而 IQ1、IQ2 这种极低比特量化是强制要求每个张量都有重要性数据的,没有就罢工。
解法很简单,把 blk.64 单独指成 Q4_K,K 系量化不需要 imatrix:
llama-quantize --imatrix imatrix.gguf --tensor-type "blk.64=Q4_K" f16.gguf out-IQ1_S.gguf IQ1_S
这样 MTP 层用 Q4_K 保真,主干用 IQ1_S 压缩,两不耽误。
四、Q8 塞不进 24G 怎么办:Q8SLIM
周总跟我说 Q8_0 在 7900XTX 上跑没问题。但我自己转换的纯 Q8_0 是 27 GiB,24G 的卡物理上就装不下。之前试过各种层拆分(-ngl 62、54、52)全都 Vulkan DeviceLost,只有 -ngl 50 勉强稳定但只剩 2.5 tok/s,没啥实用价值。
所以我选择的做法是混合量化:注意力部分保 Q8_0,FFN 降到 Q6_K,词表嵌入压到 Q4_K,输出层给 Q6_K:
llama-quantize --token-embedding-type Q4_K --output-tensor-type Q6_K \
--tensor-type "ffn_=Q6_K" f16.gguf Q8SLIM.gguf Q8_0
出来 22.3 GiB(6.99 BPW),整卡装下还有富余。质量上注意力这种对精度最敏感的部分还是 Q8,FFN 这些大块头降一档,体感损失很小。实测 29.1 tok/s,两道验证题全对。这大概就是我这张 7900XTX 24G 卡上能跑的最高质量档。
五、7900XTX 大阅兵
10 个超过 8G 的版本挨个上,Ollama 走 ROCm 后端,但怕爆显存就只设置了 8k 上下文,temperature 0,每档跑两道固定题:一道数学(17×23),一道代码(写斐波那契函数)。
| 模型 | 速度 | 数学 | 代码 |
|---|---|---|---|
| Q8SLIM | 29.1 tok/s | 对 | 对 |
| Q6_K | 29.4 tok/s | 对 | 对 |
| Q5_K_M | 30.9 tok/s | 对 | 对 |
| Q4_K_M | 32.8 tok/s | 对 | 对 |
| IQ4_XS | 39.6 tok/s | 对 | 对 |
| Q3_K_M | 32.9 tok/s | 对 | 对 |
| IQ3_XS | 31.1 tok/s | 对 | 对 |
| IQ2_M | 32.0 tok/s | 对 | 对 |
| IQ2_XS | 32.2 tok/s | 对 | 对 |
| IQ2_XXS | 32.6 tok/s | 对 | 对 |
几个观察:
- IQ4_XS 是速度之王,39.6 tok/s 一骑绝尘,比 Q4_K_M 快了 20%。原因不复杂:IQ4_XS 是 4 BPW 出头,比 Q4_K_M 的 4.92 BPW 小了 1.4G,全部塞进显存之后剩余空间更宽裕,而且 IQ 系列的内存访问模式在显存带宽吃紧的时候更有优势。
- Q8SLIM 和 Q6_K 这两个大块头反而最慢(29 出头),大概是因为太大,显存基本塞满了,KV cache 的空间也吃紧。
- IQ2_XXS 居然还能全对,8.1 GiB 的 27B 模型,质量崩塌的临界点比想象中低。
- 中间有个小插曲:Q6_K 第一次测出来只有 1.3 tok/s,吓一跳。后来发现是前一个测试的模型没卸载干净,显存被占了一半。清掉重测就是正常的 29.4。跑批量测试的时候,每个模型测完记得 keep_alive=0 卸载,不然数据全是坑。
六、4070 接力:IQ1_S 和质量底线
小于 8G 的只有 IQ1_S(6.9 GiB),扔给 4070。8G 显存里有 1G 多被桌面占着,实际可用 6.8G 左右,无奈,只能用 -ngl 55 把大部分层放上去,剩下留 CPU:
| 测试 | 速度 | 数学 |
|---|---|---|
| IQ1_S 基线 | 5.4 tok/s | 错(340+51 算成 370) |
| IQ1_S + MTP | 6.5 tok/s | 错(同基线) |
| Q5_K_M -ngl 15 | 1.9 tok/s | 对 |
| Q5_K_M -ngl 15 + MTP | 3.2 tok/s | 对 |
IQ1_S 就是质量断崖。1.68 BPW 的比特率,27B 模型的数学能力直接崩了,340 加 51 能给你写成 370。所以说这代的可用底线是 IQ2_XXS,IQ1 系列只能算"能出字",不能算"能用"。
顺带一提,Q5_K_M 在 8G 卡上属于超载运行,18G 的模型只塞进去 15 层,剩下全靠内存和 CPU,1.9 tok/s 咬牙能用。这卡跑 27B 本来就是超纲题。
七、MTP 投机解码:白捡的加速
这个模型原生带 MTP 层,llama.cpp 用 --spec-type draft-mtp 就能启用。原理粗略来讲:普通自回归是猜一个 token 验证一个,MTP 相当于模型自带一个小抄,一次猜好几个,主模型批量验证,猜中的直接收下,猜错的回滚。猜中率越高,加速越明显。
实测数据:
- IQ1_S(4070):5.4 → 6.5 tok/s,提速 20%
- Q5_K_M(4070,部分卸载):1.9 → 3.2 tok/s,提速 65%
部分卸载场景提速更显著,可能是因为瓶颈在 CPU 内存带宽,一次验证多个 token 等于把宝贵的带宽利用率拉满了。而且开了 MTP 之后输出和基线完全一致——这是投机解码的数学性质保证的,猜错会回滚,最终结果和逐 token 生成一模一样,纯粹是白捡的速度。
温度为 0 的时候接受率最稳。温度拉高之后输出随机性变大,草稿和主模型容易对不上,加速效果会打折扣,这个要有心理预期。
八、这一路踩的坑
- 官方 Windows 二进制好像是有 bug。llama.cpp b10405 和 b10435 的官方 Windows release,在回调路径(cb_eval)上有堆损坏,llama-imatrix 跑任何模型任何后端都会在第一个 decode 静默崩掉,exit code 0xC0000374;开 draft-mtp 的 llama-cli 也崩。解决办法是自己编译:本机 VS18 Community 加 CMake,注意必须用 Ninja 生成器,VS 自带生成器会报 "No CUDA toolset found"。自建的版本一切正常。
- 链式量化别接管道。第一次批量量化的时候,输出接了
grep | head,管道提前关闭触发 SIGPIPE,把 IQ3_XS 的文件头截断了,GGUF magic 都没了。量化这种长任务老老实实写日志文件,我整不明白就暂时先不接管道了。 - Vulkan 崩了可能是驱动问题但也别慌。AMD 的 Vulkan 后端偶发 DeviceLost,恢复套路是固定的:taskkill 杀光所有 llama 进程,等 10 秒再启动,基本就能活过来。
- llama-cli 单轮测试用
-st。不带这个参数它会进对话模式,后台跑的时候没人交互,就死循环打印提示符,日志能给你写几百兆。另外后台跑一定要> /dev/null。
九、简单总结
- 24G 卡追求质量:Q8SLIM,22.3 GiB 全进显存,29 tok/s,这是 7900XTX 上能摸到的最高画质。
- 24G 卡追求速度:IQ4_XS,39.6 tok/s,质量验证全过,日常用体感和 Q4_K_M 没区别。
- 质量底线:IQ2_XXS(8.1 GiB),再往下 IQ1_S 数学就崩了。
- 8G 卡:27B 纯属超纲,IQ1_S 能跑但别指望质量,真想跑 27B 老老实实上 16G 以上显存。
- MTP 必开:特别是部分卸载场景,65% 的提速不要白不要。
一轮折腾下来,本地盘上躺了 268 GiB 的模型文件。可能觉得折腾这些不如直接调 API,但自己量化、自己测速、自己找到那个"再压一档就崩"的临界点,这个过程对模型和硬件的理解是租 API 很难提供的乐趣。下一次出新卡或者新模型,这套流程直接照搬就行,几个小时就能摸清楚它的底细。