TL;DR (version 3 lignes)

  • Performance MLX est plus rapide, mais uniquement dans un benchmark Apple Silicon sur machine locale (+3 à 12 %)
  • Agents en production llama.cpp + Ollama convient mieux aux agents et à l'inférence en production (le runtime HTTP est la variable déterminante)
  • Vrai goulot Dans la plupart des cas, c'est la bande passante mémoire qui est le plafond, pas le framework — en swap, les deux s'effondrent simultanément

Jugement central de cet article

Proximité matérielle : MLX gagne (3× moins de dispatches, chemin de quantification plus court). Proximité d'ingénierie : llama.cpp / Ollama gagne (runtime HTTP intégré, zéro configuration pour Claude Code). Ces deux dimensions ne sont pas interchangeables.

Explication unifiée (couche premiers principes)

La différence fondamentale entre MLX et llama.cpp n'est pas « un peu plus rapide ou un peu plus lent », mais deux philosophies d'exécution radicalement opposées :

  • graph-fusion execution (MLX) : collecte lazy du graphe d'opérateurs → fusion à l'exécution → dispatch groupé
  • per-op dispatch execution (llama.cpp) : chaque opérateur soumis indépendamment → compatibilité multi-plateforme → coût prévisible

Et deux orientations d'ingénierie fondamentalement différentes :

  • hardware-native specialization (MLX) : Apple-only, exploite à fond un seul type de matériel
  • engineered portability (llama.cpp) : fonctionne sur CUDA / Metal / Vulkan / CPU, portabilité en priorité

Tous les écarts de performance se résument à trois facteurs :
① nombre de dispatches  ② capacité de kernel fusion  ③ saturation ou non de la bande passante mémoire

Limites du système : portée et périmètre des conclusions

Une conclusion avec des limites explicites est plus fiable qu'une description sans frontières. Toutes les conclusions de cet article sur les performances et le choix d'architecture MLX vs llama.cpp sont valables sous les conditions suivantes :

✅ Cas d'usage couverts

  • Apple Silicon (séries M1–M4 / M5)
  • Inférence batch = 1 / petit batch (phase de décodage)
  • Transformers decoder-only (modèles 7B–14B courants)
  • Backend Metal (chemin GPU natif macOS)
  • Inférence locale mono-machine / nœud partagé en petite équipe
  • Outils agents : Claude Code / Cursor / Open WebUI

❌ Cas non couverts

  • Serving multi-GPU CUDA / NVIDIA
  • Entraînement large batch
  • Inférence distribuée multi-nœuds
  • Pipeline de speculative decoding
  • Modèles MoE (architecture significativement différente)
  • Instances GPU cloud (sans Apple Silicon)

Les conclusions de cet article ne s'appliquent pas aux GPU NVIDIA / AMD — cela relève du domaine CUDA vs ROCm, sans rapport avec l'architecture mémoire unifiée d'Apple Silicon.

Définitions des termes clés : Metal dispatch · Kernel fusion · Mémoire unifiée · GGUF vs format MLX

Avant d'aborder le contenu technique, alignons quelques concepts fondamentaux. Ce sont aussi les termes les plus souvent confondus dans le domaine de l'inférence LLM sur Apple Silicon.

