MoE 与稠密模型生成速度对比

我的机器是 Ryzen + 31GB 内存 + AMD 核显,没有独立显卡。折腾了几个月本地大模型,把实测结论整理成这一篇:哪些参数有用、哪些是玄学、核显为什么用不上、按内存怎么选模型。全部数据来自 llama.cpp 本机实测。

结论一:MoE 是纯 CPU 的版本答案

生成速度对比(tok/s,纯 CPU 6 线程 Q4)
LFM2-24B-A2B(激活2B)15.5
Qwen3-30B-A3B(激活3B)11.4
Gemma-4-26B(激活4B)9.6
Qwen3-14B(稠密)3.6

原理:CPU 推理的瓶颈是内存带宽——生成每个 token 都要把激活的权重从内存搬一遍。MoE 每次只激活 2~4B 参数,搬运量只有稠密 14B 的零头,所以快 2~4 倍。注意一个反直觉点:总参数 30B 的 MoE 虽然激活只有 3B,但权重文件还是 17GB+,加载和 prefill 依然吃总参的带宽,别指望 30B-A3B 在 8G 内存机上跑。

结论二:量化对生成速度几乎无影响

Qwen3.6-35B-A3B 的 Q3_K_XL 和 Q4_K_M 对比(同机同参数):

量化体积输出速度填充速度(prefill)
Q3_K_XL16.8 GB7.90 t/s18.72 t/s
Q4_K_M22.3 GB7.79 t/s12.81 t/s

输出速度几乎一致(都卡在带宽),但 Q3 的 prefill 快 46%——权重更小,读得更快。长系统提示词的 Agent 场景(prefill 占大头)选低一档量化反而更划算,质量损失 1~3% 可接受。

结论三:线程 = 物理核心数,其他全是玄学

对 LittleLamb-0.3B 做了完整参数扫描:

  • -t 6(物理核心数)最优:输出 98.7 t/s;开到 -t 16 反而暴跌到 59 t/s——超线程和过多线程只会争用内存带宽
  • 这些 GPU 向参数在纯 CPU 上全是负优化,别开:--flash-attn on、KV cache 量化(--cache-type-k/v q8_0)、--mlock、投机解码(--spec-type ngram-simple)
  • --reasoning off 对纯文本任务有效:省掉思考 token,首字延迟明显降低

结论四:核显「能用」是个误区

我的 AMD 核显(Radeon Graphics)Vulkan 可用,但 llama.cpp Vulkan 版一加载就 ErrorOutOfDeviceMemory。原因:核显没有独立显存,用的是系统内存(UMA),Vulkan 驱动把 BIOS 分的「专用帧缓冲」(默认仅 0.5GB)当成设备本地内存,模型权重根本塞不进去。

  • 正确姿势:进 BIOS 把 UMA 帧缓冲调大到 4~8GB,Vulkan 才能卸载部分层
  • 但调大后权重还是躺在系统内存里,加速有限(只是核显 EU 参与矩阵运算)——预期不要太高
  • 纯 CPU 构建的 llama.cpp 二进制会静默忽略 -ngl 参数,你以为在卸载,其实没有

按内存选模型(实测分档)

内存能跑的模型体积代表
4G< 1GB(文件+2G开销)Qwen3-0.6B-Q8、LittleLamb-0.3B、Nexus-1.2B
8G< 5GBGemma-4-E4B(5GB 临界)、7B-Q4
16G< 13GBLFM2-24B-A2B(13.4G 临界)、12~14B-Q4
32G< 29GBQwen3-30B-A3B、gemma-4-26B 系列、35B-A3B-Q3

分档规则:模型文件大小 + 约 2GB 运行开销(KV 缓存/运行时)≈ 最低内存。上下文越长开销越大,16K 上下文再额外吃 1~2GB。

我的推荐组合

  • 16G 内存机:LFM2-24B-A2B 当主力(15.5 t/s 能打),或 14B-Q4 当质量选
  • 32G 内存机:Qwen3-30B-A3B / 35B-A3B-Q3 是甜点,质量和速度平衡最好
  • Agent 调度:常驻一个 0.3B 调度员(见小模型 tool-calling 实测),重活交 MoE

有显卡的朋友直接看显卡跑大模型速查AI 算力工具;写作质量横评在这篇8 模型小说续写横评

免责声明:数据来自本机实测(Ryzen Zen4 / 31GB / 纯 CPU),不同 CPU 代际、内存频率、模型版本会有差异,仅供参考。

My machine: Ryzen + 31GB RAM + AMD iGPU, no discrete GPU. After months of local LLM experiments, here are the measured takeaways — what helps, what's superstition, why the iGPU wouldn't work, and how to pick models by RAM.

1. MoE is the answer for CPU inference

CPU decoding is memory-bandwidth-bound: every token requires streaming activated weights from RAM. MoE models activate only 2–4B parameters, so they run 2–4× faster than dense 14B (15.5 vs 3.6 tok/s). Counter-intuitive bit: a 30B-A3B MoE still needs a 17GB+ weight file — loading and prefill scale with total parameters, so it won't fit an 8GB machine.

2. Quantization barely affects decode speed

Qwen3.6-35B-A3B, Q3_K_XL vs Q4_K_M: decode is nearly identical (7.9 vs 7.8 tok/s — both bandwidth-bound), but Q3's prefill is 46% faster (18.7 vs 12.8 tok/s). For agent workloads with long prompts, lower quant is the smarter trade.

3. Threads = physical cores; everything else is superstition

  • -t 6 (physical cores) is optimal at 98.7 tok/s; -t 16 collapses to 59 — HT and extra threads just fight over bandwidth
  • All GPU-oriented flags are negative on CPU: flash-attn, KV-cache quantization, mlock, speculative decoding
  • --reasoning off meaningfully cuts first-token latency for text tasks

4. The iGPU myth

Vulkan builds detect the AMD iGPU but die with ErrorOutOfDeviceMemory: an iGPU has no VRAM — it carves a small "dedicated" frame buffer from system RAM (0.5GB by default), and model weights don't fit. Fix: enlarge the UMA frame buffer in BIOS (4–8GB). Even then weights stay in system RAM, so gains are modest. Also: CPU-only llama.cpp builds silently ignore -ngl — you think you're offloading, you're not.

Pick models by RAM

RAMModel fileExamples
4GB< 1GBQwen3-0.6B-Q8, LittleLamb-0.3B
8GB< 5GBGemma-4-E4B, 7B-Q4
16GB< 13GBLFM2-24B-A2B, 12–14B-Q4
32GB< 29GBQwen3-30B-A3B, 35B-A3B-Q3

Rule of thumb: file size + ~2GB runtime overhead ≈ minimum RAM; long contexts add 1–2GB more.

Disclaimer: measured on one machine (Ryzen Zen4 / 31GB / CPU-only); results vary across CPU generations and memory speeds.
返回文章列表