Tesla V100 32G + llama.cpp 本地部署 Qwen3.6 27B:从驱动到 138K 长上下文的完整方案

作者:

这篇记录 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

实测与估算吻合,这套预算方法是可信的。两个结论:

  1. --flash-attn on + --cache-type-k q4_0 --cache-type-v q4_0 是长上下文的两个必选项,缺一个 256K 都悬。
  2. 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 没有内置鉴权,建议套一层反代)。

七、踩坑清单

  1. V100 要 Data Center 驱动,GeForce 驱动装不上/不识别。
  2. Q6 + 256K 直接别想,光权重 23.56GB。
  3. KV 缓存量化是长上下文的必选项:q4_0 把 256K 的 KV 从 17GB 压到约 4.8GB。
  4. --n-cpu-moe 对稠密模型无效,MoE 时代的残留,删掉免得误导。
  5. MTP 要配套草稿文件:3.6 没有 mtp 文件,--spec-type draft-mtp 加了也白加。
  6. 别重复起服务: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 量化的制作流程。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注