Intermédiaire 13 minMac

MLX vs llama.cpp sur Mac M-series : qui gagne en 2026 ?

Sur Mac M-series, vous avez deux choix pour faire tourner un LLM en local : MLX, le framework officiel d'Apple, ou llama.cpp avec son backend Metal. Les deux exploitent le GPU intégré et la mémoire unifiée, mais avec des philosophies très différentes. Ce comparatif mlx vs llama.cpp mac confronte les deux sur tokens/sec, support modèles, quantization et confort d'usage Python — avec un verdict tranché selon votre profil.

Par Marie L.·Màj 2026-06-13·Testé sur macOS 14+

#Les deux camps en 2026

MLX est sorti fin 2023, signé par l'équipe ML d'Apple. C'est un framework Python qui ressemble à une fusion de NumPy et PyTorch, conçu dès le départ pour la mémoire unifiée et Metal. Sa cible est large : LLM, vision, audio, fine-tuning. Le package mlx-lm s'occupe spécifiquement de l'inférence et du training de modèles de langage.

llama.cpp est un projet C++ né en 2023, devenu le standard de facto pour l'inférence LLM locale toutes plateformes confondues. Sur Mac, son backend Metal génère des shaders compute pour exploiter le GPU Apple Silicon. C'est ce qui fait tourner Ollama, LM Studio et la majorité des outils grand public. Format de modèle : GGUF.

i
Pourquoi ils coexistent
MLX est natif Apple, llama.cpp est portable. Le premier est optimisé jusqu'à la dernière instruction Metal ; le second exporte le même code sur CUDA, Vulkan, ROCm. Sur Mac, ils sont en concurrence directe. Ailleurs, il n'y a pas débat.

#1. Installation

Côté MLX, tout passe par pip. Le runtime mlx-lm gère le téléchargement depuis Hugging Face, la conversion, la quantization et l'inférence.

MLX
pip install mlx-lm

# Premier test : Llama 3.2 3B 4-bit en une commande
mlx_lm.generate --model mlx-community/Llama-3.2-3B-Instruct-4bit \
  --prompt "Explique la mémoire unifiée Apple en 3 phrases."

Côté llama.cpp, vous avez trois entrées : compiler depuis les sources avec Metal activé, passer par Homebrew, ou utiliser un wrapper comme Ollama ou LM Studio. Pour comparer honnêtement, on utilise le binaire compilé.

llama.cpp
brew install llama.cpp

# Inférence sur un modèle GGUF déjà téléchargé
llama-cli -m ./Llama-3.2-3B-Instruct-Q4_K_M.gguf \
  -p "Explique la mémoire unifiée Apple en 3 phrases." \
  -n 256 -ngl 99
ngl 99 = tout sur le GPU
Le flag -ngl (number of GPU layers) sur Mac, vous le mettez systématiquement à 99 ou plus. Toutes les couches partent sur le GPU intégré via Metal, et la mémoire unifiée fait que c'est gratuit en bande passante.

#2. Tokens/sec mesurés sur M3 Max et M4 Pro

Voici des mesures représentatives prises sur deux machines courantes en 2026 : un MacBook Pro M3 Max 64 Go (bande passante 400 Go/s) et un Mac mini M4 Pro 48 Go (273 Go/s). Modèles testés en quantization équivalente — 4-bit MLX vs Q4_K_M GGUF — sur un prompt de 200 tokens et 256 tokens générés.

Llama 3.2 3B — M3 Max
MLX 4-bit : 158 tok/s · llama.cpp Q4_K_M : 142 tok/s. MLX devant de ~11%.
Llama 3.1 8B — M3 Max
MLX 4-bit : 78 tok/s · llama.cpp Q4_K_M : 71 tok/s. Écart ~10% au profit de MLX.
Qwen 2.5 14B — M3 Max
MLX 4-bit : 42 tok/s · llama.cpp Q4_K_M : 38 tok/s. MLX +10%.
Mistral Small 24B — M3 Max
MLX 4-bit : 24 tok/s · llama.cpp Q4_K_M : 22 tok/s. MLX +9%.
Llama 3.3 70B — M3 Max
MLX 4-bit : 9.8 tok/s · llama.cpp Q4_K_M : 8.7 tok/s. MLX +13%.
Llama 3.1 8B — M4 Pro
MLX 4-bit : 54 tok/s · llama.cpp Q4_K_M : 49 tok/s. MLX +10%.

Le pattern est clair et reproductible : MLX gagne entre 8 et 15% sur la génération pure. La différence vient du fait que les kernels Metal de MLX sont écrits et optimisés directement par Apple, avec une connaissance fine du planificateur GPU et des caches L1/L2. llama.cpp utilise des kernels Metal aussi, mais plus génériques.

