2026-09 · 27B 量级模型 + 200K 上下文 + 投机解码,同时挤在一张消费级卡上
卡的总量是 32607 MiB。一份 27B 的 6bit 量化权重就要吃掉约 20.6 GiB,剩下不到 11 GiB 要同时装下三样东西: KV 缓存、前向计算的中间缓冲、以及投机解码那个草稿模型自己的权重和缓冲。
| 项 | 占用 | 说明 |
|---|---|---|
| 主模型权重 | ≈ 20.6 GiB | Q6_K,全常驻显存 |
| KV 缓存 200K × 4 槽 | ≈ 7 GiB | K 与 V 都用 4bit 量化,且必须开 flash attention |
| 草稿模型权重 | ≈ 1.05 GiB | 换成 8bit 版本要多 0.87 GiB,见下文 |
| 计算中间缓冲 | 随草稿长度增长 | 草稿长度到 5 时这一项要再 1.08 GiB,直接分配失败 |
| 合计 | ≈ 31.3 / 32.6 GiB | 余量约 1.3 GiB |
多槽是为了让几个短请求同时跑。默认情况下每槽各自一份上下文窗口,200K × 4 是绝对放不下的; 打开 KV 统一池之后,四个槽共享同一个 200K 的池子,才勉强塞得进去。
代价也很实在:一个长请求会把池子占满,别的槽只能排队。实测把一个 100K 的请求和两个短请求同时发进去, 短请求的首字延迟到了 86 秒、吞吐掉到 7 tok/s。所以"支持并发"和"适合并发"是两回事。
减少槽数确实能换出显存(4 槽降到 1 槽省了约 2 GiB),我本来以为这能解锁更长的草稿从而更快, 实测反而更慢——省下来的显存不产生吞吐,而并发能力没了。
多模态模型除了语言主干还有一块"视觉投影器"(把图像特征映射成模型能吃的向量)。它要不要进显存由一个开关控制,
而这个开关的命名极其反直觉:--no-mmproj-offload 里的 "offload" 指的是"放进 GPU",
所以加了这个 flag 意味着投影器留在 CPU 上,那块几百 MB 到一 GB 多的文件根本不计入显存账单。
我第一次读反了,于是算出来的显存预算比实际多出一大块,配出来的参数在别的机器上"应该能跑"却起不来。 现在我的做法是:凡是语义可能读反的 flag,先查一下版本自己的帮助文本,再决定信不信自己的记忆。
留在 CPU 上的代价是可以量化的——同样的方法测不同尺寸图片的编码耗时:
| 输入 | prompt token | 服务端预填充耗时 | 端到端 |
|---|---|---|---|
| 纯文本对照 | 60 | 121 ms | 0.88 s |
| 256×256 图 | 126 | 286 ms | 1.04 s |
| 768×768 图 | 638 | 1.81 s | 2.74 s |
| 1536×1536 图 | 2366 | 12.61 s | 13.62 s |
按文本预填充的速率算,2366 个 token 只值 1.5–2 秒,也就是说那张大图里约 11 秒是 CPU 在做视觉编码。 小图完全无所谓,大图就是另一回事了。要不要拿 0.6 GiB 显存换掉这段时间,取决于余量——而我的余量只有 1.3 GiB, 草稿模型的计算缓冲随时要用,所以最后的选择是留在 CPU,并在入口侧限制图片尺寸。