在 RTX 4060 Laptop(8GB 显存)笔记本上部署 Qwen3.5-4B 和 Qwopus3.5-9B-Coder 的完整实战
2026 年上半年,阿里发布了 Qwen3.5 系列模型,社区也涌现了不少基于它的微调版本。我在 RTX 4060 Laptop(8GB 显存)笔记本上用 llama.cpp 部署了 Qwen3.5-4B 和 Qwopus3.5-9B-Coder 两个模型,测试了 64K 上下文的实际表现。这篇文章整理从选型、配置到性能测试的完整过程。
硬件环境
| 组件 | 规格 |
|---|---|
| CPU | i7-12650H(16 线程) |
| RAM | 15 GiB |
| GPU | RTX 4060 Laptop(8GB VRAM,compute 8.9) |
| llama.cpp | build 1,CUDA 后端 |
模型选择
两个目标:一个轻量模型做日常问答,一个专用模型做代码生成。
Qwen3.5-4B
阿里巴巴于 2026 年 2 月发布,Apache 2.0 协议。核心特点:
- 4B 参数,Dense 架构
- 采用 Gated Delta Networks + Gated Attention 混合架构,具体为 8×(3×DeltaNet→FFN→1×Attention→FFN)
- 32 层,hidden_dim=2560,16 attention heads,4 KV heads(GQA)
- 原生 262K 上下文,可扩展至 1M
- 支持 MTP(Multi-Token Prediction),包含 1 个预测头
- Q4_K_XL 量化后仅 2.85 GiB
选择理由:参数少、显存占用低、支持 MTP,适合做低延迟的实时交互场景。
Qwopus3.5-9B-Coder-MTP
社区基于 Qwen3.5-9B 架构的编程特化版本:
- 9B 参数
- 使用 Trace Inversion 数据增强和高质量 Agent Traces 微调
- 社区添加了 MTP 层,作者在 7900 XTX 上实测从约 80 t/s 提升到约 120 t/s
- 原生 32K 上下文,可扩展到 128K/256K
- Q4_K_M 量化后 5.51 GiB
选择理由:代码生成质量高、MTP 加速、显存刚好能装下。
llama-bench 基准测试
先用 llama-bench 跑标准参数,得到纯推理速度的基线:
1 | llama-bench -m model.gguf -ngl -1 -p 512 -n 128 |
| 测试项 | 4B GPU | 4B CPU | 加速比 | 9B GPU | 9B CPU | 加速比 |
|---|---|---|---|---|---|---|
| Prompt 处理 (pp512) | 2,998 t/s | 797 t/s | ×3.8 | 1,994 t/s | 702 t/s | ×2.8 |
| 文本生成 (tg128) | 69.0 t/s | 10.0 t/s | ×6.9 | 43.8 t/s | 6.9 t/s | ×6.3 |
GPU 模式下的生成速度差了约 7 倍,CPU 跑 10 t/s 以下交互体验会比较卡。
llama-server 配置优化
llama-bench 只是理论速度,实际使用需要启动 llama-server。以下是我的最终配置。
4B 模型(端口 45380)
1 | llama-server \ |
9B 模型(端口 45381)
1 | llama-server \ |
参数说明
| 参数 | 值 | 作用 |
|---|---|---|
-ngl |
-1 |
所有层加载到 GPU |
-c |
65536 |
64K 上下文窗口 |
-ctk / -ctv |
q8_0 |
KV cache 用 8-bit 量化,每条 token 约 27.5KB 开销 |
--spec-type |
draft-mtp |
启用 MTP 推测解码 |
--spec-draft-type-k/v |
q8_0 |
MTP 草稿模型的 KV cache 也量化(默认 f16,显性设能省显存) |
-fa |
on |
强制启用 Flash Attention,减少中间缓冲 |
-t |
8 |
8 个 CPU 线程(16 线程的 i7 用一半,留余量给系统) |
-np |
1 |
单槽位,避免多 slot 抢占上下文 |
MTP 草稿 cache 默认是 f16,不显式声明会浪费不少显存。这是实际测试中发现的第一个坑。
实际文本性能测试
用 llama-server 的 /completion API 跑了三类场景,每个场景先预热一次再计时。
4B 模型
| 测试 | Prompt | PP t/s | 生成 | TG t/s | MTP 接收 | 耗时 |
|---|---|---|---|---|---|---|
| 简短问答 | 8 tok | 121.4 | 128 tok | 84.5 | 76/153 (50%) | 1.6s |
| 代码生成 | 26 tok | 379.7 | 256 tok | 100.9 | 170/252 (67%) | 2.6s |
| 长上下文 | 552 tok | 2,306.1 | 256 tok | 93.6 | 164/271 (61%) | 3.0s |
| 平均 | - | 935.7 | - | 93.0 | ~68% | - |
9B Code 模型
| 测试 | Prompt | PP t/s | 生成 | TG t/s | MTP 接收 | 耗时 |
|---|---|---|---|---|---|---|
| 简短问答 | 8 tok | 63.3 | 128 tok | 37.6 | 74/157 (47%) | 3.6s |
| 代码生成 | 26 tok | 118.9 | 256 tok | 48.8 | 174/238 (73%) | 5.5s |
| 长上下文 | 552 tok | 1,235.1 | 256 tok | 43.5 | 166/262 (63%) | 6.3s |
| 平均 | - | 472.4 | - | 43.3 | ~69% | - |
MTP 加速效果
与 llama-bench 的纯推理速度对比,MTP 在实际应用中带来了明显的提升:
| 模型 | llama-bench | 实际加速后 | 提升 |
|---|---|---|---|
| 4B | 69.0 t/s | 93.0 t/s | +35% |
| 9B | 43.8 t/s | 43.3 t/s | – |
4B 提升显著,9B 持平的原因是 llama-server 基础开销更大,MTP 主要用于抵消这部分损失。MTP 接受率约 68-69%,即每个 draft 周期预测 3 token 约命中 2 个。
64K 上下文显存分析
通过对比不同 -c 设置下的 VRAM 占用(启动后不跑任何请求),量化了各组件的分配:
4B + q8_0 cache
| 上下文长度 | VRAM 占用 | 增量 |
|---|---|---|
| 4K | 3,545 MiB | - |
| 16K | 3,883 MiB | +338 MiB |
| 32K | 4,381 MiB | +498 MiB |
| 64K | 5,377 MiB | +996 MiB |
每 token KV 开销约 27.5 KiB(q8_0)。
9B + q8_0 cache
| 上下文长度 | VRAM 占用 | 增量 |
|---|---|---|
| 4K | 5,711 MiB | - |
| 16K | 5,879 MiB | +168 MiB |
| 32K | 6,233 MiB | +522 MiB |
| 64K | 6,554 MiB | +843 MiB |
每 token KV 开销约 13.7 KiB。
VRAM 分布(64K 上下文)
| 组件 | 4B + q8_0 | 9B + q8_0 |
|---|---|---|
| 模型权重 + MTP 头 | ~3,433 MiB | ~5,711 MiB |
| KV cache(64K) | ~1,832 MiB | ~914 MiB |
| CUDA 缓冲 / 工作区 | ~112 MiB | ~-71 MiB (fitting 压缩) |
| 总计 | 5,377 MiB | 6,554 MiB |
| 空闲 | 2,459 MiB | 1,281 MiB |
KV cache 是预分配的
一个值得注意的发现:llama.cpp 的 KV cache 是启动时一次性预分配的,而非按需动态增长。
验证方法:启动 64K 上下文的服务器,分别发送 0 token、500 token、10K token 的请求,VRAM 始终保持 5,377 MiB 不变(±30 MiB 测量误差)。如果用 -c 4096 启动,VRAM 直接降到 3,545 MiB。
换句话说,-c 的值直接决定显存占用,和实际用了多少上下文无关。这个设计的代价是启动时就必须留出全部缓存空间,好处是运行期间不会有内存碎片或 OOM 的风险。
踩坑记录
这里记录几个实际调试中遇到的问题。
坑一:MTP draft cache 默认是 f16
默认配置下 MTP 草稿模型的 KV cache 为 f16,比 q4_0/q8_0 精度的草稿缓存多用不少显存。必须显式设置 --spec-draft-type-k 和 --spec-draft-type-v。
坑二:n_parallel=auto 反而省显存
-np auto(自动判断为 4 slots + unified KV)在某些配置下比 -np 1 的 VRAM 更低,因为 fitting 算法在多头共享缓存池时会更积极压缩工作缓冲区。实际用户场景建议还是设 -np 1。
坑三:9B 模型的 Gated Delta Net 警告
启动 9B 模型时出现 fused Gated Delta Net not supported,这个层被迫跑在 CPU 上。不影响正常使用,但说明 CUDA 后端对该架构的支持还不完善。
坑四:显存够用时 q8_0 和 q4_0 的差异不大
实测 9B 模型 q4_0(6,624 MiB)和 q8_0(6,554 MiB)的最终 VRAM 几乎一样,因为 llama.cpp 的 fitting 算法会自适应调节工作缓冲区。有显存余量就上 q8_0,精度更好。
总结
| 结论 | 数据 |
|---|---|
| 8GB 显存能跑 9B + 64K 上下文 | 6,554 MiB / 7,834 MiB |
| 4B 生成 93 t/s | 响应几乎无延迟 |
| 9B 代码生成 43 t/s | 编码对话完全流畅 |
| MTP 实际加速 30-50% | 接受率 ~68% |
| KV cache 预分配 | -c 设置决定一切 |
两个模型定位清晰:4B 做日常快速问答,9B Coder 做代码生成。8GB 显存虽然只能同时跑一个,但切换成本很低,配合不同的 API 端口可以随时切换。
核心教训是 MTP 的几个配置项(草稿 cache 量化、n_max、draft 预测头)对实际体验影响很大,值得花时间调。llama.cpp 的 fitting 算法也是一把双刃剑——它帮你省显存,但也让调参的反馈变得不直观,建议每次只改一个参数做 A/B 对比。