Metal dispatch (Metal compute dispatch)
Unité minimale par laquelle le CPU soumet un compute kernel au GPU Apple Silicon. Chaque dispatch nécessite une synchronisation CPU-GPU générant environ 1–3 µs de latence d'ordonnancement. Plus le nombre de dispatches est élevé, plus le coût cumulé d'attente du CPU est important.
Kernel fusion (fusion de noyaux)
Opération consistant à combiner plusieurs opérateurs indépendants (ex. matmul → bias add → activation) en un seul kernel GPU, réduisant ainsi le nombre de dispatches et les lectures/écritures intermédiaires en mémoire globale. MLX réalise la fusion automatiquement via lazy evaluation ; llama.cpp s'appuie sur des kernels fusionnés écrits à la main (ex. flash attention), avec une couverture limitée.
Mémoire unifiée (Apple Silicon)
Sur Apple Silicon, CPU et GPU partagent le même bloc de mémoire physique — il n'y a pas de VRAM séparée. Une fois les poids du modèle chargés, aucune copie CPU↔GPU n'est nécessaire : c'est le fondement de l'avantage hardware pour l'inférence LLM sur Mac. Les backends Metal de MLX et llama.cpp exploitent tous deux automatiquement cette mémoire unifiée, mais l'allocateur mémoire de MLX est plus aligné sur ce modèle.
GGUF (format de quantification llama.cpp)
Format de quantification utilisé par llama.cpp, supportant plusieurs niveaux de précision de Q2_K à Q8_0. Les fichiers modèle ont l'extension .gguf et sont téléchargeables directement sur Hugging Face. Ollama utilise GGUF pour gérer les modèles ; ce format est incompatible avec le format MLX.
Format MLX (format de quantification mlx-community)
Format utilisé par MLX, basé sur safetensors + métadonnées de quantification MLX. Obtenu via mlx_lm.convert ou depuis mlx-community. Les kernels de quantification sont directement liés aux shaders Metal, et le format est totalement incompatible avec GGUF — un même modèle de base doit être converti séparément pour chaque framework.

Vue d'ensemble architecturale MLX vs llama.cpp : comparaison complète des frameworks d'inférence Apple Silicon

Avant d'entrer dans les détails, construisons une vision globale avec un tableau synthétique. La divergence fondamentale entre mlx vs llama.cpp réside dans leur objectif de conception : l'un vise l'optimisation maximale sur Apple uniquement, l'autre la portabilité multi-plateforme.

DimensionMLXllama.cpp
Objectif de conception Dédié Apple Silicon Multi-plateforme (CUDA / Metal / Vulkan / CPU)
Modèle d'ordonnancement Lazy graph fusion (dispatch groupé après analyse du graphe) Per-op dispatch (chaque opérateur soumis indépendamment)
Accès Metal Runtime JIT kernel (compilé selon la forme des tenseurs) Kernels précompilés (embarqués dans le binaire)
Modèle mémoire Native unified memory (allocation mémoire unifiée native) ggml allocator (générique, non spécifique Apple)
Format de quantification safetensors + métadonnées MLX (mlx-community) GGUF (Q2_K à Q8_0)
Runtime HTTP Aucun intégré (nécessite une passerelle FastAPI) Encapsulé par Ollama, prêt à l'emploi (:11434)
Connexion directe à Claude Code / Cursor ❌ Passerelle à construire ✅ Zéro configuration avec Ollama
Cas d'usage adaptés benchmark, recherche, fine-tuning LoRA Runtime agent, inférence en production, partage d'équipe

Les deux dernières lignes définissent le choix d'architecture ; l'écart en tok/s est traité en § Vraies sources de l'écart de performance et n'entre pas dans la décision de runtime agent.

Apple Silicon LLM Inference Stack Model (2026)

En traduisant le tableau ci-dessus en un modèle à quatre couches, on obtient le cadre le plus simple pour comprendre toutes les conclusions de cet article :

┌─────────────────────────────────────────────────┐
│            Application Layer                    │
│   Claude Code  ·  Cursor  ·  Open WebUI         │
├─────────────────────────────────────────────────┤
│            Runtime Layer                        │
│   Ollama (llama.cpp)  │  FastAPI (MLX wrapper)  │
│   ✅ Chemin agent recommandé  │  ⚠️ À construire │
├─────────────────────────────────────────────────┤
│            Compute Layer                        │
│   ggml-metal (per-op) │  MLX (graph fusion)     │
│   Multi-plateforme, kernels précompilés         │
│                       │  Apple-only, JIT        │
├─────────────────────────────────────────────────┤
│            Hardware Layer                       │
│       Apple Silicon Unified Memory              │
│   CPU + GPU partagent la mémoire physique       │
└─────────────────────────────────────────────────┘
Fig. · Stack d'inférence LLM Apple Silicon à 4 couches — le choix d'architecture se fait au niveau Runtime, l'écart de performance vient du niveau Compute, le plafond est au niveau Hardware

Conclusion clé : le choix d'architecture se fait uniquement au niveau Runtime. L'écart de performance au niveau Compute (MLX vs ggml-metal) n'influence pas le choix au niveau Runtime — les deux opèrent à des niveaux distincts et ne se substituent pas l'un à l'autre.

