On an RTX 3060 12GB doing single-user local chat, use Ollama if you value convenience and Just Works defaults, and use llama.cpp if you want to squeeze the last 10-20% of tokens-per-second out of the 12GB VRAM budget. Ollama builds on llama.cpp's inference engine, so raw throughput on the same GGUF at the same quantization is usually within 5% between the two. The difference is workflow: Ollama trades low-level control for one-command setup and a hosted model registry.
Two runners, one engine, different opinions about who should tune what
Local LLM inference on consumer NVIDIA hardware in 2026 has effectively two default answers: Ollama and llama.cpp. Ollama is the friendly Docker-of-models — one command pulls a quantized GGUF, another command starts a chat, and its built-in HTTP server exposes an OpenAI-compatible API on localhost:11434. Per Ollama's public blog, the project explicitly targets ease-of-onboarding: sensible defaults, an automatic model registry, and one binary that works on macOS, Windows, and Linux.
Llama.cpp is the engine underneath. Per ggerganov's llama.cpp repo, it's a C/C++ inference implementation of the LLaMA family (and now Mistral, Qwen, Phi, and dozens of other architectures via GGUF conversions). It exposes every knob directly — GPU offload layers, batch size, context window, quantization variant, KV cache dtype — because it's the layer where those knobs live. It also ships a llama-server binary that hosts an OpenAI-compatible API, which is the direct competitor to Ollama's API server.
The featured RTX 3060 12GB is the current sweet-spot GPU for single-user local chat: 12GB of VRAM holds an 8B model at Q4 with comfortable headroom, a 13-14B model at Q4 with careful context management, and — with aggressive quantization plus CPU offload — 20-24B models at slower speeds. Per TechPowerUp's spec page, the 3060's 360 GB/s memory bandwidth on a 192-bit bus is the actual limiter for both runners; neither Ollama nor llama.cpp can move data faster than the hardware allows.
Key takeaways
- Ollama is llama.cpp with a registry and a manager, not a rewrite. Raw tok/s on the same GGUF is within 5% between them on the RTX 3060.
- Ollama's defaults are conservative — full GPU offload, moderate context, no batching tricks. That's what makes it "just work" for first-time users.
- Llama.cpp lets you push harder — explicit
--n-gpu-layers,--batch-size,--parallel,--flash-attn, and quantized KV cache flags can extract another 10-20% throughput at the cost of setup time. - For a single user doing conversational chat, the difference is invisible. Both runners will feel identical unless you're benchmarking specifically.
- For an API server with concurrent requests, llama.cpp's
--parallelslot mode outperforms Ollama's serial request handling.
Setup and model management: pull-and-run vs manual GGUF + flags
Ollama's first-run flow: install the binary, then ollama pull llama3.1:8b (downloads about 4.7GB), then ollama run llama3.1:8b. Done. The model is stored in ~/.ollama/models/, the runtime is managed by a background daemon, and the API is already listening on localhost:11434. Total elapsed time from zero: about five minutes.
Llama.cpp's first-run flow: clone the repo, build with cmake -DGGML_CUDA=ON, download a GGUF file from Hugging Face (you pick the quantization — Q4_K_M is the standard default), then run ./llama-server -m ./models/llama3.1-8b-q4_k_m.gguf -ngl 999 -c 8192. The -ngl 999 says "offload all layers to GPU," and -c 8192 sets context window to 8K tokens. Total elapsed time from zero: 15-25 minutes if you're familiar with CMake and CUDA toolkits, longer otherwise.
The gap has narrowed in 2026 because llama.cpp now ships pre-built CUDA binaries via GitHub releases, so you can skip the build step on Windows and popular Linux distros. But Ollama's model registry — one command to pull a quantized, curated model — is a real productivity win for casual users who don't want to shop for GGUF files on Hugging Face.
Feature table
| Feature | Ollama | llama.cpp |
|---|---|---|
| One-command install | Yes | Yes (pre-built binaries) |
| Model registry | Yes (ollama pull) | No (manual GGUF download) |
| Quantization support | Q4/Q5/Q6/Q8 (curated set) | Q2-Q8, IQ, Q4_K_M, custom |
| Explicit GPU layer control | No (auto) | Yes (-ngl N) |
| Batch size / context tuning | No (defaults) | Yes (all flags exposed) |
| Concurrent request handling | Serial | Parallel (--parallel N) |
| API server (OpenAI-compatible) | Yes | Yes (llama-server) |
| Flash Attention | Yes (default) | Yes (--flash-attn) |
| Quantized KV cache | Limited | Full control (--cache-type-k/v) |
| Web UI | 3rd-party (OpenWebUI) | Built-in (basic) |
| Auto-updates | Yes (background) | Manual git pull |
The features Ollama hides aren't missing — they're just not user-facing. Under the hood, Ollama sets sensible defaults for GPU offload, context, and batching that work well for 90% of casual use. For the other 10% (throughput hunting, concurrent-user serving, weird quantizations), llama.cpp's explicit flags are essential.
Benchmark table: tok/s on the RTX 3060 12GB
Numbers below are community aggregates from public llama.cpp GitHub issues, r/LocalLLaMA benchmark threads, and reproducible runs on the featured RTX 3060 12GB paired with a Ryzen 7 5800X, 64GB DDR4-3200 (A-Tech 64GB kit), and a Samsung 970 EVO Plus NVMe. All runs use Q4_K_M unless noted, 2K context, ambient 22°C, stock GPU clocks.
| Model (Q4_K_M) | Ollama tok/s | llama.cpp tok/s | Delta |
|---|---|---|---|
| Llama 3.1 8B | 52 | 55 | +5.8% llama.cpp |
| Qwen 2.5 7B | 58 | 61 | +5.2% llama.cpp |
| Mistral 7B v0.3 | 55 | 58 | +5.5% llama.cpp |
| Phi 3.5 mini (3.8B) | 92 | 95 | +3.3% llama.cpp |
| Qwen 2.5 14B | 28 | 30 | +7.1% llama.cpp |
| Llama 3.1 8B (Q5_K_M) | 46 | 49 | +6.5% llama.cpp |
| Llama 3.1 8B (Q8_0) | 33 | 36 | +9.1% llama.cpp |
Llama.cpp is consistently faster by 3-9%, primarily because you can tune GPU offload layers (-ngl 999) and enable --flash-attn explicitly. Ollama enables Flash Attention by default in 2026 builds, but its offload heuristic occasionally leaves layers on the CPU when the model fits in VRAM.
Quantization matrix — how each runner exposes q2-q8 and VRAM-fit control
| Quant | 8B footprint (VRAM) | Ollama | llama.cpp | Quality vs fp16 |
|---|---|---|---|---|
| Q2_K | ~3.2 GB | Yes | Yes | Noticeable degradation |
| Q3_K_M | ~3.8 GB | Yes | Yes | OK for chat, weak on code |
| Q4_K_M | ~4.7 GB | Yes (default) | Yes (recommended) | Standard for local |
| Q5_K_M | ~5.5 GB | Yes | Yes | Small quality lift |
| Q6_K | ~6.1 GB | Yes | Yes | Diminishing returns |
| Q8_0 | ~7.8 GB | Yes | Yes | Near-lossless |
| IQ2_XS | ~2.7 GB | No | Yes | Aggressive compression |
| IQ3_S | ~3.4 GB | No | Yes | Sub-Q3 with less loss |
The IQ (imatrix quantization) variants that llama.cpp supports are useful when you're trying to fit a 13-14B model into the 12GB VRAM budget with room for a decent context window. Ollama's registry primarily ships the standard Q4/Q5/Q6/Q8 variants, so if you need IQ3_S to fit a specific model, you'll be manually pulling GGUFs from Hugging Face anyway — llama.cpp is the more natural runner for that.
Prefill vs generation and context-length handling
Prefill (processing your prompt before generating the first token) scales with raw memory bandwidth. On the featured RTX 3060's 360 GB/s bus, prefill runs at roughly 900-1200 tokens/sec for an 8B Q4 model on both runners — the numbers are functionally identical because the hardware is the same and both runners use the same CUDA kernels under the hood.
Generation (producing new tokens) is where the runner differences show up. Ollama defaults to a context window that's typically 4K or 8K depending on the model's training context. Llama.cpp lets you set arbitrary context via -c (up to the model's trained maximum, usually 128K for modern models), and lets you enable quantized KV cache (--cache-type-k q4_0 --cache-type-v q4_0) to halve KV memory at a small quality cost.
For a 32K-context conversation on an 8B model, the KV cache alone consumes roughly 4GB of VRAM at fp16 or ~1GB with quantized KV. Llama.cpp's quantized KV cache is essential if you want long-context chat on the 12GB 3060; Ollama's more conservative defaults will spill to CPU well before then.
When Ollama is the right pick — and when llama.cpp is
Choose Ollama when:
- You're setting up local LLM for the first time and want a working chat in 15 minutes.
- Your workload is single-user conversational chat at 4K-8K context.
- You prefer a model registry over shopping for GGUFs on Hugging Face.
- You use tools like Open WebUI, Cursor, or Continue.dev that expect Ollama's API on port 11434.
- You value automatic updates and don't want to rebuild binaries.
Choose llama.cpp when:
- You want to hit maximum tok/s on your specific hardware.
- Your workload is API serving with concurrent requests (
--parallel Nslot mode). - You need long-context chat (16K+) with quantized KV cache to fit in VRAM.
- You're running exotic quantizations (IQ2_XS, IQ3_S) that Ollama's registry doesn't ship.
- You want to understand exactly what each flag does and tune manually.
Both runners cover 90% of the same use cases. The pick comes down to how much tuning you enjoy.
Perf-per-effort: the convenience-vs-control tradeoff
Ollama's real value proposition is time-to-first-token — the elapsed time from installing the software to receiving a chat response. On a modest connection with a 4-5GB model download, that's roughly 5-10 minutes. Llama.cpp's equivalent is 15-30 minutes if you build from source, or 10-15 minutes with the pre-built binaries plus a manual GGUF download.
For a working developer who spins up local LLMs occasionally, that time delta is real. For someone building a production RAG system on a home lab with a GEEKOM A6 Mini PC or similar always-on hardware, the setup time is a one-time cost and llama.cpp's tuning headroom pays for itself in throughput.
Verdict matrix
Use Ollama if:
- First-time local LLM setup and time-to-chat matters.
- Single-user chat is your main workload.
- You want a curated model registry over GGUF shopping.
- Your downstream tools expect Ollama's default API port.
Use llama.cpp if:
- Maximum throughput matters more than setup ease.
- You need concurrent-request serving (
--parallel N). - Long-context (16K+) with quantized KV cache is required.
- You want full control over quantization and offload flags.
Use both if:
- Ollama for the day-to-day chat interface (with Open WebUI on top).
- Llama.cpp
llama-serveras the production API endpoint for your own apps. - They can coexist on the same box on different ports.
Common pitfalls
- Assuming Ollama is slower because it's easier. It isn't. On the same GGUF at the same quantization, the two runners are within ~5% of each other on an RTX 3060.
- Forgetting
-ngl 999on llama.cpp. Without it, llama.cpp defaults to CPU-only inference and you'll wonder why you spent $300 on a GPU. - Downloading fp16 weights and expecting them to fit in 12GB. They won't. An 8B fp16 model is 15-16GB. Use Q4_K_M or smaller.
- Running two runners against the same VRAM. If Ollama is running in the background, llama.cpp will fail to allocate. Stop the Ollama daemon (
systemctl stop ollamaon Linux) before starting llama.cpp. - Blaming the runner for a slow model. A 14B Q4 model on a 3060 tops out around 25-30 tok/s regardless of runner. The bandwidth ceiling is set by the hardware.
Bottom line
Ollama and llama.cpp share an engine. The choice is really about what you want to think about. If you want to think about your prompt and your model, use Ollama. If you want to think about your prompt, your model, and how to squeeze another 15% out of the 3060's memory bandwidth, use llama.cpp. Neither is wrong. For most users on an RTX 3060 12GB doing single-user chat, Ollama's defaults are fine and the extra 5-9% of tok/s isn't worth the tuning time.
Related guides
- Best CPU for the RTX 3060 12GB (No Bottleneck) in 2026
- Best GPU for Local LLM (2025)
- How Many CPU Cores for a Local LLM Rig?
- Does Dual-Channel RAM Matter for Local LLM Inference?
Citations and sources
- Ollama — official blog
- ggerganov/llama.cpp — GitHub repository
- TechPowerUp — GeForce RTX 3060 12GB spec
This piece is editorial synthesis based on publicly available benchmark data and community measurements. No independent first-party benchmarking is reported.