!
Le prompt processing peut inverser le verdict
Sur le traitement du prompt initial (prefill), llama.cpp avec Flash Attention activé (-fa) rattrape souvent MLX, voire le dépasse à contexte long. Si vous balancez 16 k tokens dans un système RAG, mesurez les deux phases séparément avant de trancher.

#3. Support des modèles Hugging Face

C'est l'un des points où les deux écosystèmes divergent en pratique. MLX a son propre format de poids (.safetensors avec config MLX), llama.cpp utilise GGUF.

MLX — disponibilité
L'organisation mlx-community sur Hugging Face publie la majorité des modèles populaires (Llama, Qwen, Mistral, Gemma, Phi) en versions 4-bit et 8-bit, souvent dans la semaine de la sortie.
MLX — modèles rares
Pour un fine-tune exotique ou un modèle confidentiel, vous devrez convertir vous-même avec mlx_lm.convert. Conversion typique : 2-10 minutes selon la taille.
llama.cpp — disponibilité
Les GGUF sont partout. Bartowski, TheBloke (archives), Unsloth et les éditeurs officiels publient en GGUF avant même MLX pour beaucoup de modèles.
llama.cpp — modèles très récents
Quand une nouvelle architecture sort (ex. MoE inédite, attention exotique), llama.cpp doit l'implémenter en C++. Délai typique : quelques jours à 2 semaines. MLX, étant Python + Metal, suit parfois plus vite quand Apple l'a déjà préparée.
Convertir un modèle HF vers MLX 4-bit
mlx_lm.convert \
  --hf-path meta-llama/Llama-3.1-8B-Instruct \
  --mlx-path ./llama-3.1-8b-mlx-4bit \
  -q --q-bits 4 --q-group-size 64

#4. Quantizations disponibles

C'est probablement le sujet où llama.cpp domine sans appel. GGUF propose une douzaine de variantes de quantization (Q2_K, Q3_K_S/M/L, Q4_K_S/M, Q5_K_M, Q6_K, Q8_0, plus les I-quants IQ2_XXS à IQ4_NL) qui permettent de calibrer finement le compromis taille / qualité.

MLX
Quantization 4-bit, 6-bit et 8-bit. Paramètre principal : group-size (32, 64, 128). Pas d'équivalent direct des K-quants mixtes (Q4_K_M conserve plus de précision sur certaines couches).
llama.cpp
GGUF Q4_K_M (recommandé), Q5_K_M, Q6_K, Q8_0, FP16, plus les I-quants pour aller encore plus bas. Calibration possible via imatrix.
Qualité observée
À taille équivalente, GGUF Q4_K_M et MLX 4-bit donnent une perplexité très proche (écart < 1%). Pour aller en dessous (Llama 70B sur 32 Go), les I-quants de llama.cpp restent plus fins.
i
Q4_K_M reste la référence
Pour la majorité des cas d'usage, Q4_K_M côté llama.cpp et 4-bit group-size 64 côté MLX donnent la même chose en pratique. Différence visible uniquement si vous benchmarkez sur MMLU ou perplexité avec précision.

#5. Mémoire unifiée : qui l'exploite le mieux ?

Sur Mac M-series, CPU et GPU partagent la même RAM. Pas de copie, pas de transfert PCIe, juste un même pool. C'est l'avantage structurel des puces Apple pour l'inférence LLM, et les deux frameworks en bénéficient — mais pas de la même façon.

MLX
Conçu nativement pour la mémoire unifiée. Les tenseurs vivent dans un espace adressable par CPU et GPU sans distinction. Conversion zéro-copie entre NumPy et MLX. C'est l'argument architectural majeur d'Apple.
llama.cpp Metal
Alloue des MTLBuffer partagés. Fonctionne, mais ajoute une couche d'abstraction. Pour des modèles qui débordent la VRAM allouée par défaut, il faut parfois ajuster manuellement la limite via sudo sysctl iogpu.wired_limit_mb.
Modèles 70B sur 64 Go
Les deux y arrivent. MLX 4-bit charge Llama 70B en ~38 Go. llama.cpp Q4_K_M en ~40 Go. Pour 128 Go (M3 Max top spec ou M2 Ultra), même les modèles 123B passent.
Augmenter la limite VRAM macOS
Par défaut, macOS réserve environ 75% de la RAM au GPU. Sur une machine 64 Go, ça fait ~48 Go utilisables. Pour pousser à 56 Go : sudo sysctl iogpu.wired_limit_mb=57344 — utile pour les modèles 70B en quantization plus haute (Q5_K_M ou 6-bit MLX).

#6. Intégration Python

Si vous codez un agent, un pipeline RAG, ou que vous instrumentez votre LLM avec LangChain / LlamaIndex / votre propre code, l'expérience Python compte autant que les tokens/sec.

