TinkerLab
01 // HOMELABNVIDIA GPUDocker / ComposeStreaming / API~14 min read & lab

Running 30B & 80B MoE Models on a 12GB–24GB Consumer GPU + Dual-Channel DDR5 PC: Native llama.cpp --n-cpu-moe Benchmark & RTX 5070 SUPER (18GB) / 5080 SUPER (24GB) Sizing

You do not need an EPYC server or a $4,000 workstation card to run Qwen3-30B-A3B (18.6GB) or Qwen3-Next-80B-A3B (48.2GB) on a desktop PC. Upstream llama.cpp’s native `--n-cpu-moe N` (`-ncmoe N`) flag keeps 100% of attention layers and the Q8_0 KV cache inside your 12GB/16GB/24GB GPU while offloading only sparse MoE experts for N layers to dual-channel DDR5 RAM—delivering 46–55 tok/s on Qwen3-30B-A3B and 26–33 tok/s on Qwen3-Next-80B-A3B. We also model how 3GB-module GDDR7 refreshes (RTX 5070 SUPER 18GB & RTX 5080 SUPER 24GB, spec-estimate) shift the exact `--n-cpu-moe` threshold.

[KEY VERIFIED TAKEAWAY / TL;DR]In Tinker AI Lab's reproducible verification of "Running 30B & 80B MoE Models on a 12GB–24GB Consumer GPU + Dual-Channel DDR5 PC: Native llama.cpp --n-cpu-moe Benchmark & RTX 5070 SUPER (18GB) / 5080 SUPER (24GB) Sizing" (tested on Measured on: AMD Ryzen 9 9900X + 64GB Dual-Channel DDR5-6400 CL30 (~84 GB/s read) + NVIDIA RTX 4070 (12GB) / RTX 5060 Ti (16GB) / RTX 5070 Ti (16GB) / RTX 4090 (24GB) | Spec-estimate rows: NVIDIA RTX 5070 SUPER (18GB GDDR7 192-bit · ~672 GB/s) & RTX 5080 SUPER (24GB GDDR7 256-bit 32 Gbps · ~1,024 GB/s) with llama.cpp b4920+ (upstream native `--n-cpu-moe` / `-ncmoe` & `--cpu-moe` / `-cmoe` support), CUDA 12.8 (`GGML_CUDA=1` + Flash Attention `-fa`), Models: Qwen3-30B-A3B-Q4_K_M.gguf (18.6 GB, 48 layers) & Qwen3-Next-80B-A3B-Q4_K_M.gguf (48.2 GB, 48 layers), verified 2026-11-06): You do not need an EPYC server or a $4,000 workstation card to run Qwen3-30B-A3B (18.6GB) or Qwen3-Next-80B-A3B (48.2GB) on a desktop PC. Upstream llama.cpp’s native `--n-cpu-moe N` (`-ncmoe N`) flag keeps 100% of attention layers and the Q8_0 KV cache inside your 12GB/16GB/24GB GPU while offloading only sparse MoE experts for N layers to dual-channel DDR5 RAM—delivering 46–55 tok/s on Qwen3-30B-A3B and 26–33 tok/s on Qwen3-Next-80B-A3B. We also model how 3GB-module GDDR7 refreshes (RTX 5070 SUPER 18GB & RTX 5080 SUPER 24GB, spec-estimate) shift the exact `--n-cpu-moe` threshold. Offline capability is classified as "100% Local Desktop GPU + DDR5 Execution" (All GGUF weights and `--n-cpu-moe` tensor splits run locally across PCIe and system RAM with zero external API calls.), with key operational boundary: The RTX 4070 (12GB), RTX 5060 Ti (16GB), RTX 5070 Ti (16GB), and RTX 4090 (24GB) rows in Table 1 are lab-measured on our Ryzen 9 9900X + DDR5-6400 testbench; the **RTX 5070 SUPER (18GB)** and **RTX 5080 SUPER (24GB)** rows are **SPEC-DERIVED ESTIMATES** based on leaked 3GB (24Gb) GDDR7 module specs and are explicitly labeled `[Spec-Est.]`.
REPRODUCIBILITY MANIFEST // TESTED SPECS & LIMITS
Last Verified: 2026-11-06
Tested Hardware & OS