Différence principale : nombre de dispatches Metal (480 vs 160) — source de performance de l'inférence Apple Silicon

C'est le chiffre le plus important à retenir de tout cet article. Comprendre l'écart en nombre de dispatches, c'est comprendre la racine de l'écart de performance MLX vs llama.cpp.

Pour un modèle transformer 7B, générer un token nécessite un forward pass complet sur les 32 couches. Chaque couche contient des opérateurs QKV projection, attention score, softmax, output projection, FFN gate, FFN up/down, RMS Norm, RoPE, etc. :

llama.cpp (dispatch per-op) : 32 couches × ~15 opérateurs/couche ≈ 480 dispatches Metal
MLX (après lazy graph fusion) : 32 couches × ~4–5 blocs fusionnés/couche ≈ 128–160 dispatches Metal

💡 Insight clé (citable)

L'avantage de MLX n'est pas une puissance de calcul supérieure, mais une réduction d'environ 3× du nombre de dispatches CPU↔GPU.
En batch=1, le coût d'ordonnancement CPU de chaque [commandBuffer commit] est d'environ 1–3 µs. 480 vs 160 dispatches, soit une économie d'environ 0,3–1 ms par token — c'est le principal mécanisme expliquant l'avantage de MLX dans les benchmarks, pas un algorithme de kernel supérieur.

Chaque dispatch Metal est un point de synchronisation CPU-GPU : le CPU doit attendre que le GPU confirme l'entrée en file du command buffer avant de lancer le kernel suivant. Quand le temps de compute GPU est court (inférence petit batch), le coût de dispatch devient le goulot. La lazy evaluation de MLX fusionne plusieurs opérateurs en un seul dispatch, contournant directement ce coût de synchronisation.

Modèle de décomposition de la latence par token (Dispatch Cost Model)

La latence de génération d'un token se décompose en trois composantes quantifiables :

Latence par token ≈
  dispatch_count × cpu_sync_cost     ← coût de dispatch (source de la différence framework)
  + gpu_compute_time                 ← temps de calcul GPU réel (limité par bande passante / puissance)
  + memory_bandwidth_time            ← temps de transfert des poids (plafond physique)

Distribution typique pour batch=1, modèle 7B, M4 Mac Mini 16 Go :

Composantellama.cppMLXNotes
dispatch_count × cpu_sync_cost ~480 × 2 µs ≈ 0,96 ms ~160 × 2 µs ≈ 0,32 ms Source de l'écart framework, représente 10–30 % de la latence totale
gpu_compute_time ~1–3 ms (similaire pour les deux) Déterminé par la puissance de calcul et le format de quantification
memory_bandwidth_time ~4 Go ÷ 120 Go/s ≈ 33 ms (terme dominant) Plafond physique, inoptimisable par le framework

Estimations approximatives (batch=1, 7B Q4_K_M, M4 16 Go). memory_bandwidth_time est le terme largement dominant, ce qui explique pourquoi l'avantage MLX est quasi nul en saturation de bande passante.

Dimensionllama.cpp (ggml-metal)MLX
Cycle de vie du kernel Précompilé, embarqué dans le binaire (.metal.metallib) Compilé à la demande à l'exécution, délai initial, puis mis en cache
Fusion de noyaux Limitée : quelques kernels fusionnés écrits à la main (ex. flash attention) Fusion automatique au niveau framework, opérateurs adjacents fusionnés après analyse du lazy graph
Nombre de dispatches par forward pass (7B) ~400–600 (per-op) ~80–160 (après fusion)
Chemin d'ordonnancement CPU Thread scheduler ggml → Metal command buffer MLX scheduler écrit directement dans le Metal command buffer
Parallélisme multi-flux Queue Metal command unique (configuration standard) Multi-stream supporté, calcul des couches adjacentes potentiellement parallèle

Pourquoi MLX a été créé : point de départ d'un framework d'inférence dédié Apple Silicon

Fin 2023, l'équipe de recherche en machine learning d'Apple a rendu public MLX. Sa motivation de conception est singulière — non pas pour la portabilité, mais pour exploiter à fond un seul type de matériel.

