MLX vs Ollama vs llama.cpp: Which Wins on Apple Silicon?

MLX vs Ollama: they are not the same kind of thing

People compare these three as if they were rivals, but they sit at different layers. llama.cpp is an inference engine written in C and C++. MLX is Apple’s array framework for Apple Silicon, with an mlx-lm package for language models. Ollama is a friendly wrapper that downloads models and serves them through a local API. Historically Ollama used llama.cpp underneath, and recent versions have added an MLX backend on Apple Silicon.

So the real question is not “which is best?” but “how close to the metal do you want to be?” If you have not picked a runtime yet, my post on running a local AI model on your Mac is a gentler starting point.

llama.cpp: the flexible workhorse

llama.cpp runs almost anything in the GGUF format and uses Metal on Apple Silicon. It is a command-line tool and a server, with fine control over context size, quantisation and offloading. It is also quick to get new model architectures, because so much of the community builds on it.

brew install llama.cpp
llama-server -m model.gguf -c 8192

Choose it when you want maximum control, odd model formats, or the latest model support.

MLX: built for Apple’s chips

MLX is designed around unified memory, so it avoids copying data between CPU and GPU. In independent tests and in vendor numbers alike, MLX tends to be faster at generating tokens on Apple Silicon, with the biggest gains reported on mixture-of-experts models and smaller gains on dense ones. Reports of the exact gap vary widely, from tens of percent to around double, so treat any single figure with caution.

pip install mlx-lm
mlx_lm.generate --model <mlx-model-repo> --prompt "Hello"

The catch is that you need an MLX version of the model, usually from the community on Hugging Face. MLX has also been reported to be slower at processing long prompts, so time to first token on a very long context can be worse than llama.cpp.

Ollama: the easiest route

Ollama is the one most people actually use, because it handles downloading, quantised variants and a local server in two commands.

ollama pull <model-name>
ollama run <model-name>

Its API works with many editors and agents, which is why it is the default in so many setups, including Claude Code with local models. Wrapping an engine adds overhead, so Ollama has historically been a little behind raw llama.cpp in speed. With its MLX backend, the picture on supported models has changed. Check the current Ollama release notes to see which models use MLX, because older models may not get the speedup.

How they compare

  • Ease of use: Ollama, then llama.cpp, then MLX.
  • Raw generation speed on a Mac: MLX usually leads, llama.cpp is close, and a wrapper can trail.
  • Model choice: llama.cpp and Ollama cover the widest range of GGUF models. MLX needs an MLX conversion.
  • Long prompts: llama.cpp often has the edge on prompt processing.
  • Integration: Ollama and llama.cpp both expose OpenAI-style APIs, which most tools expect.

Benchmark on your own Mac

Published numbers depend on the chip, memory, model, quantisation and context length, so your result may differ. A fair test uses the same model family at the same quantisation and a fixed prompt, and measures tokens per second:

  1. Run the same prompt three times in each tool and take the average.
  2. Note the first-token delay separately from the generation speed.
  3. Watch memory pressure in Activity Monitor.

Ollama prints timing with ollama run <model> --verbose, and llama.cpp reports its own speed at the end of each run.

Which should you use?

  1. Just want a model running today: Ollama.
  2. Chasing speed or doing experiments on Apple Silicon: MLX.
  3. Want control, new models and custom builds: llama.cpp.

Many people use two. Ollama for everyday tools and agents, and MLX or llama.cpp when they want to squeeze out extra speed or test something new.


Leave a Reply