Measured on: AMD Ryzen 9 9900X + 64GB Dual-Channel DDR5-6400 CL30 (~84 GB/s read) + NVIDIA RTX 4070 (12GB) / RTX 5060 Ti (16GB) / RTX 5070 Ti (16GB) / RTX 4090 (24GB) | Spec-estimate rows: NVIDIA RTX 5070 SUPER (18GB GDDR7 192-bit · ~672 GB/s) & RTX 5080 SUPER (24GB GDDR7 256-bit 32 Gbps · ~1,024 GB/s)

Pinned Stack & Model Versions
llama.cpp b4920+ (upstream native `--n-cpu-moe` / `-ncmoe` & `--cpu-moe` / `-cmoe` support)CUDA 12.8 (`GGML_CUDA=1` + Flash Attention `-fa`)Models: Qwen3-30B-A3B-Q4_K_M.gguf (18.6 GB, 48 layers) & Qwen3-Next-80B-A3B-Q4_K_M.gguf (48.2 GB, 48 layers)
Offline & Network Boundary
100% Local Desktop GPU + DDR5 Execution

All GGUF weights and `--n-cpu-moe` tensor splits run locally across PCIe and system RAM with zero external API calls.

Known Limits & Failure Modes
  • The RTX 4070 (12GB), RTX 5060 Ti (16GB), RTX 5070 Ti (16GB), and RTX 4090 (24GB) rows in Table 1 are lab-measured on our Ryzen 9 9900X + DDR5-6400 testbench; the **RTX 5070 SUPER (18GB)** and **RTX 5080 SUPER (24GB)** rows are **SPEC-DERIVED ESTIMATES** based on leaked 3GB (24Gb) GDDR7 module specs and are explicitly labeled `[Spec-Est.]`.
  • `--n-cpu-moe N` only helps **sparse Mixture-of-Experts (MoE)** models (`Qwen3-30B-A3B`, `Qwen3-Next-80B-A3B`, `DeepSeek-V3/R1`). On dense models (`Qwen3-32B`, `Llama-3.3-70B`), every parameter is active on every token, so offloading to dual-channel DDR5 (~84 GB/s) still drops decode speed into single digits.
Hit an edge-case failure?Open Troubleshooter →

1. Why Upstream `llama.cpp --n-cpu-moe N` Beats Classic Layer Splitting (`-ngl`) by 3.4x

Suppose you have a mainstream **16GB GPU (`RTX 5060 Ti` / `5070 Ti` / `4080`)** and want to run **`Qwen3-30B-A3B-Q4_K_M` (`18.6 GB` weights + `~1.8 GB` KV cache at 32K context = `~21 GB` total)**. With traditional layer offloading (`-ngl 33`), `llama.cpp` pushes layers `0–32` onto the GPU and leaves layers `33–47` **completely on the CPU**—forcing both the heavy multi-head attention + KV cache reads and the MoE routers of those 15 layers onto slow CPU threads (`16.1 tok/s`). In contrast, when you pass **`-ngl 99 --n-cpu-moe 16`** (`-ncmoe 16`), upstream `llama.cpp` keeps **all 48 layers of Dense Attention, KV Cache, and Shared Tensors 100% inside GDDR7 VRAM**, and only moves the **routed MoE expert FFN tensors (`ffn_*_exps.weight`) of the first 16 layers into dual-channel DDR5 RAM**. Because `Qwen3-30B-A3B` only activates **3.3B parameters (~2.0 GB total across all 48 layers)** per token, offloading 16 layers of experts means the CPU only reads **~0.67 GB from DDR5 per token**—skyrocketing decode speed from `16.1 tok/s` to **`54.6 tok/s`** while keeping prefill at **`3,180 tok/s`**!
Run 30B-A3B (18.6GB) or 80B-A3B (48.2GB) on a 16GB GPU + 64GB DDR5 PC using native --n-cpu-moe
# Case A: Fit Qwen3-30B-A3B (18.6GB Q4_K_M) + 32K context on a 16GB GPU (~14.1 GB VRAM used)
./build/bin/llama-server \
  -m ./models/Qwen3-30B-A3B-Q4_K_M.gguf \
  -ngl 99 --n-cpu-moe 16 \
  -fa -ctk q8_0 -ctv q8_0 -c 32768 -t 12

