Comment kimi-k3-in-c fait tourner 2 800 milliards de paramètres avec 8 Go de RAM
TL;DR
kimi-k3-in-c ne charge jamais le modèle complet en mémoire. Il garde une petite partie fixe (le tronc dense) toujours résidente, et va chercher le reste (les experts) sur le disque à chaque mot généré, en ne prenant que les 16 experts sur 896 réellement utiles. Les experts sont déjà compressés à 4 bits sur le disque, un cache garde les plus demandés à portée de main, et la quantité de RAM allouée ne fait que régler la vitesse : la réponse produite reste identique, qu'on lui donne 8 Go ou 224 Go.
Le problème posé : un fichier qui ne rentre nulle part
Le checkpoint de Kimi K3 pèse 1,56 To sur le disque, réparti en 96 fichiers. Aucune machine grand public, et aucun serveur sous la barre du téraoctet de RAM, n'a assez de mémoire pour le charger en entier. La question que résout kimi-k3-in-c n'est donc pas « comment calculer plus vite », mais « comment faire tenir un modèle 200 fois plus gros que la RAM disponible sans changer sa sortie ».
La réponse tient en quatre décisions d'architecture, appliquées dans l'ordre.
Rappel : un modèle à mélange d'experts
Kimi K3 est un modèle à mélange d'experts (Mixture-of-Experts, MoE). Plutôt qu'un seul grand réseau qui traite chaque mot avec tous ses paramètres, le modèle contient 896 sous-réseaux spécialisés, les experts, et un routeur qui en sélectionne 16 pour chaque mot à produire.
Un modèle dense de la même taille utiliserait ses 2 800 milliards de paramètres à chaque calcul. Un modèle MoE comme Kimi K3 n'en active qu'une fraction : environ 104 milliards de paramètres actifs par mot, soit 3,7 % des 2 800 milliards stockés. C'est cette propriété, pas une astuce de compression, qui rend le reste de l'architecture possible.
Réduction un : les experts sont déjà à moitié compressés
Sur le disque, chaque expert est stocké au format MXFP4, un flottant sur 4 bits plutôt que les 16 ou 32 bits habituels. Le moteur multiplie directement sur cette représentation compacte, sans repasser par une version décompressée en mémoire. Premier gain : 1,45 To d'experts routés tiennent en un quart de leur poids d'origine.
Réduction deux : séparer ce qui reste fixe de ce qui circule
Le modèle se divise en deux parties de nature différente. Le tronc dense, 93 couches qui utilisent l'attention (MLA, un seul latent partagé plutôt que 96 têtes séparées, et KDA, une attention linéaire dont la mémoire ne grandit pas avec le texte), reste en mémoire en permanence ou est relu depuis un fichier compact selon le budget choisi. Les 1,45 To d'experts routés, eux, ne sont jamais résidents : ils sont lus et multipliés directement depuis le disque, à la demande.
Le tronc est réécrit une fois, au format d'un fichier de 109 Go où chaque couche vit à un emplacement connu et se lit en un seul appel disque. Cette réécriture, l'empaquetage, est ce qui transforme la contrainte mémoire en curseur réglable plutôt qu'en plafond fixe.
Le cache LRU : quels experts garder chauds
À chaque mot généré, le moteur sait déjà quels 16 experts sur 896 il doit consulter, le routeur vient de les désigner. Un cache LRU (least recently used, le moins récemment utilisé est le premier évincé) garde en mémoire les experts sollicités le plus souvent, pour éviter de les relire à chaque fois qu'ils reviennent.
La taille de ce cache dépend directement du budget RAM choisi via les préréglages du moteur (laptop, workstation, server). Plus il est grand, moins le moteur relit le disque pour les mêmes experts, et plus la génération accélère.
Le vrai goulot : le disque, pas le calcul
Les mesures publiées dans le dépôt sont sans ambiguïté. Avec le préréglage laptop, 8,24 Go de RAM, le moteur produit un mot toutes les 32,7 secondes en moyenne. Avec le préréglage server, 127,92 Go de RAM, ce délai tombe à 10,7 secondes par mot.
Le calcul en lui-même, une multiplication de matrices sur 104 milliards de paramètres actifs, prendrait quelques centaines de millisecondes sur un CPU moderne. L'écart vient d'ailleurs : chaque expert manquant au cache doit être lu depuis le disque avant de pouvoir être multiplié, et cette lecture domine le temps total. Donner plus de RAM au moteur ne le fait pas calculer plus vite, ça lui évite de relire le disque aussi souvent.
Pourquoi la sortie ne change jamais
Un détail distingue ce projet d'une compression avec perte classique : le budget mémoire ne modifie ni les poids ni les calculs, seulement l'endroit où les données transitent avant d'être utilisées. Que le tronc soit entièrement résident ou relu couche par couche, que le cache d'experts contienne 100 ou 10 000 entrées, chaque expert finit multiplié dans sa forme complète et exacte. Le dépôt le prouve avec une suite de tests qui compare la sortie du moteur à une référence PyTorch, position par position, sur un modèle réduit partageant le même graphe tensoriel que Kimi K3.
Ce qu'on peut en retirer
L'idée générale, séparer un modèle en une partie petite et toujours utile et une partie grande et rarement consultée, puis ne charger cette dernière qu'à la demande, s'applique bien au-delà de ce projet. C'est le principe derrière le chargement à la demande de llama.cpp ou les offloads d'experts pour DeepSeek. kimi-k3-in-c en propose une implémentation particulièrement lisible, en C99 sans dépendance, avec des tests qui prouvent chaque affirmation plutôt que de les énoncer.
Reste la question de l'usage réel : 10 à 32 secondes par mot face à ce qu'un GPU permet de faire aujourd'hui, l'écart n'a rien d'anecdotique. Pourquoi un GPU reste indispensable détaille précisément cet écart.