Avant MLX, l'inférence LLM sur Apple Silicon reposait sur :

  • Core ML / MPS : stack d'inférence officielle Apple, format modèle fermé, peu adapté aux chercheurs
  • llama.cpp + Metal : principale solution communautaire, mais ggml conçu pour l'écosystème CUDA, avec le surcoût d'abstraction multi-plateforme
  • PyTorch + backend MPS : couverture opérateur MPS incomplète, vitesse d'inférence ne tirant pas pleinement parti d'Apple Silicon

Le jugement des ingénieurs Apple : pour exploiter réellement la combinaison mémoire unifiée + bus haute bande passante + GPU Metal, il fallait un framework de calcul tensoriel conçu de zéro pour Apple Silicon.

Les quatre principes fondamentaux de conception de MLX

  • CPU et GPU partagent le même espace mémoire — transfert zéro copie
  • Lazy evaluation : les opérations ne s'exécutent pas immédiatement, elles sont accumulées puis ordonnancées en lot avec optimisation du graphe
  • Graphe dynamique + JIT, API proche de NumPy / JAX, adaptée aux chercheurs
  • Les compute shaders Metal sont compilés à la demande à l'exécution, pas de kernels fixes préembarqués

Architecture llama.cpp : abstraction multi-plateforme ggml + backend Metal + quantification GGUF

llama.cpp a été publié par Georgi Gerganov en mars 2023, avec pour objectif de faire tourner LLaMA sur du matériel grand public en C/C++ pur. La portabilité est la première priorité.

ggml : backend tenseurs universel

Le cœur de llama.cpp est ggml — une bibliothèque tenseurs C légère qui supporte plusieurs types de matériel via des plugins backends :

BackendMatérielCondition d'activation
GGML_METALGPU Apple SiliconmacOS, -DLLAMA_METAL=ON
GGML_CUDAGPU NVIDIALinux/Windows + CUDA
GGML_VULKANGPU AMD / IntelDriver Vulkan
GGML_CPUTous CPUFallback par défaut

L'avantage est un seul code pour toutes les plateformes ; le prix à payer est que chaque backend est une adaptation générique, sans optimisation profonde pour un matériel spécifique, avec le surcoût d'ordonnancement dû aux couches d'abstraction.

Backend Metal (ggml-metal) et kernels précompilés

Sur Apple Silicon, llama.cpp active ggml-metal.metal — un fichier de shaders Metal précompilé contenant :

  • Multiplication matricielle : kernels dédiés pour chaque format de quantification GGUF (Q4_K, Q8_0, etc.)
  • Softmax, RoPE, RMS Norm : kernels indépendants par opérateur
  • Opérations KV cache : réutilisation des vues mémoire pour éviter les copies

Limitation clé : les kernels sont précompilés et fixes, sans ré-optimisation selon la forme des tenseurs à l'exécution. Quand la longueur de séquence ou la taille de batch change, les paramètres du kernel sont transmis via des Metal buffers, mais le kernel lui-même ne change pas — c'est précisément là que la spécialisation runtime de MLX peut prendre l'avantage.

Format de quantification GGUF

llama.cpp utilise GGUF, avec des niveaux de précision allant de Q2_K (compression maximale) à Q8_0 (proche de fp16). Chaque format de quantification dispose d'une implémentation dédiée dans les kernels Metal — c'est pourquoi ses performances sur Apple Silicon restent bonnes — mais cela signifie aussi qu'ajouter un nouveau format de quantification nécessite de maintenir un nouveau jeu de kernels.

Architecture MLX : lazy evaluation + runtime JIT kernel + mémoire unifiée Apple Silicon

La différence fondamentale entre MLX et llama.cpp réside dans la position de la couche d'abstraction : Metal est un "plugin backend" dans llama.cpp, tandis que tout le graphe de calcul de MLX a été conçu dès l'origine dans la sémantique Metal.

Lazy Evaluation + fusion du graphe de calcul

  1. Quand du code Python appelle un opérateur MLX, l'exécution n'est pas immédiate — seul un nœud du graphe de calcul est enregistré
  2. Lors de l'appel à mx.eval(), le framework analyse le graphe complet
  3. Les opérateurs adjacents fusionnables (matmul + bias + activation, etc.) sont regroupés en un seul dispatch Metal
  4. Le compute shader Metal généré est compilé à l'exécution, mis en cache, puis réutilisé