# Case B: Fit Qwen3-Next-80B-A3B (48.2GB Q4_K_M) on a 16GB GPU + 64GB DDR5 RAM (~14.4 GB VRAM + ~36 GB DDR5)
./build/bin/llama-server \
  -m ./models/Qwen3-Next-80B-A3B-Q4_K_M.gguf \
  -ngl 99 --n-cpu-moe 38 \
  -fa -ctk q8_0 -ctv q8_0 -c 32768 -t 12

2. Benchmark Matrix (12GB / 16GB / 24GB Measured) + 3GB-GDDR7 SUPER Refresh Sizing (18GB / 24GB Spec-Estimate)

How many expert layers (`--n-cpu-moe N` out of 48 total layers) should you offload for each VRAM tier, and how much does NVIDIA’s transition from 2GB (16Gb) to **3GB (24Gb) GDDR7 memory ICs** on the rumored/upcoming **RTX 5070 SUPER (18GB · 192-bit)** and **RTX 5080 SUPER (24GB · 256-bit 32 Gbps)** change the math? Each layer of `Qwen3-30B-A3B Q4_K_M` holds **~0.35 GB of routed experts**. Offloading 16 layers saves `~5.6 GB` of VRAM (fitting a 16GB card); on an **18GB RTX 5070 SUPER**, you only need `--n-cpu-moe 6` (or `0` at `IQ4_XS`!), and on a **24GB RTX 5080 SUPER**, the entire 30B-A3B `Q4_K_M` model + 32K KV cache fits **100% inside 1,024 GB/s GDDR7 VRAM (`--n-cpu-moe 0`)**!
Table 1: Native llama.cpp --n-cpu-moe Benchmark on Dual-Channel DDR5-6400 (32K Context, Q8_0 KV) & 18GB/24GB SUPER Sizing
GPU Tier (+ 64GB DDR5-6400)Model (`Q4_K_M`)Optimal FlagVRAM / DDR5 UsedPrefill (`pp2048`)Decode (`tg128`)
RTX 4070 (12GB · 504 GB/s) [Measured]Qwen3-30B-A3B (18.6 GB)`-ngl 99 --n-cpu-moe 26`10.4 GB / 9.8 GB1,640 tok/s**34.8 tok/s** (vs 14.2 w/ `-ngl`)
RTX 5060 Ti (16GB · 448 GB/s) [Measured]Qwen3-30B-A3B (18.6 GB)`-ngl 99 --n-cpu-moe 16`14.1 GB / 6.2 GB1,890 tok/s**46.2 tok/s**
RTX 5070 Ti (16GB · 896 GB/s) [Measured]Qwen3-30B-A3B (18.6 GB)`-ngl 99 --n-cpu-moe 16`14.1 GB / 6.2 GB3,180 tok/s**54.6 tok/s**
**RTX 5070 SUPER (18GB · 672 GB/s) [Spec-Est.]**Qwen3-30B-A3B (18.6 GB)`-ngl 99 --n-cpu-moe 6`~16.4 GB / ~2.5 GB~2,900 tok/s (est.)**~78–86 tok/s (est.)**
**RTX 5080 SUPER (24GB · 1024 GB/s) [Spec-Est.]**Qwen3-30B-A3B (18.6 GB)`-ngl 99 --n-cpu-moe 0` (100% GPU)~20.6 GB / 0 GB~4,400 tok/s (est.)**~120–135 tok/s (est.)**
RTX 5070 Ti (16GB) + 64GB DDR5 [Measured]Qwen3-Next-80B-A3B (48.2 GB)`-ngl 99 --n-cpu-moe 38`14.4 GB / 36.2 GB1,420 tok/s**26.4 tok/s**
RTX 4090 (24GB · 1008 GB/s) [Measured]Qwen3-Next-80B-A3B (48.2 GB)`-ngl 99 --n-cpu-moe 30`21.6 GB / 28.5 GB2,190 tok/s**32.8 tok/s**

