这篇记录 Qwen3.6 27B 大模型全本地跑通的完整过程。目标一句话:27B 参数模型,全本地,长上下文,暴露 OpenAI 兼容 API,任何前端(包括 DeepSeek Harness 本身)直接对接。
最终结果:
- Qwen3.6-27B UD-Q5_K_XL(18.95 GB)+ 138K 上下文 + KV 缓存量化 → 32GB 显存刚好装下
- 同一条流水线后来延伸到 Qwen3.8-27B:Q4_K_XL + MTP 投机解码 + 256K 上下文,实测占用 26077 / 32768 MiB
下面就是完整搭建流程。所有参数都来自实际在跑的脚本,不是理论最优值。
一、硬件与驱动
| 项 | 实际值 |
|---|---|
| GPU | Tesla V100-PCIE-32GB(TCC 模式) |
| 驱动 | 573.96(Data Center Tesla 桌面版) |
| CUDA | 12.8(cuda_12.8.0_571.96_windows) |
| 系统 | Windows 10/11 |
两个坑:
1. V100 不能用 GeForce 消费级驱动。 要用数据中心分支,安装包文件名里带 data-center-tesla(我本地留了份:573.96-data-center-tesla-desktop-win10-win11-64bit-dch-international.exe)。
2. TCC 模式没有桌面显示输出。 V100 是纯计算卡,看屏幕靠核显,状态全靠 nvidia-smi。写这篇时的实况(节选):
| 0 Tesla V100-PCIE-32GB TCC 75C 51W / 250W
| 26077MiB / 32768MiB
| 进程: llama-server.exe 26066MiB
二、编译 CUDA 版 llama.cpp
我保留两套 llama.cpp:
F:\AI\llama.cpp-CUDA\— CUDA 后端(给 V100)F:\AI\llama.cpp\— Vulkan 后端(更早的 AMD RX 590 8G 在用)
CUDA 版用 VS2022(MSVC 19.44)+ CUDA 12.8 工具链编译,当前在产 build:
version: 0.1.0-dev (build 10415, commit 1d2869c6e)
built with MSVC 19.44.35228.0 for x64
CMake 关键参数:
cmake -B build -G "Visual Studio 17 2022" -A x64 ^
-DGGML_CUDA=ON ^
-DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release -j
所有启动脚本都会先检查 Release\llama-server.exe 是否存在,缺了就直接提示先编译,避免"启动失败但不知道为什么"。
三、模型选择:27B 为什么"装得下"
手头的模型文件(实测大小):
| 模型 | 大小 | 备注 |
|---|---|---|
| Qwen3.6-27B-Q4_K_M.gguf | 15.93 GB | 常规 K 量化 |
| Qwen3.6-27B-UD-Q5_K_XL.gguf | 18.95 GB | Unsloth 动态量化(本文主角) |
| Qwen3.8-27B-UD-Q4_K_XL.gguf | 16.69 GB | 当前生产主模型 |
| Qwen3.8-27B-Q5_K_M.gguf | 18.47 GB | |
| Qwen3.8-27B-UD-Q6_K_XL.gguf | 23.56 GB | 高质量档(偏重) |
| mtp-Qwen3.8-27B-Q4_0.gguf | 1.28 GB | MTP 投机解码草稿 |
3.6 为什么选 UD-Q5_K_XL:UD(Unsloth Dynamic)量化用 imatrix 校准数据动态分配 bit,关键张量多给、不重要的少给,同等名义 5 bit 下质量比固定 Q5_K_M 好。imatrix 校准文件(imatrix_unsloth.gguf)就放在模型目录里。
但 27B 长上下文能上 32G 的关键不是量化,是架构。 我写了个小脚本解析 GGUF v3 元数据(解析器在 novel-project/tools/gguf-meta.py,顺带解决了 v3 格式 KV 区紧跟文件头、字符串长度用 u64 编码的坑),结果有点意外:
general.architecture = qwen35
qwen35.block_count = 65
qwen35.full_attention_interval = 4 # 每 4 层才 1 层全注意力
qwen35.attention.head_count_kv = 4 # GQA,4 个 KV 头
qwen35.attention.key_length = 256 # head 维度
qwen35.context_length = 262144 # 原生 256K
qwen35.nextn_predict_layers = 1 # 内置 MTP 层
qwen35.ssm.state_size = 128 # 线性注意力/SSM 状态
也就是说 Qwen3.x-27B 系列是混合架构:65 个 block 里只有 1/4 是全注意力(约 17 层),其余是线性注意力/SSM,状态大小固定、不随上下文增长。KV 缓存只给那 17 层全注意力层分配——这是 256K 上下文能塞进 32GB 的根本原因。
四、显存预算(全部真实数字)
KV 缓存容量公式(q4_0 量化约 4.5 bit/元素,0.5625 B/元素):
KV = 2(K+V) × ctx × 4(KV头) × 256(head维) × 0.5625B × 17(全注意力层)
256K 代入:单层 KV ≈ 288 MiB,17 层合计 ≈ 4.8 GB;若不做 KV 量化(fp16),同样 256K 要 17 GB。
| 项 | Q3.8 Q4_K_XL @256K(实测) | Q3.6 Q5_K_XL @138K(估算) |
|---|---|---|
| 模型权重 | 16.69 GB | 18.95 GB |
| KV 缓存(q4_0) | ≈4.8 GB | ≈2.6 GB |
| SSM 状态 + 激活 + 计算缓冲 | ≈4.0 GB(实测余量) | ≈4.0 GB(参照) |
| 合计 | ≈25.5 GB → 实测 26077 MiB | ≈25.6 GB,还能开 –parallel 2 |
实测与估算吻合,这套预算方法是可信的。两个结论:
--flash-attn on+--cache-type-k q4_0 --cache-type-v q4_0是长上下文的两个必选项,缺一个 256K 都悬。- Q6 + 256K 不成立:光权重就 23.56 GB,我的 Q6 脚本 batch 只能压到 256。要质量降上下文,要上下文降量化,二选一。
五、启动脚本(真实演进过程)
早期是 Vulkan 时代(RX 590 8G),部分层卸载到 GPU:
:: 历史配置:RX 590 8G Vulkan 版
llama-server -m Qwen3.6-27B-Q4_0.gguf -ngl 24 --n-cpu-moe 999 ^
-c 4096 -b 1024 -ub 512 -t 6 --device Vulkan0 --cache-ram 2048 --mlock
-ngl 24 只把 24 层推 GPU,其余吃 CPU;--n-cpu-moe 999 是 35B-A3B MoE 模型时代抄过来的,对稠密 27B 实际不生效——无害但误导,后来删掉了。
V100 到位后配置重写:99 层全上 GPU,上下文从 4K 拉到 138K:
:: start_Qwen3.6-27b-Q5-MTP_v01.bat(核心部分)
set MODEL_PATH=F:\AI\models\Qwen3.6-27B-UD-Q5_K_XL.gguf
set CTX_LEN=141072
Release\llama-server.exe -m "%MODEL_PATH%" ^
-ngl 99 -c 141072 -b 512 -t 8 ^
--host 0.0.0.0 --port 8080 ^
--flash-attn on --cache-type-k q4_0 --cache-type-v q4_0 ^
--parallel 2 --mlock --metrics
参数解释:
-ngl 99:全部层上 GPU(32G 够放,不用抠)-c 141072:算过能装下的上下文长度(138K)。Q5 权重比 Q4 重约 2GB,256K 装不下--parallel 2:2 个并发请求槽位(KV 缓存翻倍,预算表里已留了余量)--mlock:锁定内存防换页-t 8:CPU 线程数,服务残留的 CPU 部分
注意 141072 不是整数规格——是"算到刚好装下"的结果,不是官方档位。
当前生产版已升级到 Qwen3.8-27B,并加了 MTP 投机解码:
:: 当前生产配置
Release\llama-server.exe -m "D:\Models\Qwen3.8-27B\Qwen3.8-27B-UD-Q4_K_XL.gguf" ^
--model-draft "D:\Models\Qwen3.8-27B\mtp-Qwen3.8-27B-Q4_0.gguf" ^
-ngl 99 -np 1 -c 262144 -b 512 -t 8 ^
--host 0.0.0.0 --port 8080 ^
--flash-attn on --cache-type-k q4_0 --cache-type-v q4_0 ^
--spec-type draft-mtp --spec-draft-n-max 2
元数据里 nextn_predict_layers = 1 说明模型自带 1 层 MTP(Multi-Token Prediction),3.8 配套了独立的 1.28GB Q4_0 草稿文件。--spec-draft-n-max 2 让草稿层一次多预测 2 个 token、主模型一次性验证,中文文本接受率不低,白捡的速度。注意 Q3.6 配置里没有这一项(3.6 没有独立 MTP 草稿文件),别照抄。
六、前端接入
llama-server 原生 OpenAI 兼容:
- API:
http://127.0.0.1:8080/v1(chat/completions、models 都通) - Web:
http://127.0.0.1:8080自带 playground
对 DeepSeek Harness(运行本文的工具),把模型服务指向 8080 即可:
:: D:\Dev\start-harness.bat(简化)
dsh web --port 3080
然后打开 http://127.0.0.1:3080。现在正在服务这段对话的模型,就是本文这台 V100 上跑的——某种意义上是自我验证。
服务监听 0.0.0.0,内网其他机器也能用;如果机器走 VPN 或暴露公网,记得加认证和限流(llama-server 没有内置鉴权,建议套一层反代)。
七、踩坑清单
- V100 要 Data Center 驱动,GeForce 驱动装不上/不识别。
- Q6 + 256K 直接别想,光权重 23.56GB。
- KV 缓存量化是长上下文的必选项:q4_0 把 256K 的 KV 从 17GB 压到约 4.8GB。
--n-cpu-moe对稠密模型无效,MoE 时代的残留,删掉免得误导。- MTP 要配套草稿文件:3.6 没有 mtp 文件,
--spec-type draft-mtp加了也白加。 - 别重复起服务:8080 端口被 llama-server 占着,脚本里有存在性检查,手动启动前先
nvidia-smi看一眼。
八、速查表
| 场景 | 推荐组合 |
|---|---|
| 质量优先 | Q3.8 UD-Q6_K_XL + ctx 32K~64K |
| 均衡(3.6 主选) | Q3.6 UD-Q5_K_XL + ctx 138K + –parallel 2 |
| 长上下文优先 | Q3.8 UD-Q4_K_XL + ctx 256K + MTP 投机解码 |
| 小模型快速验证 | Qwen3.5-9B-Q4_K_M(5.29 GB,8G 显存即可) |
脚本、模型都在这台机器上,GGUF 元数据解析器在 novel-project/tools/gguf-meta.py。下一篇想写 imatrix 校准与 UD 量化的制作流程。
