写在前面
这三天都没咋睡觉,主要在验证一件事:一台 RTX SPARK搭载(GB10,128GB 统一内存)的笔记本,本地推理大模型的极限到底在哪里?
目标不是跑分,而是搞清楚:稠密模型和 MoE(Mixture of Experts)模型在不同参数规模下,到底谁能在我的机器上跑得动、跑得好、上下文够用。最终我验证了一个使用起来不错的模型——Qwen3.6-35B-A3B(MOE),但这之前为了测到极限,踩了无数坑。锁进程内存的坑、压缩物理内存的坑,混合推理的坑。各个不同Claw的坑。
整篇文章可以直接丢给 AI 让它帮你理解我的验证过程。以下是完整的踩坑记录和结论。
模型分类速查
在深入验证之前,先把常见的模型架构分三类说清楚,这直接影响推理方式和资源占用:
1. 稠密模型(Dense)
代表: Qwen3 8B/32B、Llama 3.3 70B、Qwen3-Coder-Next 80B、MiniMax-M2.7
特点: 每次推理所有参数全部激活。70B 的模型生成一个 token 就要计算 700 亿次乘法。
资源需求:
- 模型体积 ≈ 参数量 × 量化比特数 × 2(权重 + KV Cache)
- 70B Q4_K_M → ~39.6 GB
- KV Cache 随上下文线性增长,70B 的 KV Cache 开销尤其大
- 生成速度随参数规模递减,70B 实测只有 ~2.7 t/s
2. MoE 模型(Mixture of Experts)
代表: Qwen3.6-35B-A3B、DeepSeek-V4 (Flash)、Qwen3.6 系列
特点: 总参数可能很大,但每个 token 只激活一小部分专家。35B MoE 实际每次只算 ~3B 参数。
资源需求:
- 模型体积由总参数决定(Q4_K_XL 量化下 35B MoE ~ 20.82 GB)
- 推理负载由激活参数决定(~3B,和 8B 稠密模型一个量级)
- KV Cache 开销取决于层数,MoE 通常层数更少,开销更小
- 推理速度由激活参数决定,远快于同规模的稠密模型
3. 多模态模型(Vision/Text)
代表: Qwen2VL、LLaVA、MiniCPM-V(这些在 llama.cpp 二进制里有对应的专用 CLI,如 llama-qwen2vl-cli.exe、llama-llava-cli.exe、llama-minicpmv-cli.exe)
特点: 同时处理图像和文本。推理时需要加载视觉编码器,额外占用显存。
资源需求:
- 模型体积比纯文本模型大 30-50%
- 视觉编码器加载后常驻显存
- KV Cache 计算方式类似稠密模型,但 prompt 中图像 token 会占用额外空间
- 本次验证中未作为重点测试,因为目标是纯文本推理能力
简单类比:
- 稠密模型:每次考试,全班 80 个人都要答每一道题
- MoE 模型:每次考试,只从 80 人里挑 3 个人答对应的题
- 多模态模型:每次考试,先请美术老师看图,再由文字老师答题
环境全貌
硬件:
| 组件 | 规格 |
|---|---|
| GPU | RTX SPARK (GB10) · CUDA ARCH · 59.5 GB VRAM |
| CPU | AMD · 20 线程 |
| 系统内存 | 120 GB |
| 虚拟内存 | 推到了 200+ GB(后期调试用) |
| 操作系统 | Windows 11 ARM64,x64 |
软件栈:
- llama.cpp build b9731 · CUDA 13.3 · 官方 Windows x64 二进制
- GGUF 量化格式(Q4_K_M / Q4_K_XL)
- Flash Attention:
-fa auto(b9731 版本必须带值,裸-fa会报错) --fit on是关键参数:让 llama.cpp 根据实际可用显存自动适配
模型存放:
F:\AI\Models\
├── Meta\
│ └── Llama-3.3-70B-Instruct-GGUF\
│ └── Llama-3.3-70B-Instruct-Q4_K_M.gguf (39.6 GB)
└── Qwen\├── Qwen3-8B-GGUF│ └── Qwen3-8B-Q4_K_M.gguf (4.68 GB)├── Qwen3-32B-GGUF│ └── Qwen_Qwen3-32B-Q4_K_M.gguf (18.4 GB)├── Qwen3-Coder-80B-GGUF│ └── Qwen3-Coder-Next-UD-Q4_K_XL.gguf (46.2 GB)└── Qwen3.6-35B_MOE_GGUF└── Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf (20.82 GB)
运行时在 F:\AI\Runtimes\llama-b9731,日志在 F:\AI\Outputs\。
第一阶段:Qwen3 8B — 烟雾测试
这是整个验证的起点。8B 参数、Q4_K_M 量化后仅 4.68 GB,最快验证 CUDA 路径。
运行命令:
llama-cli.exe -m "%MODEL%" --jinja -ngl 99 -fa auto -fit on -c 4096 -n 128 -cnv -st -p "用中文简单自我介绍"
日志关键输出:
offloading 35 repeating layers to GPU
offloaded 37/37 layers to GPU
CPU model buffer size = 0.00 MiB
projected to use 1766 MiB of host memory vs. 120666 MiB total
结果:✅ 完全通过。
所有层全部加载到 GPU。prompt eval: 151ms/token,生成速度约 2.6 tokens/second。
注意: b9731 版本的 Flash Attention 语法是 -fa auto,不是裸 -fa。如果用 -fa on 会报错 unknown value for --flash-attn: '-on'。这个坑后面踩了好几次。
第二阶段:Qwen3 32B — 稠密模型的上下文瓶颈
32B 的 Q4_K_M 量化模型约 18.4 GB。显存 59.5 GB,理论上是够的。
运行命令:
llama-server.exe -m "%MODEL%" --host 127.0.0.1 --port 18081 -c 4096 -ngl 99 -fa auto --jinja --fit on
关键发现:
-
上下文窗口很窄。 日志确认
n_ctx_seq (4096) < n_ctx_train (40960)——模型训练支持 40K 上下文,实际推理只用了 4K。 -
稠密模型的上下文瓶颈。 32B 稠密模型,每个 token 都要过全部参数。KV Cache 随上下文线性增长,很快就把显存吃满了。这就是为什么后续需要 MoE 模型——KV Cache 才是真正限制长上下文的关键。
结论:32B 稠密模型能用,但上下文太小,不适合做长期对话。
DeepSeek-V4 Flash — 测试数据丢失,基于推理的补充
这一段的实验数据在硬盘上已经不存了(模型文件已删除,日志丢失)AI在清理数据的时候他太大了,给清理丢了,但是结论就是没有跑起来,但根据架构分析和同类型 MoE 模型的表现,只做合理推断。
在我的机器上会怎样
推断结论: DeepSeek-V4 Flash 在我的 59.5 GB 显存机器上,理论上可以用 --fit on + 大量虚拟内存跑起来,但实际体验会非常差——加载慢、生成慢、上下文窗口极窄。它不是本地部署的理想选择,而是云端 GPU 集群的赛道。
这也印证了选模型的核心原则:不是越大的模型越好,而是要匹配你的硬件。
MiniMax-M2.7 的教训
在探索过程中,我还下载了 MiniMax-M2.7 模型(100+ GB),但最终删除了它。原因:
- 显存完全不够:即使量化,模型体积远超 59.5 GB VRAM
- CPU 推理太慢:只能纯 CPU 推理,速度完全不可用
- 磁盘空间浪费:100+ GB 的模型下载占用了大量磁盘
- Windows 兼容性:某些模型格式在 Windows 下不支持
教训:不是所有模型都适合本地部署。在选模型之前,先算一笔账:模型大小 vs 可用显存 vs 目标推理速度。如果算不过来,就该放弃。
第三阶段:Llama 3.3 70B — 显存不够的极限挑战
70B 的 Q4_K_M 量化模型约 39.6 GB。我的 GPU 有 59.5 GB VRAM,但实际测试中显存是瓶颈。
踩坑:--fit 和 -ngl 99 冲突
日志第一条错误:
W common_fit_params: failed to fit params to free device memory:
n_gpu_layers already set by user to 99, abort
原因: -ngl 99 强制把 99 层全放 GPU,--fit on 要求自动调整,两者矛盾。llama.cpp 看到用户强制指定了 -ngl 99,就拒绝让 --fit 做任何调整。
解决: 稠密大模型去掉 -ngl 强制指定,完全让 --fit 来决策。
实际运行表现
加载耗时约 26 秒,跑起来了。但性能数据很说明问题:
长上下文测试(21145 tokens prompt):
prompt eval time = 234677 ms / 21145 tokens = 90.10 t/seval time = 7658 ms / 21 tokens = 2.74 t/s (生成速度)
total time = 242336 ms / 21166 tokens
n_ctx_seq (65536) < n_ctx_train (131072)
关键发现:
- 生成速度只有 2.74 tokens/秒
- 处理 21K token 的 prompt 需要 近 4 分钟
- KV Cache:
27346 tokens → 8.55 GB,prompt cache 上限 8192 MB 被撑爆
cache size limit reached, removing oldest entry
性能数据汇总(Llama 3.3 70B):
| 测试 | Prompt Tokens | Prompt 速度 | 生成速度 |
|---|---|---|---|
| 首次握手 | 42 | 84.39 t/s | 5.26 t/s |
| 长上下文 | 21145 | 90.10 t/s | 2.74 t/s |
| 更长上下文 | 26012 | 97.06 t/s | 3.18 t/s |
| 长上下文 | 19348 | 83.80 t/s | 3.10 t/s |
一句话总结:70B 稠密模型能跑,但生成速度太慢(~3 t/s),上下文窗口受限,不适合日常对话。
第四阶段:Qwen3-Coder-Next 80B — 更大的MOE模型
80B 参数(实际 80B+),Q4_K_XL 量化后 46.2 GB。
运行脚本中的调参思考:
set CTX=131072
set FIT_CTX=32768
set GPU_LAYERS=all
set FIT_TARGET=256
set CACHE_K=q4_0
set CACHE_V=q4_0
思路:用 KV Cache 量化(q4_0)+ CPU offload(--kv-offload / --op-offload)的组合拳,在 59.5 GB 显存下尽可能撑大上下文到 128K。
但这个模型仍是MOE模型,主要问题是启动起来就占用了110G的内存。没有余量留给KV Cache了。最终4K的KVCache下运行起来了。 没有任何意义,虚拟内存增加只会拖慢推理速度。
第五阶段:Qwen3.6-35B-A3B (MoE) — 最终答案
什么是 MoE,为什么它改变了游戏规则
这是整个探索中最重要的一课。
MoE(Mixture of Experts)和稠密(Dense)模型的本质区别: 每个 token 推理时,MoE 只激活一部分专家网络(约 3B 参数),而稠密模型每次都要过全部参数。
| 对比维度 | 稠密模型 (Dense) | MoE 模型 |
|---|---|---|
| 总参数量 | 70B / 80B | 35B |
| 每次激活参数 | 全部 70B/80B | 约 3B |
| 推理速度 | 慢(全部参数计算) | 快(少量专家计算) |
| 上下文上限 | KV Cache 限制严重 | 相对友好 |
简单类比:
- 稠密模型:每次考试,全班 80 个人都要答每一道题
- MoE 模型:每次考试,只从 80 人里挑 3 个人答对应的题
这就是为什么 Qwen3.6-35B-A3B 虽然总参数 35B,但实际推理负载只有 3B 级别——推理时的计算量和显存占用和 8B 稠密模型在一个量级。
最终配置
模型文件: Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf · 20.82 GB
运行命令:
set MODEL_PATH=F:\AI\Models\Qwen\Qwen3.6-35B_MOE_GGUF\Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf
set PORT=18083
set CONTEXT=262144
set GPU_LAYERS=99llama-server.exe -m "%MODEL_PATH%" -c %CONTEXT% -fa auto -ngl %GPU_LAYERS% --host %HOST% --port %PORT%
关键点:
- 262144 上下文:当前会话正在使用的实际上下文上限(256K tokens)
-ngl 99+-fit on不冲突:MoE 每层计算量小,99 层全放 GPU 不会爆显存- 20.82 GB 模型 + 262K 上下文:在 59.5 GB 显存 + 200 GB 虚拟内存的组合下跑得通
为什么最终选择了这个模型
- 推理速度快:每次只激活 ~3B 参数,生成速度远高于 70B 稠密模型
- 上下文窗口大:262K 上下文可处理大量代码、长文档、多轮对话
- 中文能力强:Qwen3.6 系列中文理解能力优秀
- 显存压力小:MoE 的稀疏激活模式,KV Cache 开销相对可控
- GGUF 量化友好:Q4_K_XL 量化在质量和体积之间取得了良好平衡
推测解码实验:让 32B 跑得更快
在验证过程中我还尝试了两种推测解码(speculative decoding)方案,目标是用一个小模型猜,大模型只负责验证,从而提高生成速度。
方案一:8B 草稿模型(speculative draft)
脚本:serve-qwen3-32b-18081-spec-draft8b.cmd
llama-server.exe -m "%MODEL%" \--spec-type draft-simple \--spec-draft-model "Qwen3-8B-Q4_K_M.gguf" \--spec-draft-ngl 99
思路:用 8B 小模型做草稿(每次生成几个 token),32B 大模型只做验证。草稿模型全放 GPU,32B 主模型也用 --fit on 自动分配。
方案二:N-gram 缓存(speculative ngram cache)
脚本:serve-qwen3-32b-18081-spec-ngram.cmd
llama-server.exe -m "%MODEL%" \--spec-type ngram-cache
思路:不需要额外的草稿模型,llama.cpp 内部用 n-gram 匹配历史 token 来推测下一个 token。零额外模型下载,纯靠缓存加速。
和 70B 日志的关联
70B 测试日志里有一条关键警告:
common_speculative_init: no implementations specified for speculative decoding
这就是为什么 70B 生成速度只有 2.7 t/s 的核心原因之一。 没有开推测解码,所有 token 都要纯算一遍。如果当时配上一个小草稿模型,速度应该有可观提升。这也是后续可以优化的方向。
关键踩坑总结
1. Flash Attention 语法
- b9731 版本:
-fa auto/-fa on/-fa off(必须带值) - 裸
-fa会报错:unknown value for --flash-attn: '-ctk' - 解决方案: 统一使用
-fa auto
2. --fit on 和 -ngl 的冲突
-ngl 99强制 99 层全 GPU,--fit on要求自动调整 → 矛盾- MoE 模型可以用
-ngl 99+-fit on,因为每层负载小 - 稠密大模型建议去掉
-ngl,完全依赖--fit
3. 上下文窗口 = 显存杀手
稠密模型每个 token 的 KV Cache 都很大:
27346 tokens → 8.55 GB KV Cache
21170 tokens → 6.62 GB KV Cache
MoE 模型相对友好,但 256K 上下文仍然需要大量显存 + 虚拟内存。
4. 虚拟内存是救命稻草
把虚拟内存推到 200+ GB 后,即使显存爆了,系统也能用内存 + 磁盘交换空间来兜底。代价是速度变慢,但至少不会崩溃。
5. CUDA 13 的 ARM64 兼容
llama.cpp 官方 CUDA 构建是 Windows x64,而我的机器是 ARM64。通过 Windows 的 x64 emulation 运行,基本功能正常。CPU 指令集检测可能不准确,某些 ggml-cpu-* DLL 可能选到次优路径,总体影响不大。
6. Prompt Cache 上限
llama.cpp 的 prompt cache 默认上限约 8 GB。70B 模型的长上下文测试中,27346 tokens 就占了 8.55 GB,触发 cache size limit reached。解决方案:调整 --cache-ram 或减少上下文长度。
7. 推测解码不是摆设
70B 日志中 no implementations specified for speculative decoding 的警告说明,如果目标模型支持推测解码但没配草稿模型,等于白白浪费了加速能力。
性能对比汇总
| 模型 | 参数量 | 架构 | 量化 | 模型大小 | 上下文 | 生成速度 | 适用场景 |
|---|---|---|---|---|---|---|---|
| Qwen3 8B | 8B | Dense | Q4_K_M | 4.68 GB | 4K | ~3 t/s | 快速测试、简单对话 |
| Qwen3 32B | 32B | Dense | Q4_K_M | 18.4 GB | 4K | ~3 t/s | 中等对话 |
| Llama 3.3 70B | 70B | Dense | Q4_K_M | 39.6 GB | 64K | ~2.7 t/s | 复杂推理(慢) |
| Qwen3-Coder-Next 80B | 80B | Dense | Q4_K_XL | 46.2 GB | 128K | 更慢 | 代码生成(未验证完成) |
| Qwen3.6-35B-A3B | 35B (3B active) | MoE | Q4_K_XL | 20.82 GB | 256K | 较快 | 主力日常使用 |
后记:这不是终点
这个验证周期花了三天时间,从 8B 一路试到 230B,最终在 35B MoE 上稳定了。但我知道这只是一个起点。
未来可能的方向:
- 探索 speculative decoding(草稿模型 + 主模型)——已有脚本,缺实际跑分数据
- 对比不同推理引擎(llama.cpp vs mlc-llm vs others)
- 扩展更长的上下文从 262K 扩展到 1M
最重要的是:本地推理不是一个配置问题,而是一个取舍问题。你必须在模型质量、推理速度、上下文窗口和硬件成本之间做出选择。搞清楚自己的需求,然后选择最匹配的模型——这才是验证的终极意义。
本文基于真实实验日志和运行记录编写,所有数据和结论均来自 F:\AI\ 下的实际测试文件。DeepSeek-V4 Flash 部分的体积推断基于 GGUF 量化公式和同类型模型经验,因测试数据丢失无法提供实测数据。