3. Quick Formula to Calculate Your Exact `--n-cpu-moe N` Without Trial-and-Error OOMs

Instead of guessing `N` until CUDA crashes, use this two-line rule for 48-layer MoE models (`Qwen3-30B-A3B` has ~0.35 GB of experts per layer; `Qwen3-Next-80B-A3B` has ~0.94 GB of experts per layer at `Q4_K_M`): **1) First compute the fixed GPU footprint (Attention + Shared + 32K Q8_0 KV Cache)**, which is **~3.8 GB** for `30B-A3B` and **~5.1 GB** for `80B-A3B`. **2) Divide your remaining usable VRAM by the per-layer expert size** to find how many expert layers fit on the GPU (`L_gpu`), then set **`--n-cpu-moe = 48 - L_gpu`**! Or simply pass `--cpu-moe` (`-cmoe`) to put all 48 layers’ routed experts in DDR5 RAM while keeping 100% of attention and KV cache on the GPU.
[TIP]Use the embedded script `launch-llama-cpp-n-cpu-moe.sh` below to check your free GPU VRAM and launch `llama-server` with `--n-cpu-moe` and `Q8_0` KV cache.
FIELD Q&A // 常见实测疑问与边界解答

Frequently Asked Questions & Edge Cases

Q: How does `--n-cpu-moe N` compare to `ik_llama.cpp -ot "blk\.[0-9]+\.ffn_.*_exps\.weight=CPU"` from Guide #33?

`--n-cpu-moe N` is built directly into **official upstream `llama.cpp`** and lets you offload **only the first `N` layers of MoE experts** (so your 16GB/24GB GPU still accelerates the remaining `48 - N` layers of experts!), whereas a wildcard `-ot "blk\.[0-9]+..."` offloads all layers unless you write complex layer-range regexes. For 12GB–24GB desktop PCs running 30B–80B MoE models, `--n-cpu-moe N` is much simpler and works out of the box.

Q: Can I use `--n-cpu-moe` inside Ollama as well?

Recent Ollama builds inherit `llama.cpp`’s MoE tensor-offload heuristics when a model exceeds VRAM, but `llama-server` gives you explicit deterministic control via `--n-cpu-moe N` (so Ollama never accidentally offloads full attention layers to CPU when VRAM gets tight).

REPRODUCIBLE ARTIFACT // 配套可参数化附件

llama.cpp Native --n-cpu-moe Hybrid GPU+DDR5 MoE Launcher (12GB–24GB VRAM)

Audits free GPU VRAM via nvidia-smi, keeps 100% of attention layers and Q8_0 KV cache on GPU (-ngl 99 -fa), and offloads exact N MoE expert layers to dual-channel DDR5 RAM via --n-cpu-moe.

launch-llama-cpp-n-cpu-moe.sh ↗
Edit variables above to update the configuration live
#!/usr/bin/env bash
# Tinker AI — Mainstream 12GB–24GB GPU + Dual-Channel DDR5 MoE Offload Launcher (Guide #40)
set -euo pipefail

MODEL="./models/Qwen3-30B-A3B-Q4_K_M.gguf"
NCMOE="16"
THREADS="12"
CTX="32768"

echo "=== [1/3] Checking GPU Free VRAM & PCIe Link State ==="
if command -v nvidia-smi >/dev/null 2>&1; then
  nvidia-smi --query-gpu=name,memory.total,memory.free,pcie.link.gen.current,pcie.link.width.current --format=csv
fi

echo "=== [2/3] Verifying llama-server Supports Native --n-cpu-moe ==="
./build/bin/llama-server --help 2>&1 | grep -E -- "--n-cpu-moe|-ncmoe" | head -n 2

echo "=== [3/3] Starting Hybrid MoE Server (-ngl 99 --n-cpu-moe $NCMOE, Attention+KV on GPU, $NCMOE Expert Layers in DDR5) ==="
./build/bin/llama-server \
  -m "$MODEL" \
  -ngl 99 \
  --n-cpu-moe "$NCMOE" \
  -fa -ctk q8_0 -ctv q8_0 \
  -c "$CTX" -t "$THREADS" \
  --host 0.0.0.0 --port 8080

More Reproducible Engineering Guides

View All 42 Guides →