Pourquoi llama.cpp a gagné le local
Faire tourner un LLM sur sa propre machine était, il y a peu, réservé aux possesseurs de gros GPU. llama.cpp a renversé ça avec trois partis pris : pas de dépendances lourdes, un format de modèle autoportant, et une quantification suffisamment fine pour faire tenir un modèle 13 B dans la RAM d’un ordinateur portable. Comme on le voyait dans le comparatif des runtimes, c’est devenu le standard de fait du déploiement local.
GGUF : un format pensé pour le mmap
GGUF (GGML Universal File) stocke dans un seul fichier les tenseurs, leurs types de quantification, le vocabulaire et les métadonnées du modèle. Sa structure est alignée pour être lue par mmap : le fichier est mappé en mémoire virtuelle, et l’OS charge les pages à la demande.
Les schémas de quantification
Le cœur de llama.cpp, c’est sa famille de quantifications. Plutôt que de stocker chaque poids en 16 bits, on les regroupe par blocs et on encode chaque bloc avec une échelle commune et des indices de quelques bits. Les variantes « K » affinent ce schéma avec des sous-blocs et des échelles à deux niveaux.
| Schéma | Bits / poids | Taille modèle 7B | Qualité |
|---|---|---|---|
| F16 | 16 | ≈ 14,5 Go | Référence |
| Q8_0 | 8 | ≈ 7,7 Go | Quasi identique |
| Q5_K_M | ≈ 5,5 | ≈ 5,1 Go | Très bonne |
| Q4_K_M | ≈ 4,5 | ≈ 4,4 Go | Bon compromis |
| Q2_K | ≈ 2,6 | ≈ 2,8 Go | Dégradée |
Le sweet spot pratique est presque toujours Q4_K_M : la perte de qualité reste faible et mesurable, pour une empreinte divisée par trois. En dessous de 3 bits, la dégradation devient nette et dépend beaucoup du modèle.
Le chemin d’un token
Comprendre llama.cpp, c’est suivre ce que devient un token entre l’entrée et la sortie.
Le point intéressant est l’étape « kernels ». Les poids restent quantifiés en mémoire ; ils ne sont déquantifiés que dans le kernel, par blocs, juste avant la multiplication. On lit donc peu d’octets — bon pour la bande passante mémoire — pour un surcoût de calcul modéré.
Un kernel de déquantification
Voici la forme générale d’une déquantification de bloc Q4 : une échelle par bloc, des poids sur 4 bits, reconstruits à la volée.
// Déquantifie un bloc Q4 : 32 poids 4 bits + une échelle f16
void dequantize_q4_block(const block_q4 * restrict b, float * restrict out) {
const float scale = f16_to_f32(b->scale);
for (int i = 0; i < 16; i++) {
const uint8_t packed = b->qs[i]; // deux poids par octet
const int lo = (packed & 0x0F) - 8; // centré sur zéro
const int hi = (packed >> 4) - 8;
out[i] = scale * (float) lo;
out[i + 16] = scale * (float) hi;
}
} Tout est là : deux poids par octet, un décalage pour recentrer sur zéro, une échelle unique par bloc. Multiplié sur des millions de blocs, c’est ce qui transforme un modèle de 14,5 Go en un modèle de 4,4 Go sans réécrire le reste du moteur.
Quand llama.cpp n’est pas le bon choix
llama.cpp brille sur une à quelques requêtes. Pour servir un grand nombre d’utilisateurs concurrents, son absence de batching continu le pénalise face à vLLM. Et sur GPU datacenter récent, des runtimes spécialisés exploitent mieux les formats FP8/FP4 natifs. llama.cpp est l’outil du local et du portable — pas du service à grande échelle.
Conclusion
llama.cpp n’a pas gagné par magie : il a gagné parce que GGUF rend le chargement trivial et que sa quantification échange intelligemment un peu de qualité contre beaucoup de mémoire. C’est une leçon d’ingénierie système autant que d’IA. Pour le déploiement embarqué qui en découle, voir NPU vs GPU à l’edge.
Sources et méthode
Format GGUF — spécification officielle dans le dépôt GGML (objectifs « single-file » et compatibilité mmap). La spécification ne développe pas l’acronyme ; l’expansion GGML Universal File est celle reprise par la documentation du projet.
Schémas de quantification — code source ggml-common.h de llama.cpp, qui définit chaque bloc et son coût effectif en bits par poids (block_q4_K « 4.5 bits », block_q5_K « 5.5 bits », block_q2_K « 2.625 bits »). Compromis qualité : outil quantize.
Déquantification — fonction de référence dequantize_row_q4_0 dans ggml-quants.c. Le code de l’article est une version simplifiée et fidèle de ce bloc Q4_0 ; il ne reproduit pas une variante « K » (super-blocs et échelles à deux niveaux).
Tailles de fichiers (modèle 7 B) — ordres de grandeur mesurés sur des dépôts GGUF publics, par exemple TheBloke/Mistral-7B-Instruct-v0.2-GGUF. Ils varient de quelques pour cent selon le modèle et le tokenizer.