6GB显存能跑35B MoE吗:FreeToken极限配置、性能压榨与实操教程
之前在8GB 显存运行 35B 的原理文章里,我重点解释了 FreeToken 的三级存储、全局 LRU 专家缓存和 CPU-GPU 混合执行。
继续往下压一个档位,会遇到更实际的问题:
只有 6GB 显存,能不能运行同一个 Qwen3.6-35B-A3B-NVFP4?怎样配置才不会一启动就 OOM?
先说结论:可以尝试,而且已经有 RTX 3060 Laptop 6GB 的成功案例;但 6GB 不在论文公开基准的范围内,目前能引用的是 FreeToken 官方仓库中的社区复现,不是官方性能承诺。
成功启动也不等于能复现 8GB RTX 4060 Laptop 的 39.3 tok/s。6GB 会进一步压缩专家缓存和 KV Cache,更多专家 miss 会落到 PCIe 或 CPU,最终性能更依赖整机内存带宽、CPU、PCIe 和工作负载。
这里的“32GB 是下限、48GB 更推荐”是根据 30GB 内存环境的成功日志、约 22GB 的 NVFP4 checkpoint、Host expert bank、JIT 编译和操作系统余量做出的工程建议,不是 FreeToken 官方写死的最低内存规格。
FreeToken 官方仓库的 issue #303 给出了完整环境:
1
2
3
4
5
6
7
8
GPU: RTX 3060 Laptop 6GB,实际容量 5.67GiB
CPU: Ryzen 9 5900HX
RAM: 30GB
OS: Linux Mint 22.3
FreeToken: 0.1.2 + 当时的源码版本
CUDA toolkit: 13.0.2
Driver: 595.84
Model: nvidia/Qwen3.6-35B-A3B-NVFP4
失败配置是:
1
2
3
4
ft serve \
--model nvidia/Qwen3.6-35B-A3B-NVFP4 \
--memory-ratio 0.95 \
--kv-reserve-tokens 4096
它在启动阶段还要申请 FlashInfer 的 256MiB float_workspace_buffer,此时只剩 238.12MiB,最终 CUDA OOM。
社区报告给出的稳定配置是:
1
2
3
4
--attn triton
--memory-ratio 0.92
--max-prefill-length 2048
--moe-cache-size 512
启动后还可以通过:
1
ft ctl cache --moe 940
在线扩大专家缓存。
这组证据能证明“6GB 可以启动并服务”,但 issue 没有给出可与论文严格对齐的吞吐表,所以本文不会编造一个 6GB token/s。
35B MoE 的专家可以留在 Host RAM,但显存里仍然有几块不能随便消失的内容:
Attention、Router、Embedding、Norm、GDN 等非专家模块仍要在 GPU 上执行。专家能 offload,不代表模型其余部分也能全部移走。
显存越少,能保留的 expert slots 越少。缓存 miss 变多以后,有两条补救路径:
1
2
3
PCIe 搬到 GPU 再算
或者
CPU 直接读取 Host RAM 中的专家权重计算
在 issue #303 的那台机器上,带宽 profile 让 hybrid 模式把约 20.1% 的 Decode miss 通过 PCIe 搬给 GPU,其余交给 CPU。这个比例只属于那台机器,换 CPU、内存或 PCIe 后会重新计算。
更多 expert slots 通常能降低 Decode miss,但会挤压 KV Cache;KV 更多则能容纳更长上下文,却可能让 Decode 更依赖 CPU 和 PCIe。
所以 6GB 调优不是“把专家缓存拉到最大”,而是找到:
1
2
3
4
5
满足目标上下文的最小 KV
+
不会触发运行时 OOM 的余量
+
剩余空间尽可能给专家缓存
FlashInfer 的 256MiB workspace 正是典型例子。CUDA Graph、JIT kernel、临时 tensor 和内存碎片也需要余量。6GB 卡上把 --memory-ratio 从 0.92 拉到 0.95,看起来只多用了 3%,实际可能正好吃掉最后的启动空间。
FreeToken 官方 FAQ 的表述是:MoE 专家位于 Host RAM,因此需要大致相当于专家权重大小的可用内存。Qwen3.6-35B-A3B 的 BF16 版本约需 70GB,而 NVFP4 小得多。
这里要区分“物理内存”和“真正空闲内存”。
issue #303 的 30GB 环境能够完成加载,但日志已经出现:
1
expert banks: low free RAM -> serial build
这说明 32GB 更像“认真清理后台后可以做实验”,而不是完全没有压力。不要手动强制 --expert-load parallel;低内存时让自动策略选择串行构建,虽然启动慢一些,但峰值更低。
Swap 可以防止进程立刻被 OOM killer 杀掉,却不能替代物理内存。一旦推理热路径频繁访问 swap,交互性能通常会失去意义。
当前官方要求是:
1
2
3
4
5
Linux x86_64
NVIDIA Ampere 或更新架构
driver r580+
CUDA 13 toolkit,nvcc 在 PATH 中
Python 3.10+
因此:
- RTX 3060 Laptop 6GB:架构满足,并已有社区成功案例
- RTX 3050 6GB:架构满足,但没有本文引用的同模型实测,需要自己验证性能
- RTX 2060 6GB:Turing,不在当前官方支持范围
- GTX 1660 6GB:Turing,不在当前官方支持范围
- AMD 6GB:当前官方 CLI 不支持
- macOS:当前不支持 FreeToken CUDA 路径,继续使用 llama.cpp 或 MLX
Windows 和 Linux 可以使用桌面应用;下面的 CLI 教程以 Linux 为准。
1
2
3
4
5
6
7
8
9
nvidia-smi --query-gpu=name,memory.total,memory.free,driver_version,pci.bus_id \
--format=csv,noheader
nvcc --version
python3 --version
free -h
swapon --show
df -h "${HF_HOME:-$HOME/.cache/huggingface}"
lscpu | grep -E 'Model name|Socket|Core|Thread|Flags'
重点不是看到 6144 MiB 就结束,而是确认:
- 启动前实际空闲显存最好接近整卡容量;桌面环境和浏览器 GPU 进程会吃掉宝贵余量。
- Driver 与 CUDA toolkit 满足版本要求,
nvcc确实可用,因为 kernel 首次运行会 JIT 编译。 - 系统有至少约 30GB 可用内存,而不是只看“已安装 32GB”。
- Hugging Face 缓存位于空间充足的 NVMe;模型、虚拟环境和编译缓存建议预留 40GB 以上。
- CPU 支持 AVX2,并尽量使用双通道内存。6GB 下 CPU 与内存带宽比 8GB 更重要。
建议把 Hugging Face 缓存放到容量足够的 NVMe:
1
2
export HF_HOME=/mnt/nvme/huggingface
mkdir -p "$HF_HOME"
安装 uv 后创建独立环境:
1
2
3
4
5
6
7
8
9
mkdir -p ~/lab/freetoken-6gb
cd ~/lab/freetoken-6gb
uv venv --python 3.12
source .venv/bin/activate
uv pip install "freetoken[accel]"
ft --version
nvcc --version
也可以从源码安装:
1
2
3
4
5
git clone https://github.com/FlashML-org/FreeToken.git
cd FreeToken
uv venv --python 3.12
source .venv/bin/activate
uv pip install -e ".[accel]"
第一次运行会编译 CUDA kernel,时间明显比后续启动长。不要把首次 JIT 时间误认为模型每次都需要这么久。
这里最容易踩坑:Hugging Face 是模型托管平台,不代表里面的文件都是 FreeToken 支持的格式。 当前这套 Qwen3.6 实验应使用 NVIDIA 官方仓库:
FreeToken 可以直接加载 Hugging Face 的 safetensors checkpoint,不需要先转成 FTW。它当前对 GGUF 的原生支持只覆盖特定架构,不能用 Qwen3.6 GGUF 替代这个 NVFP4 checkpoint。
--model 可以直接接 Hugging Face repo id:
1
2
3
4
5
6
7
8
9
10
11
12
export HF_HOME=/mnt/nvme/huggingface
ft serve \
--model nvidia/Qwen3.6-35B-A3B-NVFP4 \
--gpu 0 \
--attn triton \
--moe-strategy auto \
--memory-ratio 0.92 \
--max-running-requests 1 \
--max-prefill-length 2048 \
--moe-cache-size 512 \
--max-output-tokens 2048
这种方式最省事,模型会进入 $HF_HOME。中断后重新执行会复用已经下载的文件。
这种方式更容易检查文件,也便于把模型固定在容量充足的 NVMe 上:
1
2
3
4
5
6
source ~/lab/freetoken-6gb/.venv/bin/activate
uv pip install -U huggingface_hub
mkdir -p /mnt/nvme/models
hf download nvidia/Qwen3.6-35B-A3B-NVFP4 \
--local-dir /mnt/nvme/models/Qwen3.6-35B-A3B-NVFP4
不要只下载权重分片;config.json、tokenizer、chat template 和 model.safetensors.index.json 也需要保留。完整下载后检查:
1
2
3
4
5
6
find /mnt/nvme/models/Qwen3.6-35B-A3B-NVFP4 \
-maxdepth 1 -type f \
\( -name '*.safetensors' -o -name '*.json' -o -name '*.jinja' \) \
-printf '%f\n' | sort
du -sh /mnt/nvme/models/Qwen3.6-35B-A3B-NVFP4
应当至少看到下面三段权重,总目录约 23.5GB:
1
2
3
model-00001-of-00003.safetensors
model-00002-of-00003.safetensors
model-00003-of-00003.safetensors
然后把本地目录交给 FreeToken:
1
2
3
4
5
6
7
8
9
10
ft serve \
--model /mnt/nvme/models/Qwen3.6-35B-A3B-NVFP4 \
--gpu 0 \
--attn triton \
--moe-strategy auto \
--memory-ratio 0.92 \
--max-running-requests 1 \
--max-prefill-length 2048 \
--moe-cache-size 512 \
--max-output-tokens 2048
建议下载前至少留出 35GB 磁盘空间。不要先用自动缓存下载一份,再手动复制一份到其他目录,否则很容易无意中占用双倍空间。
1
ft bench bw --dtype nvfp4 --gpu 0
这个测试使用真实的 CPU/offload MoE kernel,结果会写入:
1
~/.cache/freetoken/benchbw/<gpu-uuid>.json
--moe-strategy auto 会读取它,决定继续使用 offload,还是切换到 hybrid,并推导 --moe-hybrid-max-fetch。旧版本里的 --moe-backend 目前仍可兼容,但已经不是官方文档推荐的参数名。
不要复制别人的 q* 或 fetch 数量。FreeToken 会按 GPU UUID 和 expert format 区分 profile,其他机器的结果不会直接套用。
先关闭其他 CUDA 程序,再确认一次空闲显存:
1
nvidia-smi
然后使用保守配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
ft serve \
--model nvidia/Qwen3.6-35B-A3B-NVFP4 \
--gpu 0 \
--attn triton \
--moe-strategy auto \
--memory-ratio 0.92 \
--max-running-requests 1 \
--max-prefill-length 2048 \
--moe-cache-size 512 \
--max-output-tokens 2048 \
--decode-log-interval 20
其中真正针对 6GB 的关键项是:
--max-prefill-length 2048 只控制分块 Prefill 每块处理多少 token,不代表模型只能使用 2048 上下文。真正可容纳的上下文由 KV pool 决定。
另开一个终端:
1
2
3
4
5
source ~/lab/freetoken-6gb/.venv/bin/activate
ft ctl health
ft ctl cache
ft ctl stats
重点记录:
- 实际选择的
attention_backend - 实际选择的
moe_backend moe_cache_size- KV pool 能容纳多少 token
- GPU 显存占用和剩余量
- CPU executor 的线程数与 ISA
- hybrid 模式每步有多少 miss 走 PCIe
issue #303 的成功日志中,512 起步配置对应的运行时曾显示 610 个自动 slots、4163 个 KV tokens;这只用于理解量级,不应该预设你的机器也会得到相同结果。
1
2
3
ft ctl generate \
"用三句话解释MoE中总参数和激活参数的区别" \
--max-tokens 128
再测试 OpenAI 兼容接口:
1
2
3
4
5
6
7
8
9
10
curl http://127.0.0.1:1919/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "Qwen3.6-35B-A3B-NVFP4",
"messages": [
{"role": "user", "content": "写一个带单元测试的Python LRU缓存"}
],
"max_tokens": 256,
"temperature": 0
}'
冒烟测试通过后再压测,不要第一次请求就塞入几十 K 上下文。
先保存基线:
1
2
3
mkdir -p logs
ft ctl --json cache > logs/cache-512.json
ft ctl --json stats > logs/stats-512-before.json
然后一次只改一个变量:
1
2
3
4
5
6
7
8
9
10
11
12
ft ctl cache --moe 640 --wait 300
ft ctl cache
ft ctl cache --moe 768 --wait 300
ft ctl cache
ft ctl cache --moe 896 --wait 300
ft ctl cache
ft ctl cache --moe 940 --wait 300
ft ctl cache
每升一级,都用同一个 Prompt 连续跑至少三轮:
1
2
3
4
5
6
7
8
9
for i in 1 2 3; do
ft ctl generate \
"实现一个线程安全的LRU缓存并解释锁粒度" \
--max-tokens 256 \
--ignore-eos
done
ft ctl --json stats
ft ctl --json requests --limit 20
第一轮更接近冷缓存,后两轮才能观察路由局部性被 LRU 利用后的状态。
增加 slots 时同时观察 KV 容量。如果 Decode 变快,但 KV 已经低于实际上下文需求,这个配置仍然不能用于 Agent。
目标上下文只有 2K 到 4K 时,可以把更多剩余显存给专家缓存。先验证 512,再向 640、768、896 增长。
先保证 KV,而不是先追求 expert hit rate:
1
2
ft ctl cache --kv 8k --wait 300
ft ctl cache
如果 8K KV 让专家缓存缩得过小、Decode 明显变慢,就说明 6GB 已经不适合这个工作集。此时更合理的选择通常是:
- 降到 4K 左右上下文。
- 减少同时注入的仓库文件。
- 利用 radix/prefix cache 减少重复 Prefill。
- 换 8GB 或更大显卡,而不是继续挤掉运行时余量。
模型声明支持长上下文,不等于 6GB 能为它分配足够 KV。--max-seq-len-override 是上限约束,不会凭空制造 KV 显存。
可以使用这组决策:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
KV 不够目标上下文
-> 先加 KV,减少专家缓存
KV 足够,但 Decode miss 很高,GPU 仍有安全余量
-> 分级增加 expert slots
CPU 已满载,Decode 仍慢
-> 增加 expert slots,或比较 offload
PCIe 已满、CPU 还有余量
-> hybrid 让更多 miss 在 CPU 计算
启动或 warmup OOM
-> 降 memory-ratio,保持 Triton attention,不要先扩大 pool
专家缓存不是越大越快的单调函数。缓存增长可能降低 miss,却同时压缩 KV 和运行时余量;发生重建、长 Prompt 或工作集变化时,整体延迟仍可能更差。
不要只相信带宽微基准。官方仓库已有案例显示,某些硬件上 ft bench bw 推荐 hybrid,但真实模型中 offload 更快。原因包括每个 expert activation 的小 GEMV、同步和 CPU kernel 开销没有被简单带宽比完全描述。
使用同一套 Prompt,分别重启测试:
1
2
3
4
5
6
7
8
9
10
11
ft serve ... --moe-strategy auto
ft serve ... --moe-strategy offload
ft serve ... --moe-strategy cpu
ft serve ... --moe-strategy hybrid
比较时固定:
- 模型和 FreeToken commit
memory-ratio- expert slots
- KV tokens
- Prompt
- 输出 token 数
- 冷缓存还是热缓存
只有这样,结果才能回答“哪种 backend 更适合我的机器”。
我把检查、启动、状态采集和逐级调 cache 整理成了脚本:
用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
chmod +x freetoken-6gb-lab.sh
./freetoken-6gb-lab.sh preflight
./freetoken-6gb-lab.sh download
./freetoken-6gb-lab.sh verify-model
FT_MODEL="$HOME/models/Qwen3.6-35B-A3B-NVFP4" \
./freetoken-6gb-lab.sh run
./freetoken-6gb-lab.sh status
./freetoken-6gb-lab.sh smoke
./freetoken-6gb-lab.sh sweep
通过环境变量可以覆盖默认值:
1
2
3
4
5
FT_GPU=0 \
FT_MEMORY_RATIO=0.90 \
FT_MOE_CACHE_SIZE=512 \
FT_MAX_PREFILL=2048 \
./freetoken-6gb-lab.sh run
症状通常指向 FlashInfer workspace。
处理顺序:
1
2
3
4
5
确认 --attn triton
确认 memory-ratio 不高于 0.92
关闭其他 GPU 进程
必要时继续降到 0.90 或 0.88
保持 moe-cache-size 512,不要先扩大缓存
issue #303 截至本文日期仍为 open,所以不要假设所有版本都已经自动为 attention workspace 预留空间。
1
2
3
4
关闭浏览器、IDE、Docker 和其他模型服务
让 expert-load 保持 auto,接受 serial build
检查是否正在大量 swap
仍然失败就增加物理内存
不要用 --expert-load parallel 强行换取启动速度,它会提高加载峰值。
先运行:
1
2
ft ctl cache
ft ctl requests --limit 20
确认请求长度没有超过 KV pool。FreeToken 仓库中已有“请求超过 KV pool 后排队而没有清晰错误”的问题报告,因此应用层最好主动限制上下文,而不是只依赖模型的最大长度声明。
- 查看 expert cache 是否过小。
- 在 KV 足够的前提下逐步增加 slots。
- 比较
offload与hybrid,不要只看 auto。 - 检查内存是否双通道、频率是否正常。
- 检查 CPU 是否降频或笔记本处于省电模式。
nvidia-smi 的空闲值不等于一个足够大的连续可分配块,也没有替你计算后续 workspace、graph capture 和临时 tensor。6GB 卡必须保留保守余量。
FreeToken 降低的是 VRAM 门槛,不是模型总内存需求。35B NVFP4 的专家权重仍要驻留 Host RAM。16GB 内存不是“速度慢一点”,而是很可能无法稳定加载。
当前官方要求 Ampere 或更新架构。RTX 2060 和 GTX 1660 即使也是 6GB,也不能直接套用 RTX 3060 的结论。
39.3 tok/s 属于论文中的 8GB RTX 4060 Laptop、NVFP4 模型和 coding-agent workload。6GB 社区案例只证明能启动和服务,没有同条件吞吐数据。
6GB 下增加上下文通常意味着减少 expert slots。长 Agent 会话即使不 OOM,也可能因为专家 miss 增加而逐渐变慢。
缩小 max-prefill-length 能降低峰值,却可能增加分块开销。Decode 速度好看也不代表 TTFT 好看。
同一张 RTX 3060 Laptop 6GB,在 DDR4 单通道、DDR4 双通道和高带宽 DDR5 机器上,CPU fallback 的表现会完全不同。PCIe 是否降到 x4、笔记本功耗墙和 CPU 温度也会改变结果。
6GB 暴露的是显存预算边界问题。attention workspace、cache planner、请求长度校验和 backend 自动选择都仍有活跃 issue。复现实验必须记录 FreeToken 版本或 Git commit。
如果目标是“验证系统思路、偶尔运行 35B MoE”,已有 RTX 3060 Laptop 6GB 和 32GB 内存可以先试,成本最低。
如果目标是“每天把它当 Coding Agent 使用”,更合理的最低配置是:
1
2
3
4
5
RTX 3060/4060 8GB 或更大
48GB 以上系统内存
双通道高带宽内存
NVMe
Linux + CUDA 13
多出来的 2GB 显存不仅是多放一点权重,更重要的是给 KV、expert slots 和运行时 workspace 留出同时存在的空间,调优难度会明显下降。
6GB 显存运行 35B MoE 的正确理解是:
1
2
3
4
不是把 35B 放进 6GB
而是只把非专家模块、KV、工作区和少量热专家放进 6GB
完整专家池仍然放在大内存里
缓存 miss 再由 PCIe 和 CPU 兜底
6GB 能做,但已经进入系统工程的边缘:
- 使用 Ampere 或更新的 NVIDIA GPU。
- 准备至少 32GB、最好 48GB 系统内存。
- 从 Triton attention、0.92 memory ratio、2048 Prefill chunk 和 512 slots 起步。
- 先保证启动与目标 KV,再逐级增加专家缓存。
- 实测 auto、offload 与 hybrid,不照搬别人的带宽比例。
- 不把 8GB 论文跑分包装成 6GB 性能承诺。
对 6GB 用户来说,最有价值的结果不是跑出一个孤立的最高 token/s,而是找到一个在自己的 Prompt、上下文长度和散热条件下可以连续运行的配置。