Performance Tuning Ollama and Local LLMs Without Guesswork
The short answer: establish a repeatable baseline, make the model and context fit the available memory, verify where Ollama placed the workload, and change one control at a time. Do not buy hardware or declare a winning setting from one warm run.
This guide is for a beginner or homelab operator who already has Ollama running and can use the command line. You will learn to separate model-load time, prompt processing, token generation, memory placement, concurrency, and competing workloads so a rollback is obvious when tuning makes performance worse.
Before You Tune
- Record the Ollama version, operating system, driver, GPU and VRAM, system RAM, model tag or digest, quantization, context, and power mode.
- Save the current service override and model configuration before editing them.
- Choose a fixed prompt set that represents short chat, long input, and the real task you care about.
- Decide which matters most: first-response latency, prompt throughput, generation throughput, quality, concurrency, power, or coexistence with other services.
- Stop unrelated benchmark noise, but also run a separate contention test if the server normally hosts media or camera workloads.
Local AI performance tuning is mostly about avoiding bad fits. The current Ollama behavior and documentation in this article were checked on July 15, 2026; context defaults, environment variables, model tags, and hardware support require a publication-day recheck.
Beginners often assume the fix is "use a bigger model" or "turn every setting all the way up." In practice, the best local AI setup is the one that fits comfortably in memory, stays on the GPU when possible, and does not force your computer into constant swapping or CPU fallback.
This guide uses Ollama as the main example, but the same ideas apply to many local LLM runners.
The goal is not to chase benchmark records. The goal is to make your homelab AI feel steady, predictable, and usable.
The Simple Performance Rule
Interactive Performance Tuning Flow
Click each step to see what it means in a beginner-friendly local AI setup.
Choose a box above to view details.
For most home users, local LLM speed depends on five things:
| Setting or resource | What it means | Beginner takeaway |
|---|---|---|
| Model size | How many parameters the model has, such as 7B, 8B, 13B, or 70B | Bigger models usually need more RAM or VRAM |
| Quantization | How compressed the model weights are | Lower quantization uses less memory but may lose quality |
| Context length | How much text the model can keep in memory at once | Higher context can use much more memory |
| GPU offload | How much of the model runs on the GPU | More GPU use is usually faster if it fits |
| Concurrency | How many models or requests run at once | More parallel work uses more memory |
If you remember one thing, remember this:
Start with a smaller model, a modest context length, and full GPU offload. Then increase settings one at a time.
Check What Is Happening First
Before changing settings, get a baseline. Run a model, ask it a short question, and watch where the work is going.
ollama run llama3.2
In another terminal, check what Ollama has loaded:
ollama ps
Look at the PROCESSOR column. If it says something like 100% GPU, that model is fully loaded on the GPU. If it shows a CPU/GPU split, part of the work is happening on the CPU. If it shows CPU only, expect slower responses.
On an NVIDIA system, watch VRAM while the model loads and answers:
watch -n 1 nvidia-smi
For a quick CPU and system memory view:
free -h
htop
If you use AMD or Intel graphics, the exact monitoring tools are different. AMD users commonly check rocm-smi. Intel users may use intel_gpu_top if it is installed. The important idea is the same: watch memory, GPU activity, CPU activity, and temperature while the model is running.
Tune Context Length Carefully
Context length is how many tokens the model can keep in its working memory. A token is roughly a piece of a word. More context lets the model consider more chat history, documents, or code, but it also increases memory use.
As checked on July 15, 2026, Ollama's context-length documentation lists tiered defaults: 4K below 24 GiB of VRAM, 32K from 24 through 48 GiB, and 256K at 48 GiB or more. Those are documented defaults, not proof that the default is fast, that a particular model uses its full advertised context effectively, or that other GPU workloads will still fit.
| Workload question | Decision | Validation |
|---|---|---|
| How many input tokens does the real task need? | Choose the smallest context that contains the required prompt, history, retrieved text, and output allowance. | Test near the expected upper bound, not only with a one-line prompt. |
| Does the model still fit where you expect? | Reduce context if allocation pushes work to a slower processor split you did not intend. | Check ollama ps, API process data, system memory, and GPU memory under load. |
| Does longer context improve the answer? | Keep it only when task scoring improves enough to justify latency and memory. | Run the same long-input cases at both settings and inspect omitted or invented details. |
| Will several requests run at once? | Include concurrency before accepting the setting. | Measure queueing, failures, and memory at the intended user count. |
Do not set context to the highest number just because the model supports it. A smaller context that stays on the GPU will often feel much better than a huge context that spills to CPU.
To run Ollama manually with a specific context length:
OLLAMA_CONTEXT_LENGTH=8192 ollama serve
If Ollama runs as a Linux systemd service, a common approach is to add an environment override:
sudo systemctl edit ollama
Add this:
[Service]
Environment="OLLAMA_CONTEXT_LENGTH=8192"
Then reload and restart:
sudo systemctl daemon-reload
sudo systemctl restart ollama
ollama ps
You can also set context per API request:
curl http://localhost:11434/api/generate -d '{
"model": "llama3.2",
"prompt": "Explain what context length means in one paragraph.",
"options": {
"num_ctx": 8192
}
}'
After changing context, run ollama ps again. Check the CONTEXT and PROCESSOR columns. If the processor column no longer says 100% GPU, the new context may be too large for your available VRAM.
Pick Quantization Like a Memory Budget
Quantization compresses model weights so they use less memory. The tradeoff is that a more compressed model may be less accurate or less consistent.
For beginners, think of quantization like image quality:
| Candidate | Relative weight memory | What to verify | Practical use |
|---|---|---|---|
| Q8 or higher precision | Higher | Whether measured task quality improves enough to justify memory and latency | Quality comparison point when it fits |
| Q5 or Q6 | Moderate to high | Task score, model placement, and remaining headroom | Middle candidate for comparison |
| Q4 | Lower | Whether it fits fully and retains required task quality | Often a practical first candidate, not a universal winner |
| Q2 or Q3 | Lowest of these examples | Regressions in factual, coding, multilingual, and long-context tasks | Memory-constrained experiment with explicit quality checks |
Not every model has every quantization tag. Before pulling a specific variant, check the model page in the Ollama library or inspect what you already have:
ollama list
ollama show llama3.2
Ollama's current import documentation describes quantizing supported FP16 or FP32 imports during ollama create. Follow that page for the exact supported formats and flags in your installed release, preserve the source artifact, and give the quantized result a distinct name so rollback remains possible.
For most beginner-level homelabs, a Q4 model is the right place to start. If the answers are poor and you still have memory left, try a higher-quality quantization. If the model does not fit or spills to CPU, try a smaller model or lower quantization.
Understand GPU Offload
GPU offload means the model is running on your graphics card instead of only on the CPU. This is usually much faster for LLM inference.
Check it with:
ollama ps
Example output:
NAME ID SIZE PROCESSOR CONTEXT UNTIL
llama3.2:latest abc123 4.0 GB 100% GPU 8192 4 minutes from now
The beginner-friendly goal is:
- Full GPU placement when it improves the representative workload without taking memory needed by higher-priority services
- CPU/GPU split if the model almost fits but not fully
- CPU only when you have no compatible GPU or intentionally want CPU mode
If a model is not fully on the GPU, try these fixes in this order:
| Fix | Why it helps |
|---|---|
| Lower context length | Reduces memory used by the working context |
| Use a smaller model | Reduces the model weight memory |
| Use a lower quantization | Compresses the model more |
| Stop other loaded models | Frees VRAM |
| Stop GPU-heavy media jobs | Frees VRAM and GPU resources |
| Reduce parallel requests | Prevents duplicate context memory pressure |
If Ollama is running in Docker on NVIDIA hardware, first verify Docker can see the GPU:
docker run --rm --gpus all ubuntu nvidia-smi
If that fails, Ollama in Docker will not be able to use the GPU either. Install and configure the NVIDIA container toolkit before troubleshooting Ollama itself.
Watch VRAM Like Disk Space
VRAM is the GPU's working memory. If you run out, local AI may slow down, fail to load, crash, or fall back to CPU depending on the tool and situation.
Useful NVIDIA commands:
watch -n 1 nvidia-smi
nvidia-smi --query-gpu=timestamp,name,memory.used,memory.free,utilization.gpu,utilization.memory,temperature.gpu --format=csv
nvidia-smi pmon -s um
What to look for:
| Symptom | Possible cause | First thing to try |
|---|---|---|
| VRAM is nearly full | Model, context, or another app is too large | Lower context or stop other GPU jobs |
| CPU is high but GPU is low | CPU fallback or prompt processing bottleneck | Check ollama ps and logs |
| GPU memory rises with each request | Too much concurrency or models staying loaded | Reduce parallel settings or unload models |
| Model gets slower after changing context | Context is too large for comfortable GPU use | Drop context one step |
| System becomes unstable | Driver, heat, power, or out-of-memory issue | Check logs and temperatures |
Leave headroom. Running at 99% VRAM can be fragile, especially if Plex, Jellyfin, Frigate, a desktop session, or a browser also uses the GPU.
Control Concurrency
Ollama can keep models loaded and handle concurrent work when memory allows. That is useful, but it can surprise beginners because every loaded model and every parallel request consumes memory.
For a small homelab server, start conservative:
[Service]
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_NUM_PARALLEL=1"
Environment="OLLAMA_MAX_QUEUE=32"
Then apply the systemd override:
sudo systemctl daemon-reload
sudo systemctl restart ollama
This is not the highest-throughput setup. It is easier to debug. Once everything is stable, you can raise the numbers and test again.
Unload Models When You Need Memory Back
Ollama normally keeps models in memory for a while, so the next request starts faster. That is convenient, but on a shared homelab box it can hold VRAM you need for other work.
Stop a loaded model:
ollama stop llama3.2
Or unload by API:
curl http://localhost:11434/api/generate -d '{
"model": "llama3.2",
"keep_alive": 0
}'
To preload a model for faster first response:
ollama run llama3.2 ""
Use preload for models you use constantly. Avoid preloading giant models on a server that also handles media streaming, camera detection, or game servers.
Recognize CPU Fallback
CPU fallback means the model is not using the GPU the way you expected. It may still work, but it will usually be slower.
Common signs:
ollama psdoes not show100% GPUnvidia-smishows little or no Ollama GPU memory use- CPU usage is high while token generation is slow
- Ollama logs mention GPU discovery problems
- The problem appears after suspend/resume, driver updates, or Docker changes
Basic NVIDIA checks:
nvidia-smi
docker run --rm --gpus all ubuntu nvidia-smi
journalctl -u ollama --no-pager -n 100
Ollama's docs mention that on Linux, after suspend/resume, Ollama may fail to discover an NVIDIA GPU and run on CPU. A documented workaround is to reload the NVIDIA UVM driver:
sudo rmmod nvidia_uvm
sudo modprobe nvidia_uvm
sudo systemctl restart ollama
Do this only when you can interrupt GPU work. If Plex, Jellyfin, Frigate, Tdarr, or a desktop session is actively using the GPU, reloading driver modules can disrupt them.
Read Ollama Logs
Logs are where you confirm whether a problem is a model setting, a GPU setting, or a system problem.
For Linux systemd installs:
journalctl -u ollama --no-pager --follow --pager-end
For recent logs only:
journalctl -u ollama --no-pager -n 100
For Docker:
docker ps
docker logs -f ollama
For macOS:
cat ~/.ollama/logs/server.log
Useful log phrases to notice:
| Log clue | What it may mean |
|---|---|
| GPU discovery failure | Ollama could not initialize the GPU |
| no compatible GPUs | Driver, container, or hardware support issue |
| CUDA error | NVIDIA driver/runtime/GPU issue |
| ROCm or HIP error | AMD driver/runtime/GPU issue |
| model requires more memory | Model, quantization, or context is too large |
| dynamic LLM libraries | Ollama is choosing a backend library |
Do not run random fix commands on your server. Read the error, search the exact phrase, and change one thing at a time.
A Repeatable Tuning and Measurement Process
Use this loop whenever you test a new model or setting:
- Capture versions, model digest, quantization, context, drivers, power state, and competing processes.
- Choose a candidate that fits with headroom; Q4 is a common comparison point, not an automatic quality threshold.
- Set context to the smallest value that holds the representative workload.
- Run one warm-up request, then at least three measured warm requests. Measure a cold load separately after unloading the model.
- Record
ollama ps, CPU, system memory, GPU memory, temperature, and power during the run. - Capture the API timing and token-count fields, then score whether the output completed the task correctly.
- Change one variable, repeat the same sequence, and retain failed runs rather than averaging them away.
- After single-user behavior is stable, run the intended concurrency and shared-service load as separate acceptance tests.
Here is a fixed, non-streaming request that returns Ollama's timing and token-count fields:
curl http://localhost:11434/api/generate -d '{
"model": "gemma3:4b",
"prompt": "Summarize in exactly five factual bullets: The maintenance window starts at 02:00 UTC. The API will be unavailable for 20 minutes. Existing jobs will be paused. Administrators must save work before 01:55 UTC. Status updates will appear on the internal dashboard.",
"stream": false,
"options": {
"temperature": 0,
"num_ctx": 8192,
"num_predict": 256
}
}'
The response includes total_duration, load_duration, prompt_eval_count, prompt_eval_duration, eval_count, and eval_duration; documented durations are nanoseconds. Generation throughput can be calculated as eval_count / (eval_duration / 1e9). Keep load time separate from token-generation speed, and keep both separate from answer quality.
Evidence and Testing Method
This guide is documentation-backed. TechGeeks did not run a standardized hardware benchmark for this draft, so it reports no original tokens-per-second, latency, power, temperature, or quality result. Commands, response fields, memory controls, context behavior, and troubleshooting steps were checked against current Ollama and NVIDIA documentation.
A publishable measurement should identify the hardware, software, exact model artifact, prompt set, run count, cold/warm state, context, output cap, concurrency, power mode, and failed runs. Public results from another host are corroboration of a mechanism, not a prediction for yours.
Decision Matrix: What to Change First
Hardware capacity alone cannot choose a model or context. Use the observed bottleneck to decide the next controlled change.
| Observation | First controlled change | Do not conclude yet |
|---|---|---|
| Model does not fit or loads partly on a slower path. | Reduce context, unload other models, or compare a smaller/lower-memory artifact. | That every smaller or more-quantized model meets the task-quality requirement. |
| Cold start dominates but warm generation is acceptable. | Review keep-alive and usage patterns. | That keeping the model loaded is safe on a shared GPU. |
| Prompt evaluation is slow on long inputs. | Reduce unnecessary input or retrieval volume before shrinking required context. | That output generation is the bottleneck. |
| Generation is slow with expected GPU placement. | Compare a smaller model or quantization under the same prompt and context. | That the alternative preserves correctness. |
| Single-user runs pass but concurrent runs queue or fail. | Lower parallelism or model size, or separate workloads. | That a larger queue creates capacity. |
| Media or camera service degrades during AI use. | Unload the model, schedule workloads, or move a priority service to separate hardware. | That idle VRAM predicts peak coexistence. |
Do not buy hardware from a parameter-count chart alone. Check the exact artifact, context, task score, driver support, measured memory, expected concurrency, and the resources reserved for every other service.
Quick Troubleshooting Table
| Problem | Likely cause | Beginner fix |
|---|---|---|
| Model answers very slowly | CPU fallback | Run ollama ps and check nvidia-smi |
| Model fails to load | Not enough RAM/VRAM | Use smaller model, lower quantization, or lower context |
| Fast at first, slow later | Another model or app took memory | Run ollama ps, stop unused models |
| GPU disappears after sleep | Driver discovery issue | Reboot or reload NVIDIA UVM if appropriate |
| Docker Ollama sees no GPU | Container runtime not configured | Test docker run --gpus all ubuntu nvidia-smi |
| Long prompts are slow | Context is too high or prompt eval cost | Use shorter context or split the task |
| Media server crashes during AI use | Shared VRAM pressure | Unload AI model before transcoding or streaming |
Let the Baseline Govern Each Change
Change one measured variable, retain the result and failures, then choose the next experiment from the observed bottleneck.
For most homelabs, the biggest wins are:
- Use a model that fits fully in VRAM.
- Keep context only as large as the task requires.
- Start with Q4 before trying heavier variants.
- Watch
ollama psandnvidia-smi. - Read logs before guessing.
- Leave room for the rest of the server.
Local AI gets much less frustrating once you stop treating VRAM as a mystery.
Risk, Recovery, and Operational Boundaries
Before changing a systemd override, copy the current effective values and note how to remove the override. Change during a window when restarting Ollama will not interrupt users. If latency, quality, memory, or service stability regresses, restore the last known-good model tag and settings, reload systemd, restart Ollama, and rerun the baseline.
Driver-module reloads and reboots interrupt every process using the GPU. Stop or drain media transcodes, camera workloads, desktop sessions, and other compute jobs first. Do not run commands from a model response without reviewing them for your operating system and current service layout.
Performance data can expose model names, prompts, file paths, hostnames, and workload timing. Redact benchmark artifacts before sharing them. Review each model's license and usage terms separately; local execution does not remove license restrictions or make model output safe to use.
What This Evidence Does Not Prove
100% GPUplacement does not prove the model is correct, fastest for the task, or free from CPU-side bottlenecks.- A higher tokens-per-second value does not prove lower time to first useful answer, better long-context behavior, or acceptable quality.
- A model fitting at idle does not prove it will coexist with concurrent users, media transcoding, camera decoding, or a desktop workload.
- One prompt and one run do not characterize thermal throttling, caching, variance, failures, or sustained throughput.
- Vendor documentation explains supported controls and behavior; it does not benchmark the reader's hardware or exact model artifact.
Related TechGeeks Reading
- Plex + Tdarr GPU Strategy: Sharing NVIDIA GPUs Without Hurting Playback
- Monitoring and Health Checks for a Plex and Arr Homelab
- Linux and Homelab Notes: Start Here
References
- Ollama: Context Length
- Ollama: FAQ, Concurrency, and Keep-Alive
- Ollama: Hardware Support
- Ollama: Troubleshooting
- Ollama: Generate API Timing Fields
- Ollama: List Running Models API
- Ollama: Importing and Quantizing a Model
- NVIDIA: nvidia-smi Documentation
- llama.cpp: llama-bench Method and Reported Exclusions
- Independent study: Local LLM inference on Apple Silicon
Need help applying this?
Bring TechGeeks into the real environment.
If you are working through this on a live network, WordPress site, Linux server, AI workflow, or PisoWiFi deployment, send the context and we can help turn it into a practical plan.