Exploitation approfondie de la mémoire unifiée

  • Tous les tenseurs sont alloués dans un pool de mémoire unifiée, CPU et GPU partagent la même adresse physique
  • Pas de concept de "VRAM" : une fois les poids chargés, le GPU y accède directement, sans équivalent de cudaMemcpy
  • Les Metal buffers et les tableaux MLX partagent le même pointeur en bas niveau — zéro copie lors du passage d'arguments

Le backend Metal de llama.cpp exploite également la mémoire unifiée (c'est une caractéristique matérielle d'Apple Silicon dont tout programme Metal bénéficie automatiquement), mais l'allocateur mémoire de ggml n'a pas été conçu spécifiquement pour ce modèle et comporte une logique d'alignement et d'allocation supplémentaire.

GGUF vs format MLX : deux écosystèmes incompatibles

MLX utilise safetensors + métadonnées de quantification MLX, totalement incompatible avec GGUF. Un même modèle de base nécessite deux conversions séparées :

  • Pour llama.cpp : télécharger depuis HuggingFace → convertir en GGUF avec convert.py puis quantifier
  • Pour MLX : convertir avec mlx_lm.convert, ou récupérer la version pré-convertie directement depuis mlx-community

Les précisions supportées incluent 4-bit, 8-bit et précision mixte. Les implémentations des opérateurs sont directement liées aux shaders Metal — c'est la raison fondamentale pour laquelle le chemin de décompression de quantification de MLX est plus court que celui de GGUF.

Vraies sources de l'écart de performance MLX vs llama.cpp : nombre de dispatches vs bande passante mémoire

C'est la partie la plus souvent mal interprétée dans les benchmarks MLX. L'avantage en vitesse de MLX ne vient pas d'un meilleur algorithme de multiplication matricielle, mais de trois facteurs d'ingénierie quantifiables :

1. Fusion de dispatches : 3× moins de synchronisations CPU-GPU

Comme décrit en § Différence principale, MLX réduit les dispatches Metal de ~480 à ~160 par token. Le gain est maximal en batch=1, courte séquence — le temps de compute GPU est court, le coût d'ordonnancement CPU est proportionnellement élevé.

2. Spécialisation runtime du kernel : optimisation pour la forme exacte des tenseurs

MLX compile les shaders Metal lors de la première exécution d'une forme de calcul spécifique, permettant d'ajuster la tile size et la taille du workgroup aux dimensions matricielles exactes. Les kernels précompilés de llama.cpp utilisent des paramètres génériques conservateurs, peu adaptés aux longueurs de séquence non standard.

3. Chemin de décompression de quantification plus court

Pour supporter plusieurs plateformes, la décompression (dequant) de llama.cpp doit maintenir un chemin de fallback CPU ; les kernels de quantification de MLX ont Metal comme unique cible, permettant de réaliser décompression + multiplication matricielle dans un seul shader, avec moins de lectures/écritures en mémoire globale.

Intervalles de mesure de référence

Données issues de Macstripe Lab, Llama-3.1-8B / Q4_K_M, batch=1, mesurées en juin 2026. À titre indicatif uniquement, non utilisable comme base d'achat ou de sélection de stack.

Machinellama.cpp (Ollama) tok/sMLX tok/sÉcart
M4 Mac Mini 16 Go27–3128–33+3–7 %
M4 Mac Mini 24 Go34–3937–43+5–10 %
M4 Pro 48 Go72–8080–90+8–12 %

Règle : plus la mémoire est grande et le modèle volumineux, plus l'avantage MLX est prononcé. En grand modèle, le temps de compute GPU du forward pass est plus long, le gain absolu de la fusion est plus élevé ; sur 16 Go avec un 7B, la bande passante est déjà le goulot et le gain de fusion est dilué.

Performance Convergence Model (graphique de convergence)