MLX — inférence streaming
from mlx_lm import load, stream_generate

model, tokenizer = load("mlx-community/Llama-3.1-8B-Instruct-4bit")

prompt = tokenizer.apply_chat_template(
    [{"role": "user", "content": "Résume MLX en 3 phrases."}],
    tokenize=False, add_generation_prompt=True,
)

for chunk in stream_generate(model, tokenizer, prompt, max_tokens=256):
    print(chunk.text, end="", flush=True)

Côté llama.cpp, l'intégration Python passe par llama-cpp-python (bindings officiels). L'API est plus verbeuse, plus proche du C++, mais elle est OpenAI-compatible une fois le serveur lancé.

llama-cpp-python
from llama_cpp import Llama

llm = Llama(
    model_path="./Llama-3.1-8B-Instruct-Q4_K_M.gguf",
    n_gpu_layers=-1,   # tout sur Metal
    n_ctx=8192,
    flash_attn=True,
)

for chunk in llm.create_chat_completion(
    messages=[{"role": "user", "content": "Résume llama.cpp en 3 phrases."}],
    stream=True,
):
    delta = chunk["choices"][0]["delta"].get("content", "")
    print(delta, end="", flush=True)
MLX — confort
API très propre, syntaxe NumPy-like, intégration native HF Hub. Pour un data scientist, c'est immédiat.
MLX — limites
Pas (encore) d'endpoint OpenAI-compatible officiel intégré. Pour servir un modèle à plusieurs clients, vous devez monter votre propre wrapper FastAPI.
llama.cpp — confort
L'API Python est correcte mais le vrai usage en prod passe par llama-server (binaire) qui expose nativement /v1/chat/completions OpenAI-compatible.
llama.cpp — limites
Le wheel llama-cpp-python doit être recompilé avec le bon flag Metal (CMAKE_ARGS="-DGGML_METAL=on" pip install llama-cpp-python --force-reinstall --no-cache-dir). Source de friction.

#7. Écosystème et outils

Au-delà du runtime brut, c'est l'écosystème qui détermine ce que vous pourrez faire concrètement.

Ollama
Repose sur llama.cpp. Le moyen le plus simple d'avoir un LLM qui tourne sur Mac avec une API OpenAI-compatible sur localhost:11434.
LM Studio
Supporte les deux moteurs depuis 2025 : llama.cpp par défaut, MLX en option pour les modèles compatibles. Bascule en un clic.
Fine-tuning LoRA
MLX a mlx_lm.lora natif, très propre, qui tourne sur le GPU intégré sans bidouille. llama.cpp ne fait pas de fine-tuning — il faut passer par Unsloth ou MLX.
Servir un modèle
llama.cpp gagne sans débat avec llama-server : multi-clients, batched, slots, OAI-compatible. Côté MLX, mlx_lm.server existe depuis 2025 mais reste basique.
Vision et audio
MLX a des extensions (mlx-vlm, mlx-whisper) bien maintenues. llama.cpp couvre la vision via les modèles LLaVA / Qwen-VL avec un support qui dépend du build.

#Verdict par cas d'usage

Vous voulez le maximum de tokens/sec en chat local
MLX. +10% gratuits, et l'écart se creuse sur les gros modèles. Surtout en 4-bit.
Vous voulez servir un endpoint à plusieurs clients (équipe, app)
llama.cpp (llama-server ou Ollama). Multi-slot, batched, OpenAI-compatible, stable depuis longtemps.
Vous testez une dizaine de modèles différents par semaine
llama.cpp. L'écosystème GGUF est imbattable en couverture et fraîcheur de quantizations.
Vous codez un projet Python (agent, RAG, pipeline)
MLX si tout est local et Mac-only. llama-cpp-python ou un client Ollama si vous voulez du code portable Linux/Mac.
Vous voulez fine-tuner un modèle 7-13B sur votre Mac
MLX. mlx_lm.lora marche très bien sur M3 Max / M4 Pro avec 32 Go+.
Vous débutez et voulez juste un LLM qui marche
Ollama (donc llama.cpp). Une commande, c'est fait.
i
La vraie réponse : utilisez les deux
Sur Mac, rien n'empêche d'avoir Ollama qui tourne en daemon pour l'usage quotidien (Open WebUI, Continue.dev, API locale) et MLX en venv Python pour le travail de recherche ou les benchmarks. Ils ne se marchent pas dessus, et chacun excelle dans son terrain.

#Pour aller plus loin

Quelques lectures connexes pour pousser le sujet :

Ce guide vous a aidé ?

Un retour, une erreur, une précision ? Faites-nous signe, ça améliore le guide pour tout le monde.