VRAMfarm logo VRAMfarm
EN
Sign up

12 November 2026 · VRAMfarm team

vLLM vs Ollama vs llama.cpp: which to run your LLM with, and the commands

Three terminals side by side running vLLM, Ollama and llama.cpp on one rented GPU: which LLM runtime to choose

If you are the only person talking to the model, the three are about equally fast and Ollama takes the least work: one install command and one ollama run. If a script fires 50 requests in parallel or ten colleagues use the same model, vLLM gets roughly 5–10 times more total tokens per second out of the same card, and the gap grows with load. llama.cpp, the engine Ollama grew out of, is the one to pick when you want to control every byte: exact quantisation files, cache types, which layers stay on the CPU.

All three run on a rented server with an empty PyTorch image, and all three offer an OpenAI-compatible API. The differences are in batching, file formats and how they treat memory.

The short version

Ollama llama.cpp vLLM
Best for One person, quick start, a private chat Control, odd sizes, models bigger than the card An API for apps, several users, batch jobs
Install One script Compile with CUDA pip install vllm, matched to the CUDA version
Model formats GGUF, from its own library or Hugging Face GGUF Original BF16, FP8, AWQ, GPTQ, bitsandbytes, NVFP4 on Blackwell
Memory Takes what the model needs; spills to CPU if short Exactly what you set; offload by layer Reserves 90% of the card at start
Parallel requests One to a few at a time (OLLAMA_NUM_PARALLEL) Slots, continuous batching Continuous batching, dozens to hundreds
OpenAI-compatible API Yes, port 11434, /v1 Yes, llama-server Yes, /v1
Several GPUs Splits layers Splits layers or rows Tensor and pipeline parallel
Start-up after download Seconds Seconds 1–5 minutes

Ollama is built on the same GGML foundations as llama.cpp, so their file formats, quantisation levels and single-user speed are close. What Ollama adds is convenience: a model library with short names, automatic GPU detection, models loaded on demand. What it hides is control, which you notice the day a model runs slowly and you need to know why.

Speed: one conversation vs fifty

For a single conversation, generating text is limited by memory bandwidth: for each new token the card reads the whole model once. The runtime matters less than the size of the file. That leads to a result people don’t expect: vLLM serving an 8B model in its original BF16 (16 GB) is slower for one user than Ollama with a 4-bit file (5 GB), simply because it reads three times as many bytes per token.

Batching changes the picture. vLLM reads the weights once for a whole batch of requests and adds new requests to the running batch as old ones finish, so total output grows almost linearly with users until compute or cache memory runs out. Planning ranges for an 8B model on an RTX 4090, from bandwidth arithmetic and community reports, not our own benchmarks:

Setup 1 user 16 users at once, total Per user with 16
Ollama, Q4_K_M 100–150 tokens/s 100–300 (one or a few served at a time, the rest wait) slow and uneven
llama.cpp, Q4_K_M, 16 slots 100–150 300–700 20–45
vLLM, BF16 45–60 600–1,200 40–75
vLLM, AWQ 4-bit 100–140 800–1,500 50–90

Single-user speed is plenty in every row: people read at 5–8 tokens per second. The gap opens with load: a support bot, an internal tool for a team, or a batch job that classifies 100,000 product descriptions overnight. For those, vLLM is the right engine, and the cost per million tokens shows what that does to the bill.

Two other engines are worth knowing. SGLang is a close alternative to vLLM with similar formats and an OpenAI-compatible server, strong on many requests that share a long prefix. TensorRT-LLM squeezes the most out of NVIDIA data-centre cards but takes more setup. If you are choosing between the first three, you don’t need either.

How each one treats memory

Most “it was slow” and “it crashed” stories come from this part.

Ollama spills to the CPU without telling you. If the model plus its context doesn’t fit, Ollama moves some layers to system RAM and carries on at a fraction of the speed. In our own test, Qwen3 32B on a 24 GB card with a 32k context sent 18% of its layers to the CPU and dropped from about 30 tokens per second to 2.5. Run ollama ps: the PROCESSOR column should say 100% GPU. Set the context with OLLAMA_CONTEXT_LENGTH, and remember that OLLAMA_NUM_PARALLEL multiplies the cache: four parallel slots at 8k context need the cache of 32k.

llama.cpp does exactly what you say. -ngl sets how many layers go to the GPU (99 means all), -c sets the total context, and -np sets the number of parallel slots that share it: -c 32768 -np 4 gives four users about 8k each. For mixture-of-experts models that don’t fit, --n-cpu-moe keeps some expert weights in system RAM while the shared layers stay on the GPU, which runs large MoE models on smaller cards at usable speed.

vLLM reserves memory up front. By default it takes 90% of the card at start and fills what the weights don’t use with KV cache. It then checks that one request of the maximum context fits, and refuses to start if it doesn’t; the error names the largest context that would fit. Set --max-model-len to what you really need, and --gpu-memory-utilization lower if something else must share the card. The CUDA out of memory guide covers the rest.

Ollama: start commands

On an empty PyTorch server, in the Jupyter terminal or over SSH:

curl -fsSL https://ollama.com/install.sh | sh
OLLAMA_CONTEXT_LENGTH=8192 OLLAMA_FLASH_ATTENTION=1 OLLAMA_KV_CACHE_TYPE=q8_0 \
  ollama serve > /workspace/ollama.log 2>&1 &
