AMD EPYC 12-Channel DDR5 + Single GPU Hybrid MoE Benchmark: Running DeepSeek-R1-671B & Qwen3-235B-A22B via KTransformers & ik_llama.cpp (-ot)
How to run full 671B and 235B sparse MoE models at 14–27 tok/s without a $10,000 Mac Studio or multi-GPU cluster: pinning MLA Attention & KV Cache onto a single 24GB/32GB GPU while streaming routed experts across 12-channel DDR5 EPYC RAM (~460 GB/s) using ik_llama.cpp (-ot) and KTransformers.
AMD EPYC 9374F / 9554P (32C/64C Zen 4 · 12x 48GB DDR5-4800 ECC = 576GB @ ~460 GB/s) + 1x NVIDIA RTX 5090 (32GB) or RTX 4090 (24GB)
All GGUF weights reside on local PCIe 4.0/5.0 NVMe RAID and execute completely offline without external API or telemetry calls.
- Hybrid CPU+GPU MoE offloading only accelerates **sparse MoE architectures** (`DeepSeek-R1-671B` with 37B active, `Qwen3-235B-A22B` with 22B active, `Qwen3-Next-80B-A3B` with 3B active); dense 70B/405B models read 100% of weights on every token and remain capped at ~5–8 tok/s on DDR5.
- Leaving Linux Auto-NUMA balancing enabled (`kernel.numa_balancing=1`) or spawning threads across SMT hyperthreads causes 50%–65% decode speed degradation due to cross-CCD page migration stalls.
1. Why Hybrid CPU+GPU Disaggregation Works: GPU Holds MLA Attention, 12-Channel DDR5 Streams Routed Experts
# 1. CRITICAL: Disable Linux Auto-NUMA page migration (prevents 55% cross-CCD slowdown): sudo sysctl -w kernel.numa_balancing=0 sync && echo 3 | sudo tee /proc/sys/vm/drop_caches # 2. Build ik_llama.cpp with CUDA + native zen4 AVX-512 + FlashMLA support: cmake -B build -DGGML_CUDA=ON -DGGML_NATIVE=ON -DGGML_AVX512=ON -DCMAKE_BUILD_TYPE=Release cmake --build build --config Release -j $(nproc) # 3. Run DeepSeek-R1-671B (IQ4_XS): Attention/KV on 1x GPU (-ngl 99), Routed Experts on 12-ch DDR5 (-ot): numactl --interleave=all ./build/bin/llama-server \ -m /mnt/nvme/models/DeepSeek-R1-671B-IQ4_XS.gguf \ -ngl 99 \ -ot "blk\.[0-9]+\.ffn_.*_exps\.weight=CPU" \ -mla 3 -fa -fmoe \ -ctk q8_0 -ctv q8_0 -c 32768 -t 32 --port 8080
2. Verified Benchmark Table: `ik_llama.cpp` (`-ot`) vs `KTransformers` vs Mainline `llama.cpp`
| Model & Quantization | Runtime Engine & GPU | VRAM / RAM Used | Prefill (`pp2048`) | Decode (`tg128`) | Wall Power |
|---|---|---|---|---|---|
| DeepSeek-R1-671B (`Q4_K_M` · 404GB) | Mainline `llama.cpp` + RTX 4090 (24GB) | 21.8 GB / 386 GB | 118 tok/s | 9.4 tok/s | 445 W |
| DeepSeek-R1-671B (`IQ4_XS` · 355GB) | **`ik_llama.cpp` (`-mla 3 -fmoe`) + RTX 4090** | **18.4 GB / 341 GB** | **295 tok/s (2.5x)** | **15.8 tok/s (+68%)** | 460 W |
| DeepSeek-R1-671B (`Q4_K_M` + FP8 Attn) | **`KTransformers 0.2.4` + RTX 5090 (32GB)** | 26.2 GB / 382 GB | **380 tok/s** | **17.4 tok/s** | 520 W |
| Qwen3-235B-A22B MoE (`Q4_K_M` · 143GB) | **`ik_llama.cpp` (`-ot exps=CPU`) + RTX 5090** | 19.6 GB / 128 GB | **510 tok/s** | **26.4 tok/s** | 475 W |
3. BIOS & Kernel Tuning Checklist: `NPS=1`, 12-Channel Population & Physical Core Pinning
Frequently Asked Questions & Edge Cases
Q: Should I choose `ik_llama.cpp` or `KTransformers` for a hybrid EPYC + RTX GPU server?
Choose **`ik_llama.cpp`** if you want a single self-contained C++ binary (`llama-server`) that reads standard single-file GGUFs, supports `-mla 3` compressed KV cache on 24GB GPUs, and requires zero Python/PyTorch compilation. Choose **`KTransformers`** if you run an Intel Xeon Sapphire/Granite Rapids server with **AMX instructions** or want multi-concurrency continuous batching with FP8 GPU attention.
Q: Can I use a dual-socket EPYC server (24 channels of DDR5) to double DeepSeek-R1-671B speed to 30+ tok/s?
A dual-socket EPYC server reaches **~21–24 tok/s** (about +35% to +45% over single-socket, not 2.0x) because cross-socket xGMI (Infinity Fabric) links add latency when gathering partial expert sums between Socket 0 and Socket 1. Make sure `kernel.numa_balancing=0` is set, or dual-socket will actually run slower than single-socket!
AMD EPYC 12-Ch DDR5 + Single GPU Hybrid MoE (`ik_llama.cpp` `-ot` & `KTransformers`) Launcher
Disables Linux auto-NUMA page migration, checks 12-channel DDR5 NUMA topology, and launches 671B/235B MoE models with MLA attention + KV Cache on GPU and routed experts on CPU RAM.
#!/usr/bin/env bash
# Tinker AI — AMD EPYC 12-Channel DDR5 + Single GPU Hybrid MoE Launcher (Guide #33)
set -euo pipefail
ENGINE="ik_llama"
MODEL_PATH="/mnt/nvme/models/DeepSeek-R1-671B-IQ4_XS.gguf"
THREADS="32"
CTX="32768"
echo "=== [1/3] Auditing NUMA Topology & Disabling Linux Auto-NUMA Thrashing ==="
sudo sysctl -w kernel.numa_balancing=0 >/dev/null || true
numactl --hardware | head -n 10 || true
echo "=== [2/3] Flushing VFS Page Cache Before Mapping 250GB–400GB MoE Weights ==="
sync && echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null
echo "=== [3/3] Launching Hybrid GPU (Attention+KV) + CPU (MoE Experts) Engine: $ENGINE ==="
if [ "$ENGINE" = "ktransformers" ]; then
export USE_NUMA=1
python3 -m ktransformers.server.main \
--gguf_path "$(dirname "$MODEL_PATH")" \
--cpu_infer "$THREADS" \
--max_new_tokens 4096 \
--cache_lens "$CTX" \
--port 8080
else
# ik_llama.cpp: -ngl 99 puts shared/attention layers on GPU, while -ot offloads routed MoE experts to 12-ch DDR5 CPU
numactl --interleave=all ./build/bin/llama-server \
-m "$MODEL_PATH" \
-ngl 99 \
-ot "blk\.[0-9]+\.ffn_.*_exps\.weight=CPU" \
-fa -ctk q8_0 -ctv q8_0 \
-c "$CTX" -t "$THREADS" \
--host 0.0.0.0 --port 8080
fi