硬件:RTX5060Ti 16GB VRAM + 整机 32GB 物理内存 + WSL2 Ubuntu-24.04。 结果:部署成功,OpenAI 兼容 API 运行于
http://127.0.0.1:8000/v1,稳定解码 22~24 tok/s。 本文是上一篇《FreeToken 部署 Qwen3.6-35B-A3B-NVFP4 操作计划》的实战回执:教程给出的计划在执行中遇到 4 个与文档不符的坑,本文记录每个坑的根因与最终解法,供同配置机器复现。
1. 最终部署汇总报告
# FreeToken 部署最终汇总报告
✅ 部署结果:成功
🖥️ 硬件:RTX5060Ti 16G + 整机 32G 内存(WSL2 Ubuntu-24.04)
📌 模型:Qwen3.6-35B-A3B-NVFP4(NVIDIA modelopt 官方量化版,22GB,3 分片)
📊 运行指标:
- 冷加载耗时:约 34 秒(CUDA 内核缓存命中后;首次冷启约 2~3 分钟)
- 稳定解码速度:22 ~ 24 tok/s(实测多次采样:22.5 / 24.2 / 24.4 / 23.7 / 24.0 / 23.4)
- 峰值显存占用:约 5.9 GB / 16 GB(推理中 nvidia-smi 实测)
- 峰值内存占用:约 19 GB / 23 GB(WSL 限制;专家权重 16.9GB 常驻系统内存)
- Swap 最大使用:约 0 GB(未发生 swap 风暴)
🧪 API 测试结果:成功,模型可正常自我介绍、生成代码,回答质量正常
⚠️ 发现的问题:详见第 3 节(4 个部署坑,均已解决)
🔄 备选方案建议:无需切换 Unsloth Desktop
2. 最终启动配置(可直接复现)
python -m freetoken \
--model-path /home/dev/models/Qwen3.6-35B-A3B-NVFP4-nvidia \
--moe-strategy offload \
--moe-cache-size 256 \
--num-tokens 4096 \
--kv-reserve-tokens 8192 \
--max-prefill-length 8192 \
--max-running-requests 1 \
--moe-cpu-layers auto \
--attention-backend triton \
--host 127.0.0.1 --port 8000
关键参数说明(与教程的差异已在括号标注)
| 参数 | 值 | 说明 |
|---|---|---|
--moe-strategy offload |
必选 | 专家权重驻留系统内存(16.9GB),GPU 只放 dense 权重 + 小缓存 |
--moe-cache-size 256 |
关键 | 不要用 auto 或 2048(见坑 4),本机 256 槽可稳定启动 |
--num-tokens 4096 |
关键 | KV 实际容量;教程的 8192 上下文在本机需要配合 offload 才能稳定 |
--moe-cpu-layers auto |
推荐 | 自动按 pin 预算锁 18 层 CPU decode,其余 GPU 拉取 |
--attention-backend triton |
必选 | 教程写 --attn,实际参数名是 --attention-backend |
--max-running-requests 1 |
必选 | 单并发,硬件限制 |
WSL 系统配置
%UserProfile%\.wslconfig(在教程基础上增加了 vmIdleTimeout=0):
[wsl2]
memory=24GB
processors=8
swap=4GB
localhostForwarding=true
vmIdleTimeout=0
另:建议用 systemd 托管服务(/etc/systemd/system/freetoken.service + [boot] systemd=true),服务不再依赖任何终端会话,配合 Restart=on-failure 自动拉起。
3. 实战中踩过的 4 个坑(教程与实际的关键差异)
坑 1:教程给的仓库、CLI、参数名与真实版本不符
| 教程描述 | 实际情况 |
|---|---|
github.com/freetoken/freetoken |
404 死路;真实仓库为 github.com/FlashML-org/FreeToken(镜像:https://ghproxy.net/https://github.com/FlashML-org/FreeToken.git) |
freetoken serve <model> |
CLI 入口为 python -m freetoken(entry point 另有 ft) |
--attn triton |
参数名为 --attention-backend triton |
--moe-cache-size auto |
本机 auto 会 OOM(见坑 4),需显式 256 |
坑 2:unsloth 混合量化模型不被 FreeToken 支持 → 换 NVIDIA 官方 modelopt 版
教程指向 ModelScope 的 unsloth/Qwen3.6-35B-A3B-NVFP4(26.5GB,compressed-tensors 混合布局:部分专家 FP8、部分 NVFP4)。FreeToken 的 MoE 量化注册表只有 nvfp4 / fp8_block / mxfp4 / mxfp8 / unquantized,不支持 per-tensor FP8 专家,启动即报:
NotImplementedError: no quant method for moe.fp8_tensor
解法:改用 NVIDIA 官方 nvidia/Qwen3.6-35B-A3B-NVFP4(modelopt MIXED_PRECISION:161 个 W4A16_NVFP4 专家 + 130 个 FP8 attention),经国内镜像 hf-mirror.com 下载 22GB(3 分片),并设 HF_HUB_DISABLE_XET=1 绕过 Xet 协议 401 报错。
坑 3:RTX 5060 Ti(Blackwell SM120)需要 CUDA 13 工具链
FreeToken 启动时会用 tvm_ffi JIT 编译 CUDA 内核(CUDA Graphs 阶段),目标架构 compute_120。系统自带的 nvcc 12.0 不认识 Blackwell:
nvcc fatal: Unsupported gpu architecture 'compute_120'
解法:从 NVIDIA 官方 apt 源安装 CUDA 13 工具链(仅编译需要):
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb
dpkg -i cuda-keyring_1.1-1_all.deb && apt-get update
apt-get install -y cuda-nvcc-13-0 cuda-cudart-dev-13-0 cuda-cccl-13-0
export CUDA_HOME=/usr/local/cuda-13.0
同时需 pip install ninja(FreeToken 的 tvm_ffi 编译依赖)。注意 PyPI 的 nvidia-cuda-nvcc-cu13 在清华源是占位包、官方源构建失败,apt 源才是正解。
坑 4:两个“假 OOM”——WSL 会话回收 + WDDM 显存记账
这是本次部署最折腾的部分,两种现象都表现为“服务启动成功后又消失 / 报 CUDA OOM 但显存明明没用满”:
现象 A:服务进程随 WSL 会话退出被杀
- 现象:日志停在专家加载 0%~33%,进程消失、无 OOM、无 traceback,内存全部释放
- 排查:
dmesg有 systemd shutdown 记录;sleep保持进程也消失 - 根因:任何由
wsl.exe前端启动的进程(包括setsid nohup),在 wsl.exe 断开后都会被 WSL 会话回收;WSL 发行版空闲 60 秒后还会自动关闭(vmIdleTimeout默认 60000ms) - 解法:升级 WSL 到 2.7.13(修复会话/进程回收)+ 配置
vmIdleTimeout=0+ 用 systemd 托管服务
现象 B:CUDA OOM,但 nvidia-smi 显示显存只用了不到 1GB
- 现象:
Tried to allocate 540.00 MiB失败,报错称 “this process has 17179869184.00 GiB memory in use”(16GB 虚拟记账假象),实际 PyTorch 只分配了 3.1GB - 排查:最小 torch 脚本复现——单次分配 1GB 成功、4GB 失败;但单独跑又能连续分配 16GB;
cudaMemGetInfo显示 free 11.6GB 却连 32MB 都分配失败。banks(cudaHostRegister)经探针验证不占 GPU 配额,排除嫌疑 - 根因:WSL2 的 WDDM 显存管理在特定状态下把进程可用显存锁死为 0,与物理显存占用无关(WSL 旧版本 bug)
- 解法:升级 WSL 到 2.7.13 后问题消失
结论:遇到“显存没用满却 OOM”或“进程莫名消失”,先查 WSL 版本(
wsl --version),旧版本升级到 2.7.13+ 是最优先动作。
4. 性能与资源实测
| 指标 | 实测值 | 说明 |
|---|---|---|
| 冷加载 | ~34s | CUDA 内核缓存命中后;首次冷启约 2~3 分钟(专家加载 45s + CUDA Graphs 42s + warmup 16s) |
| 稳定解码 | 22~24 tok/s | 高于教程预期的 14~22 tok/s |
| 峰值显存 | ~5.9GB / 16GB | 推理中;空闲时约 1GB(offload 架构正常现象) |
| 峰值内存 | ~19GB / 23GB | 专家权重 16.9GB 常驻系统内存 |
| Swap | ~0 | 未触发 swap 风暴 |
| 模型大小 | 22GB | NVIDIA modelopt 版,3 分片 |
显存占用低是 offload 架构的正常现象:dense 权重 + 小专家缓存放显存,专家主体在系统内存按需搬入,物理显存占用不代表性能问题。
5. API 接入信息
- API base url:
http://127.0.0.1:8000/v1 - model name:
Qwen3.6-35B-A3B-NVFP4-nvidia(默认取模型目录尾名) - api key:任意字符串(本地无鉴权,如
sk-local)
curl http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-local" \
-d '{"model":"Qwen3.6-35B-A3B-NVFP4-nvidia",
"messages":[{"role":"user","content":"你是谁"}]}'
实测返回正常(见截图),可接入 Claude Code / OpenClaw 等工具的 OpenAI 兼容端点。
6. 运维建议
- 服务托管:用 systemd(
systemctl enable freetoken)而非终端前台,避免会话回收导致服务掉线 - 监控:每 30 秒采样
free -h与nvidia-smi --query-gpu=memory.used,memory.total --format=csv;Swap 持续 >2GB 或 CUDA OOM 即停止服务释放内存 - 禁止调整:
--max-running-requests保持 1;--num-tokens/ KV 上下文不要盲目调大(16GB 显存 + 32GB 内存的硬上限) - 遇到“假 OOM”:先
wsl --version确认 WSL ≥ 2.7.13,再排查业务配置