Visualisation de la tendance du tableau ci-dessus : comment l'avantage de performance de MLX croît avec la capacité mémoire, et comment il converge vers zéro au point de saturation de la bande passante :

  Avantage MLX
  (delta tok/s)

  +12% │                                        ● 48Go (14B)
       │                                   ·
   +8% │                              ·
       │                         ·
   +5% │                    ● 24Go (7B–14B)
       │               ·
   +3% │          ● 16Go (7B)
       
    0% │━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━  ← plafond bande passante mémoire
       │   (swap)  (swap)
  -∞% │     ↓ Les deux s'effondrent en swap
       
       └────────────────────────────────────────────
              16Go       24Go       48Go       Capacité mémoire
Fig. · Modèle de convergence de l'écart de performance MLX vs llama.cpp — MLX a l'avantage en dessous du plafond de bande passante, les deux convergent vers zéro en zone swap

La signification clé du graphique : la capacité mémoire détermine où vous vous situez sur la courbe. Le gain du passage de 16 Go à 24 Go (inaccessible en changeant de framework) est bien supérieur à l'écart de 3–12 % entre MLX et llama.cpp.

Pourquoi l'écart dans les benchmarks MLX est ≈0 dans la plupart des cas : la bande passante mémoire est le vrai plafond

L'avantage de MLX n'est pas visible dans tous les scénarios. C'est la valeur "contre-intuitive" la plus importante de cet article :

Saturation de la bande passante mémoire : la différence framework écrasée par les limites physiques

Le plafond de performance de l'inférence batch=1 est la bande passante de transfert des poids, pas la puissance GPU. Pour générer un token, il faut lire l'ensemble des poids de toutes les couches (7B Q4 ≈ 4 Go de déplacement de données). La bande passante mémoire du M4 est d'environ 120 Go/s (version 16 Go), et cette limite physique détermine le plafond de tok/s. Ni MLX ni llama.cpp ne peuvent la dépasser — les deux convergent en saturation de bande passante.

Les deux s'effondrent simultanément en swap

Quand la mémoire unifiée est insuffisante, le système déplace les poids sur le SSD, et la bande passante chute de 120 Go/s à 3–5 Go/s (plafond lecture séquentielle NVMe). Les tok/s des deux frameworks tombent à un chiffre, et l'écart disparaît complètement. La seule solution est d'augmenter la capacité mémoire — changer de framework ne sert à rien.

Prefill longue séquence : le GPU devient le goulot, le coût de dispatch tend vers zéro

