Apple M6 MacBook Pro (16GB / 24GB / 32GB) for Local LLMs: Which Memory Tier, Which Models, and Why the Dual Neural Engine Does Not Speed Up llama.cpp
The new 2nm M6 brings per-core GPU Neural Accelerators, a dual 16-core Neural Engine, and 153 GB/s (16GB) or 170 GB/s (24/32GB) of memory bandwidth. For local LLMs the decisive spec is the memory tier: 16GB is an 8B-class machine, 24GB is a 14B machine, and 32GB is the only tier that comfortably runs Qwen3-30B-A3B. The Neural Engine is not used by llama.cpp, Ollama, or MLX — buy for memory, not for NPU TOPS.
Spec basis (not lab-measured): 14-inch MacBook Pro with base Apple M6 (TSMC N2 · 12-core CPU: 2 super + 4 performance + 6 efficiency · 12-core GPU with per-core Neural Accelerators · dual 16-core Neural Engine · 16GB @ 153 GB/s, 24GB/32GB @ 170 GB/s, as reported at launch)
llama.cpp / Ollama / MLX inference runs entirely on-device. Apple Intelligence features that hand off to Private Cloud Compute are not part of this guide.
- Evidence level: SPEC-DERIVED ESTIMATE. Tok/s figures are computed from published bandwidth (× 0.68 efficiency), not measured on an M6 in our lab. Run the attached script and replace them with your numbers.
- macOS caps GPU-wired memory at roughly two-thirds to three-quarters of RAM by default. Raising `iogpu.wired_limit_mb` helps on 32GB but leaves less headroom for the OS, browser, and IDE; it resets on reboot.
- The dual 16-core Neural Engine is only reachable via Core ML / Apple Foundation Models. llama.cpp, Ollama and MLX run on the GPU; their speed is governed by memory bandwidth (decode) and GPU Neural Accelerators (prefill, MLX/Metal 4 path).
1. NPU TOPS vs GPU Neural Accelerators vs Memory Bandwidth: What Each One Actually Speeds Up
| M6 feature | Used by llama.cpp / Ollama? | Used by MLX? | Affects |
|---|---|---|---|
| Unified memory capacity (16/24/32GB) | Yes | Yes | Which models fit; max context length |
| Memory bandwidth (153 / 170 GB/s) | Yes | Yes | Decode tok/s (generation speed) |
| GPU Neural Accelerators (per core) | Partially (Metal backend, version-dependent) | Yes (Metal 4 tensor ops) | Prefill / time-to-first-token |
| Dual 16-core Neural Engine | No | No | Apple Intelligence, Core ML apps only |
2. Memory-Tier Sizing: What Fits, and Estimated Decode Speed
| Model | Weights (Q4_K_M) | M6 16GB (153 GB/s) | M6 24GB (170 GB/s) | M6 32GB (170 GB/s) |
|---|---|---|---|---|
| Qwen3-8B | ~5.0 GB | fits · ~21 tok/s | fits · ~23 tok/s | fits · ~23 tok/s |
| Qwen3-14B | ~9.0 GB | tight (apps closed) · ~11 tok/s | fits · ~13 tok/s | fits · ~13 tok/s |
| Gemma 3 27B | ~16.5 GB | does not fit | tight / swap risk · ~7 tok/s | fits · ~7 tok/s |
| Qwen3-30B-A3B (MoE, ~3B active) | ~18.6 GB | does not fit | does not fit (spills to swap) | fits · ~55 tok/s |
| Qwen3-32B (dense) | ~19.8 GB | does not fit | does not fit | tight (raise wired limit) · ~6 tok/s |
3. Reproduce on Your Own M6: Wired Limit, Fixed Benchmark, Swap Check
# 1) Inspect / raise the GPU wired-memory limit (resets on reboot) sysctl iogpu.wired_limit_mb # 0 = macOS default (~2/3–3/4 of RAM) sudo sysctl iogpu.wired_limit_mb=26624 # 32GB M6 only: allow ~26GB for Metal # 2) Fixed benchmark: prompt 2048 / generate 128, 3 reps, flash attention, Q8_0 KV vm_stat | grep -E "Swapins|Swapouts" # record BEFORE ./llama-bench -m Qwen3-30B-A3B-Q4_K_M.gguf -ngl 99 -fa 1 \ -ctk q8_0 -ctv q8_0 -p 2048 -n 128 -r 3 -o md vm_stat | grep -E "Swapins|Swapouts" # record AFTER — must not grow # 3) Optional: compare MLX on the same model (uses GPU Neural Accelerators for prefill) pip install -U mlx-lm mlx_lm.generate --model mlx-community/Qwen3-30B-A3B-4bit \ --prompt "Summarize the trade-offs of unified memory for local LLMs." --max-tokens 256
Frequently Asked Questions & Edge Cases
Q: Should I wait for M6 Pro / M6 Max instead of buying the base M6 for local AI?
If your target is 30B-class MoE or 14B dense models, a 32GB base M6 is a reasonable portable machine. If you want 70B dense models or 100B+ MoE, no base-chip memory tier is large enough — you need a Max-class chip (wider bus, 64–128GB) or a desktop such as Mac Studio. See our M5 Max and M3 Ultra guides for those tiers.
Q: Is the M6 much faster than the M5 for local LLMs?
For decode, expect at most around the bandwidth difference (~10% on the 24/32GB configs), since token generation is bandwidth-bound. Prefill gains depend on how well your runtime uses the GPU Neural Accelerators; MLX benefits most. If you already own a 32GB M5 machine, upgrading for LLM speed alone is hard to justify.
Apple M6 MacBook Pro Memory-Tier Benchmark (wired limit + swap guard)
Records chip and memory tier, optionally raises iogpu.wired_limit_mb, runs a fixed llama-bench with Q8_0 KV cache, and flags the result as invalid if macOS swapped during the run.
#!/usr/bin/env bash
# Tinker AI — Apple M6 MacBook Pro Memory-Tier Benchmark (Guide #38)
set -euo pipefail
MODEL="./models/Qwen3-14B-Q4_K_M.gguf"
WIRED="0"
PROMPT_TOKENS="2048"
echo "=== [1/4] Chip & memory tier ==="
system_profiler SPHardwareDataType | grep -E "Chip|Memory"
echo "=== [2/4] GPU wired-memory limit ==="
if [ "$WIRED" != "0" ]; then
sudo sysctl iogpu.wired_limit_mb="$WIRED"
fi
sysctl iogpu.wired_limit_mb
swapins() { vm_stat | awk '/Swapins/ {gsub("\\.","",$2); print $2}'; }
BEFORE=$(swapins)
echo "=== [3/4] llama-bench pp$PROMPT_TOKENS / tg128 x3, Q8_0 KV ==="
llama-bench -m "$MODEL" -ngl 99 -fa 1 -ctk q8_0 -ctv q8_0 -p "$PROMPT_TOKENS" -n 128 -r 3 -o md
AFTER=$(swapins)
echo "=== [4/4] Swap guard ==="
if [ "$AFTER" -gt "$BEFORE" ]; then
echo "[INVALID] macOS swapped $((AFTER - BEFORE)) pages during the run — this model is too large for this memory tier."
else
echo "[OK] No swap during benchmark — result is valid for this memory tier."
fi