NVIDIA PC Model Loading & VRAM Diagnostics: Spotting PCIe Shared-Memory Spillover
Why a 12GB RTX GPU silently drops from 48 tok/s to 4 tok/s without throwing an OOM error—and how to cross-check nvidia-smi against ollama ps.
NVIDIA RTX 4070 12GB VRAM · 32GB DDR5 System RAM · Ubuntu 24.04 & Windows 11 WSL2
All diagnostics use local `nvidia-smi` and `ollama ps` queries without external dependencies.
- Modern NVIDIA drivers enable CUDA Sysmem Fallback by default: exceeding physical 12GB VRAM by even 600MB pages tensors over PCIe into DDR5 RAM, slashing speed 8–10x without crashing.
- Running an embedding model (`bge-m3`) alongside a 14B Q4_K_M chat model on a 12GB card leaves less than 1.1GB for KV cache, triggering layer spill at num_ctx > 4096.
1. Cross-Checking `nvidia-smi` vs `ollama ps` to Catch Layer Spillover
| Workload Configuration | Total Memory Needed | ollama ps Split | Measured Speed |
|---|---|---|---|
| qwen2.5:7b Q4_K_M @ 16K ctx (f16 KV) | 6.4 GB | 100% GPU (28/28 layers) | 78.5 tok/s |
| qwen2.5:14b Q4_K_M @ 4K ctx (f16 KV) | 10.4 GB | 100% GPU (48/48 layers) | 46.8 tok/s |
| qwen2.5:14b Q4_K_M @ 16K ctx (q8_0 KV) | 11.1 GB | 100% GPU (48/48 layers) | 42.1 tok/s |
| qwen2.5:14b Q4_K_M @ 32K ctx (f16 KV) | 14.9 GB (Spills +2.9GB) | 26% CPU / 74% GPU | 4.9 tok/s (9.5x slower) |
# 1. Check how many layers are on GPU vs CPU ollama ps # 2. Check physical VRAM saturation and compute utilization nvidia-smi --query-gpu=name,memory.total,memory.used,memory.free,utilization.gpu --format=csv
2. Fitting 14B on 12GB VRAM & Fixing Docker GPU Passthrough
# 1. Wire NVIDIA runtime into Docker Engine and restart daemon sudo nvidia-ctk runtime configure --runtime=docker sudo systemctl restart docker # 2. Verify container can see physical GPU VRAM docker run --rm --gpus all nvidia/cuda:12.6.0-base-ubuntu24.04 nvidia-smi
3. WSL2 vs Native Linux VRAM Overhead & Desktop Compositor Reserve
Frequently Asked Questions & Edge Cases
Q: Why does Windows Task Manager show "Shared GPU Memory" increasing when speed drops?
"Shared GPU Memory" is regular DDR4/DDR5 system RAM accessed over the PCIe bus (~32 GB/s vs 504 GB/s GDDR6X). In NVIDIA Control Panel -> Manage 3D Settings -> CUDA - Sysmem Fallback Policy, you can disable shared memory fallback if you prefer an immediate OOM error over silent 10x slowdown.
Q: How do I force Ollama to use only one specific GPU on a multi-GPU PC?
Set `CUDA_VISIBLE_DEVICES=0` (or the UUID shown in `nvidia-smi -L`) in the Ollama service environment. Using the GPU UUID (`GPU-xxxxxxxx-...`) prevents device index shifts after driver updates or PCIe slot changes.
NVIDIA PC Model Loading & PCIe Shared-Memory Spillover Probe
Compares physical VRAM usage in nvidia-smi against ollama ps processor split to detect silent CPU/PCIe fallback.
#!/usr/bin/env bash
# Tinker AI — NVIDIA PC Model Loading & VRAM Spillover Diagnostic (Guide #2)
set -euo pipefail
MODEL="qwen2.5:14b-instruct-q4_K_M"
CTX="16384"
echo "=== [1/4] NVIDIA Driver, CUDA & Physical VRAM Baseline ==="
nvidia-smi --query-gpu=name,driver_version,memory.total,memory.used,memory.free --format=csv
echo "=== [2/4] Triggering Model Load ($MODEL @ num_ctx=$CTX) ==="
curl -sS http://127.0.0.1:11434/api/generate -d "{
\"model\": \"$MODEL\",
\"prompt\": \"Warmup VRAM allocation check.\",
\"stream\": false,
\"options\": { \"num_ctx\": $CTX }
}" > /dev/null
echo "=== [3/4] Inspecting Layer Offload Split (Look for 100% GPU vs CPU/GPU Split) ==="
ollama ps
echo "=== [4/4] Post-Load Physical VRAM Utilization ==="
nvidia-smi --query-gpu=memory.used,memory.free,utilization.gpu --format=csv