ollama run qwen3:8b

Any GGUF from Hugging Face works too: ollama run hf.co/<user>/<repo>:Q4_K_M. The API listens on port 11434:

curl http://localhost:11434/v1/chat/completions -H "Content-Type: application/json" \
  -d '{"model": "qwen3:8b", "messages": [{"role": "user", "content": "Hello"}]}'

If all you want is a chat window, you don’t need any of this: the ready-made Private ChatGPT app installs Ollama, a Qwen3 or MiMo model and Open WebUI by itself, as described in your own ChatGPT with Open WebUI.

llama.cpp: build once, then run

llama.cpp has to be compiled with CUDA. The server image contains the CUDA runtime but not the compiler, so install NVIDIA’s toolkit first. It downloads a few GB, which counts as traffic, and the build takes 5–15 minutes:

wget -q https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb
dpkg -i cuda-keyring_1.1-1_all.deb && apt-get update -qq
apt-get install -y -qq cuda-toolkit-12-8 cmake git build-essential
export PATH=/usr/local/cuda-12.8/bin:$PATH

git clone https://github.com/ggml-org/llama.cpp /workspace/llama.cpp && cd /workspace/llama.cpp
cmake -B build -DGGML_CUDA=ON && cmake --build build --config Release -j

Then download a GGUF and start the server with four parallel slots:

pip install -U huggingface_hub
hf download <user>/<repo>-GGUF <model>-Q4_K_M.gguf --local-dir /workspace/models
./build/bin/llama-server -m /workspace/models/<model>-Q4_K_M.gguf \
  -ngl 99 -c 32768 -np 4 --flash-attn on --host 127.0.0.1 --port 8081

Port 8080 is taken by Jupyter on our servers, hence 8081. llama-server serves the OpenAI-style API at /v1 and a simple chat page at the root. If you will use llama.cpp again, keep the built /workspace/llama.cpp folder in the saved folder rather than compiling every time.

vLLM: an API in two commands

pip install "vllm==0.11.0" "transformers>=4.56,<5"   # built for CUDA 12.8
vllm serve Qwen/Qwen3-8B --max-model-len 16384 \
  --host 0.0.0.0 --port 8000 --api-key change-me > /workspace/vllm.log 2>&1 &

A plain pip install vllm brings the newest release with its own PyTorch build, and in autumn 2026 that build targets a newer CUDA than many machines’ drivers support, so the engine will not start. That is why the command above pins vLLM 0.11.0 (PyTorch 2.8, CUDA 12.8), the version our vLLM server uses; on a machine whose catalogue entry shows CUDA 13 or newer you can take a later release. Check the CUDA version shown before launch; CUDA and driver mismatches explains how to read those numbers. The ready-made vLLM server skips this step: vLLM is installed in a version that matches the machine, and it starts a Qwen 7B model by itself. To serve a different model there, run pkill -f "vllm serve" and start your own command on port 8000.

From your code, use the standard OpenAI client with your own address:

from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="change-me")
r = client.chat.completions.create(model="Qwen/Qwen3-8B",
    messages=[{"role": "user", "content": "Summarise this ticket: ..."}])
print(r.choices[0].message.content)

The same lines, with a different base URL, connect a Telegram bot, a RAG pipeline or an existing app that was written for OpenAI.

Reaching the API from outside, and keeping it running

A server has no public IP of its own; SSH, Jupyter and apps go through our address with ports assigned to that server. On the vLLM server, port 8000 is already published, and the dashboard shows the API address. On an empty PyTorch server only SSH and Jupyter are published, so reach Ollama or llama.cpp through an SSH tunnel from your computer: ssh -p <port> -L 8081:localhost:8081 root@<address> (port and address from the server card; the SSH key guide sets up the key), then use http://localhost:8081. A custom Docker image can publish its own port. Docker inside the server is not available, which is why every command here installs with pip or a script.

Whatever is reachable from outside needs a key. vLLM takes --api-key, llama.cpp takes --api-key too, and Ollama has no key of its own, so keep it behind a tunnel.

Start long-running servers with nohup ... & and a log file as above, or inside tmux (apt-get install -y tmux, then tmux new -s llm), so they keep running when you close the browser or the SSH session. They stop with the server: billing ends the minute you press Stop, and the next launch starts from a clean disk except for what you kept in the saved folder.

Questions on this topic

Can I call my model from my own app or a Telegram bot?

Yes. All three expose an OpenAI-compatible API, so any library or bot framework that talks to OpenAI works once you change the base URL to your server and the model name to yours. Use vLLM if the bot has many users at once.

Will they use both GPUs in a two-card machine?

Ollama and llama.cpp spread the layers across both cards by themselves, which gives you the memory of both but not much extra speed for one user. vLLM needs --tensor-parallel-size 2, and then it uses both cards' memory and bandwidth at once.

Why does vLLM take 90% of the GPU memory when the model is small?

On purpose: it reserves memory up front for the KV cache so it can serve many requests without allocating mid-flight. Lower it with --gpu-memory-utilization 0.6 if you want to run something else on the same card.

Can I just run the official vLLM or Ollama Docker image?

Not inside a server, because the server is itself a container. Install them with pip or the install script as shown here, or launch the server from your own Docker image instead.

Find the GPU your model fits on

Pick a model and see the cheapest card with enough VRAM, billed by the minute in euros.