Le prefill (traitement d'un long prompt) est une opération compute-intensive, avec une utilisation GPU proche de 100 %. Pour un prompt de 2048 tokens, l'écart de temps de prefill entre les deux est généralement <5 %.

Petits modèles (≤3B) : temps de compute absolu trop court

Un modèle 3B Q4 ne pèse qu'environ 2 Go ; un forward pass GPU prend environ 5–10 ms. La part de la fusion de dispatches (économie de 0,3–1 ms) monte en proportion, mais la valeur absolue est trop faible pour être perçue par l'utilisateur.

Quantification haute précision (Q8_0 / fp16) : bande passante saturée plus tôt

Plus la précision est élevée, plus les poids sont lourds, et plus la bande passante devient le goulot tôt. Un modèle Q8 sur une machine 16 Go est presque certain de swapper — parler de différence framework dans ce cas n'a aucun sens.

Choix d'architecture Ollama vs MLX : pourquoi le runtime agent ne se soucie pas du tok/s

Si MLX est plus proche du matériel, pourquoi la stack recommandée pour Claude Code est Ollama (llama.cpp) ? Parce que ce sont deux questions de niveaux différents.

Le serveur HTTP est la vraie variable déterminante

Ollama fournit une stack d'ingénierie complète au-dessus de llama.cpp :

  • Serveur HTTP d'inférence prêt à l'emploi (:11434, API compatible OpenAI) — Claude Code s'y connecte directement, zéro configuration
  • Gestion du cycle de vie des modèles (ollama pull / rm, déchargement automatique des modèles inutilisés)
  • Ordonnancement de requêtes concurrentes (plusieurs fenêtres Claude Code partagent la même instance de modèle, sans rechargement multiple)
  • Partage LAN en équipe (ollama serve --host 0.0.0.0, toute l'équipe sur le même :11434)

MLX n'offre rien de tout cela. Connecter MLX à Claude Code nécessite : construire une passerelle FastAPI → implémenter la logique de chargement/déchargement des modèles → gérer la file de requêtes concurrentes → maintenir une couche de compatibilité API OpenAI. C'est une stack d'ingénierie d'inférence complète, pas une simple commande.

L'écart de tok/s au niveau framework représente <5 % dans la boucle d'outils agent

Dans une boucle d'outils agent, chaque cycle Claude Code comprend : assemblage du prompt → requête HTTP → attente de la réponse → parsing des appels d'outils → exécution des outils → cycle suivant. Distribution de la latence :

FacteurPart (tâche agent typique)Optimisable par le framework ?
Temps d'exécution des outils (lecture/écriture fichiers, commandes shell)50–70 %Non
Aller-retour HTTP + TTFT du modèle20–35 %Principalement lié à la capacité mémoire
Écart tok/s au niveau framework (MLX vs llama.cpp)<5 %Oui, mais impact négligeable

La variable déterminante de l'expérience agent est la capacité mémoire et la taille du modèle. L'écart framework est complètement noyé par la couche HTTP et le temps d'exécution des outils.

Frontière d'ingénierie entre Ollama et MLX

En clarifiant les frontières respectives, la confusion disparaît :

  • Ollama (llama.cpp) : couche runtime HTTP, résout le problème « comment s'y connecter »
  • MLX : outil de couche calcul, résout le problème « comment aller vite en Python »
  • Les deux ne s'excluent pas : un même Mac peut avoir MLX pour les benchmarks et Ollama pour servir Claude Code simultanément

→ Logique complète du choix Ollama vs MLX : Ollama vs MLX : quel modèle local choisir pour Claude Code ?
→ Déploiement MLX sur M4 Pro en pratique : Guide d'exécution LLM local sur Apple Silicon M4 Pro : benchmarks réels et déploiement MLX

MLX ou llama.cpp : que choisir ? (Guide de décision en 30 secondes)

Choisissez en fonction de votre cas d'usage réel — il n'y a pas de réponse absolue sur « lequel est meilleur » :

Modèle de conclusion pour l'inférence LLM sur Apple Silicon : trois règles citables (mac m4 llm inference speed)

Toutes les conclusions de cet article condensées en un cadre de jugement réutilisable et citable :

Modèle de jugement (citable directement)

  1. Plafond de performance = bande passante mémoire
    Sur Apple Silicon, le plafond de tok/s en inférence batch=1 est déterminé par la bande passante de la mémoire unifiée (~120 Go/s pour le M4) ; aucun framework ne peut dépasser cette limite physique.
  2. Différence framework = coût de dispatch
    L'écart de performance MLX vs llama.cpp (3–12 %) vient de la différence en nombre de dispatches Metal (480 vs 160), pas d'un algorithme d'opérateur supérieur.
  3. Choix de stack = runtime vs recherche
    Pour un runtime agent, choisissez Ollama (llama.cpp) — le serveur HTTP est la variable déterminante ; pour la recherche / les benchmarks / le fine-tuning, choisissez MLX — la couche calcul la plus proche du matériel.

L'optimisation framework ne gagne que 5–15 %. La capacité mémoire détermine 85 %.
Toute discussion MLX vs llama.cpp finit par aboutir à cette conclusion.

Questions connexes : recherches courantes sur le choix d'architecture pour l'inférence Apple Silicon

MLX ou llama.cpp : lequel convient le mieux au déploiement local ?

Cela dépend de ce que signifie « déploiement ». S'il s'agit de déployer un service d'inférence (pour Claude Code / Cursor / une API maison), llama.cpp + Ollama est plus adapté — serveur HTTP prêt à l'emploi, gestion des modèles complète. S'il s'agit de déployer un environnement de recherche (tester de nouveaux modèles, faire des benchmarks, écrire des scripts Python), MLX est plus adapté — plus proche du matériel, interface Python flexible.

Pourquoi ne pas utiliser CUDA pour l'inférence LLM sur Apple Silicon ?

Apple Silicon n'a pas de GPU NVIDIA et ne supporte pas CUDA. Les GPU Apple sont pilotés via l'API Metal, et l'architecture mémoire unifiée permet au CPU et au GPU de partager le même pool de mémoire physique — ce modèle est radicalement différent de celui de la VRAM dédiée NVIDIA. MLX et llama.cpp s'appuient tous deux sur Metal, tirant parti de la mémoire unifiée plutôt que d'une VRAM.

Quelle est la différence entre les formats de quantification GGUF et MLX ?

Les deux sont incompatibles — ce sont deux écosystèmes de quantification distincts. GGUF (llama.cpp) supporte plusieurs niveaux de précision de Q2_K à Q8_0, avec des implémentations dédiées dans les kernels ggml-metal ; MLX utilise safetensors + métadonnées de quantification MLX, avec des kernels directement liés aux shaders Metal. Un même modèle de base doit être converti séparément pour chaque framework.

Pourquoi utilise-t-on principalement Ollama pour les LLM locaux sur Mac ?

Ollama résout le problème d'ingénierie « comment rendre le LLM utilisable » : une commande pour démarrer un serveur HTTP, API compatible OpenAI, connexion directe depuis Claude Code / Cursor / Open WebUI et autres outils. Sous le capot, c'est llama.cpp avec accélération Metal sur Apple Silicon — performances suffisantes, sans environnement Python ni service à construire.

FAQ

MLX vs llama.cpp : lequel est le plus rapide ? Quelle est l'ampleur de l'écart ?

Dans la plupart des benchmarks, MLX est 3–12 % plus rapide, principalement grâce à la fusion de noyaux (~480 vs 160 dispatches) et la spécialisation runtime des kernels Metal. Mais en saturation de bande passante batch=1, en swap mémoire, ou lors d'un long prefill, l'écart est quasi nul. Plus la mémoire est grande (nœud 48 Go) et le modèle volumineux (14B+), plus l'avantage MLX est marqué ; sur 16 Go avec un 7B, l'écart n'est que de 3–7 %.

Quelle est la différence fondamentale entre le backend Metal de llama.cpp et MLX ?

llama.cpp abstrait plusieurs plateformes via ggml, Metal n'en est qu'un backend parmi d'autres — kernels précompilés, chaque opérateur dispatché indépendamment ; MLX a été conçu dès le départ uniquement pour Apple Silicon, la lazy evaluation fusionne les opérateurs à l'exécution, 3× moins de dispatches, chemin de quantification plus court, alignement mémoire unifiée plus profond.

Les formats de quantification GGUF et MLX peuvent-ils être convertis mutuellement ?

Non, pas de conversion directe — les deux formats sont totalement indépendants. GGUF se génère depuis les poids originaux avec convert.py de llama.cpp ; le format MLX se convertit avec mlx_lm.convert, ou se récupère directement depuis mlx-community. Un même modèle de base nécessite une conversion séparée pour chaque framework.

Pourquoi Claude Code choisit Ollama plutôt que MLX ?

Ollama fournit un serveur HTTP prêt à l'emploi (:11434, compatible OpenAI), sans passerelle à construire. Dans la boucle d'outils agent, l'écart tok/s au niveau framework représente <5 % de la latence totale ; l'exécution des outils et la couche HTTP sont les vrais goulots. MLX n'a pas de serveur HTTP intégré : le connecter à Claude Code nécessite de construire une stack d'inférence complète, dont le coût d'ingénierie annule tout avantage en vitesse.

Lequel des deux résiste mieux au swap ?

Les deux se dégradent sévèrement et l'écart disparaît. La bande passante mémoire tombe de 120 Go/s à 3–5 Go/s (plafond NVMe), aucun framework ne peut optimiser ce goulot SSD. Augmenter la mémoire (nœud 24 Go ou 48 Go) est la seule solution.

Peut-on installer MLX et Ollama simultanément ?

Oui, sans aucun conflit. Configuration recommandée : Ollama tourne en arrière-plan pour servir Claude Code, MLX utilisé ponctuellement dans un environnement Python pour les benchmarks ou les scripts de fine-tuning. Les deux partagent la même mémoire unifiée, mais les formats de modèle sont différents et doivent être gérés séparément.

Lectures complémentaires