摘要:本文记录 Qwen3.8-27B(Unsloth GGUF 量化)在 Windows 11 + Docker Desktop(WSL2)环境下的本地部署与性能测试全过程。部署采用 llama.cpp server(CUDA 版),通过
--gpus all将 3× RTX 3060 12GB 三卡透传进容器,按 34%/33%/33% 分载模型。实测对比 UD-Q6_K 与 UD-Q4_K_XL 两档量化:单流解码均约 7.5 tok/s(瓶颈在 pipeline 串行),并发 ×4 时 Q4 聚合吞吐达 19.46 tok/s(+27%),长输入 prefill Q4 达 ~10.8K tok/s(+45%)。文中还整理了 ghcr.io 镜像源、--load-mode none防卡死、C 盘空间等踩坑记录及完整复跑方法。
环境:Windows 11 + Docker Desktop(WSL2 后端)・部署时间:2026-10-20
模型:Qwen3.8-27B(Unsloth GGUF 量化,256K 上下文、混合思考 + 视觉)
推理引擎:llama.cpp server(CUDA 版)
1. 部署架构
客户端层 Open WebUI / curl / 应用(OpenAI 兼容 API) ↓ 服务层 llama.cpp server(http://localhost:8080/v1) ↓ 容器层 Docker Desktop + WSL2,--gpus all 三卡透传 ↓ 硬件层 NVIDIA 驱动 610.88 / CUDA 13.3 → 3× RTX 3060 12GB2. 硬件与软件环境(实测检测)
| 项目 | 配置 |
|---|---|
| GPU | 3× NVIDIA RTX 3060 12GB(合计 36GB,GPU2 兼显示输出) |
| 内存 | 32GB |
| CPU | Intel Core i9-10900X(10C/20T) |
| 驱动 | NVIDIA-SMI 610.57 / KMD 610.88 / CUDA UMD 13.3 |
| Docker | 27.0.3(WSL2 后端,Docker Desktop) |
| 磁盘 | 模型存放 C 盘(部署时剩余 60GB → 部署后 16.7GB) |
3. 模型选择
| 量化档 | 文件大小 | 显存需求 | 适用 |
|---|---|---|---|
| UD-Q6_K(当前使用) | 21GB | ~24GB(三卡 7.3/7.4/9.7GB) | 质量优先,单流速度与 Q4 持平 |
| UD-Q4_K_XL(备选) | 17GB | ~20.5GB(三卡 5.9/6.1/8.4GB) | 并发 / 长上下文 / 显存紧张 |
说明:NVFP4 量化快 1.5× 但仅支持 Blackwell(RTX 50 系),RTX 3060(Ampere)不可用;BF16 原精度需 56GB 显存,超出本机。
4. 部署步骤
4.1 模型下载
Q6_K(当前模型)—— 国内走 ModelScope:
pip install -U modelscope # 注意:本机 python 环境需用 C:\softwore\python3106\python.exe(沙箱版有长路径问题) modelscope download --model unsloth/Qwen3.8-27B-GGUF ` --include "Qwen3.8-27B-UD-Q6_K.gguf" --local_dir C:\models\qwen3.8-27bQ4_K_XL(备选,存入 Docker 卷不占 C 盘):
docker volume create qwen-q4 docker run --rm -v qwen-q4:/data python:3.10-slim sh -c ` "pip install -q -i https://pypi.tuna.tsinghua.edu.cn/simple modelscope && ` modelscope download --model unsloth/Qwen3.8-27B-GGUF --include 'Qwen3.8-27B-UD-Q4_K_XL.gguf' --local_dir /data"4.2 拉取 llama.cpp 镜像
坑:ghcr.io 国内直连极慢 / 卡死,改用南京大学镜像源成功。
docker pull ghcr.nju.edu.cn/ggml-org/llama.cpp:server-cuda # Digest: sha256:31b39eacce2bab5fde9286ec3980ed5548a3987644e94da0d0c2092f933135384.3 启动服务容器(当前:Q6_K)
docker rm -f llama-qwen 2>$null docker run -d --name llama-qwen --gpus all --restart unless-stopped ` -v C:\models:/models ` -v qwen-q4:/models-q4 ` -p 8080:8080 ` ghcr.nju.edu.cn/ggml-org/llama.cpp:server-cuda ` -m /models/qwen3.8-27b/Qwen3.8-27B-UD-Q6_K.gguf ` --host 0.0.0.0 --port 8080 ` --ctx-size 16384 ` --n-gpu-layers 999 ` --tensor-split 0.34,0.33,0.33 ` --load-mode none参数说明:
| 参数 | 作用 |
|---|---|
--gpus all | 三张卡全部透传进容器 |
--restart unless-stopped | 开机 / 异常后自动重启 |
-v C:\models:/models | 挂载 Q6_K 模型目录(Windows 盘) |
-v qwen-q4:/models-q4 | 挂载 Q4_K_XL 卷(WSL2 内部存储) |
--ctx-size 16384 | 每槽 16K 上下文(原生 256K 但 KV 显存代价大) |
--n-gpu-layers 999 | 全部层放 GPU |
--tensor-split 0.34,0.33,0.33 | 三卡按 34%/33%/33% 分载(GPU2 兼显示输出略少) |
--load-mode none | 关键:禁用 mmap,否则 Windows 盘桥接挂载会卡死(详见踩坑记录) |
4.4 切换 Q6_K ↔ Q4_K_XL
# 切到 Q4_K_XL:仅改 -m 参数 docker rm -f llama-qwen docker run -d --name llama-qwen --gpus all --restart unless-stopped ` -v C:\models:/models -v qwen-q4:/models-q4 -p 8080:8080 ` ghcr.nju.edu.cn/ggml-org/llama.cpp:server-cuda ` -m /models-q4/Qwen3.8-27B-UD-Q4_K_XL.gguf ` --host 0.0.0.0 --port 8080 --ctx-size 16384 --n-gpu-layers 999 ` --tensor-split 0.34,0.33,0.33 --load-mode none5. 使用方式(OpenAI 兼容 API)
# 健康检查 curl http://localhost:8080/health # 对话(默认开启思考模式) curl http://localhost:8080/v1/chat/completions -H "Content-Type: application/json" ` -d "{\"model\":\"qwen3.8-27b\",\"messages\":[{\"role\":\"user\",\"content\":\"你好\"}]}" # 关闭思考(更快返回,适合追求速度的场景): # 请求体加 "chat_template_kwargs":{"enable_thinking":false}任意 OpenAI 兼容客户端可用:base_url = http://localhost:8080/v1。
6. 运维命令
docker start llama-qwen # 启动 docker stop llama-qwen # 停止 docker logs llama-qwen --tail 50 # 查看日志 docker stats llama-qwen # 资源监控 nvidia-smi # 查看三卡显存/利用率模型加载耗时约 1-2 分钟(22GB 读盘 + 上传三卡),期间 health 短暂 unhealthy 属正常。
7. 踩坑记录
| 问题 | 现象 | 解决方案 |
|---|---|---|
| ghcr.io 拉不动 | 个别 layer 无限重试 | 换ghcr.nju.edu.cn镜像源 |
| 容器加载卡死 | 日志停在 tensor 读取,显存不涨 | 加--load-mode none(新版替代--no-mmap);WSL2 桥接对 Windows 盘文件 mmap 会挂起 |
| 模型路径错 | 容器找不到文件 | 文件实际在/models/qwen3.8-27b/子目录,-m用完整路径 |
| C 盘空间不足 | 17.6GB 文件放不下 | 清理 Docker 构建缓存(docker builder prune -f)或把模型下载进 Docker 卷(WSL2 内部) |
| PowerShell 中文乱码 | 请求中文变乱码 | 用 UTF-8 字节体请求:-Body ([Text.Encoding]::UTF8.GetBytes($json)) |
8. 性能测试报告
测试方法:bench_qwen.py(Python 标准库脚本),流式请求测 TTFT、非流式取精确 usage 算吞吐;场景:短输入(关闭思考 256 tok)、长输入 prefill(~2411 tok)、默认思考模式(512 tok)、并发 ×4;采样 GPU 显存 / 利用率。同脚本、同参数对 Q6_K 与 Q4_K_XL 各测一轮。
8.1 结果总表
| 指标 | UD-Q6_K | UD-Q4_K_XL | 变化 |
|---|---|---|---|
| 单流解码吞吐 | 7.54 tok/s | 7.49 tok/s | ≈持平 |
| TTFT(短输入 19 tok) | 523 ms | 520 ms | ≈持平 |
| prefill(2411 tok) | ~7,463 tok/s | ~10,840 tok/s | +45% |
| prefill TTFT(长输入) | 323 ms | 222 ms | -31% |
| 并发 ×4 聚合吞吐 | 15.33 tok/s | 19.46 tok/s | +27% |
| 并发 ×4 墙钟 | 25.05 s | 19.73 s | -21% |
| 三卡显存合计 | ~24 GB | ~20.5 GB | -3.5 GB |
| GPU 利用率(并发均值) | 10%/16%/46% | 10%/12%/49% | — |
8.2 逐场景明细(Q6_K)
| 场景 | prompt tok | TTFT | 完成 tok | 总耗时 | 解码吞吐 |
|---|---|---|---|---|---|
| 短输入・非思考(max 256) | 19 | 523 ms | 256 | 34.5 s | 7.54 tok/s |
| 长输入 prefill(max 16) | 2411 | 323 ms | 16 | 2.3 s | 8.04 tok/s(prefill≈7463) |
| 思考模式(max 512) | 60 | 641 ms | 512(全被思考占用) | 68.8 s | 7.52 tok/s |
| 并发 ×4(max 96) | — | — | 384 合计 | 25.05 s | 聚合 15.33 tok/s,0 失败 |
8.3 关键结论
单流解码~7.5 tok/s 是瓶颈:多卡按层切分(pipeline)时,单条请求的延迟由各 GPU 串行计算决定,量化体积减小不改善关键路径;换 Q4 后单流速度几乎不变(7.49 vs 7.54)。
并发扩展性好:4 路并发聚合吞吐翻倍(Q6 15.3 / Q4 19.5 tok/s)—— 多客户端同时用才能吃满三卡。
prefill 是亮点:Qwen3.8 的 Gated DeltaNet 混合注意力让长输入 prefill 极快(Q4 达~10.8K tok/s),首 token 延迟不受输入长度拖累。
思考模式开销大:512 token 预算全被思考占用、未输出正文;追求快速回复建议请求内关闭思考。
选型建议:日常单发请求、看重质量 →Q6_K;多路并发 / RAG / 长文档 / 显存紧张 →Q4_K_XL。
8.4 复跑方法
# 脚本位置 C:\Users\******\Doubao\chats\2026-10-20\new-chat\bench_qwen.py # 运行(服务需已启动) C:\softwore\python3106\python.exe bench_qwen.py附:参考链接
Qwen3.8 模型文档(Unsloth):https://unsloth.ai/docs/zh/mo-xing/qwen3.8
模型仓库(ModelScope):https://modelscope.cn/models/unsloth/Qwen3.8-27B-GGUF
llama.cpp 官方镜像:https://github.com/ggml-org/llama.cpp