Aller au contenu

Ordonnancement de flotte

Au-delà d'une instance de service, le problème change de nature.

Le changement de préoccupation

Beyond a single serving instance, the challenge shifts from per-request efficiency to predictability.

À l'échelle d'une flotte, on n'optimise plus la vitesse moyenne mais la garantie : un client ne doit pas voir son temps de réponse s'effondrer parce qu'un autre client a envoyé une requête d'un million de jetons.

Deux problèmes, deux politiques.

Problème 1 : le coût d'un échec de cache

Les chiffres

L'ordre de grandeur donné par le rapport

À 1 M de contexte, une entrée de codage typique porte un préfixe de 400 K jetons mais n'exige qu'un incrément de prefill de 4 K jetons.

Un succès de cache de préfixe évite de re-prefiller tout le préfixe, et est donc plusieurs ordres de grandeur moins cher qu'un échec.

Et déplacer le cache vers un autre cluster exigerait de le transférer sur des liens inter-clusters bien plus lents que le tissu intra-cluster.

La solution : l'affinité de cache

Router chaque requête vers le cluster qui détient son cache de préfixe.

Le problème créé

Cette affinité lie chaque session à un cluster unique, dont la panne interromprait toutes les sessions qui y sont liées.

Le hachage cohérent à deux clusters

La parade est élégante :

Le hachage cohérent épingle chaque session à deux clusters : un principal, qui sert son trafic, et un secondaire pré-assigné, qui prend le relais en cas de panne du principal.

                    ┌─────────────┐
   session A ──────►│  cluster 1  │  (principal — détient le cache)
        └───────────│  cluster 4  │  (secondaire — pas de cache)
                    └─────────────┘

   session B ──────►│  cluster 2  │  (principal)
        └───────────│  cluster 1  │  (secondaire)

   session C ──────►│  cluster 3  │  (principal)
        └───────────│  cluster 2  │  (secondaire)

Le secondaire ne détient aucun cache de la session et doit le re-prefiller au basculement.

Pourquoi cela suffit

Puisque le hachage cohérent distribue les affectations secondaires des différentes sessions uniformément dans la flotte, ce travail de re-prefill est réparti entre de nombreux clusters plutôt que concentré sur un seul.

La localité de cache est donc préservée dans le cas courant, tandis que l'impact d'une panne de cluster reste borné.

Pourquoi le hachage cohérent en particulier

Un hachage cohérent a la propriété qu'ajouter ou retirer un cluster ne remappe qu'une fraction des sessions, au lieu de toutes. C'est ce qui rend le dimensionnement dynamique de la flotte possible sans invalidation massive des caches.

Problème 2 : la variance extrême du coût par requête

Le diagnostic

Trois ordres de grandeur

Le trafic de production mêle des requêtes courtes de moins de 2 K jetons et des requêtes ultra-longues jusqu'à 1 M.

Le coût par requête s'étale donc sur environ trois ordres de grandeur, et la charge totale imposée par un nombre fixe de requêtes devient hautement imprévisible.

Conséquence : la planification de capacité, les modèles de files d'attente et les quotas de limitation de débit fondés sur la « requête moyenne » » s'effondrent tous sous cette variance.

Le mode de défaillance typique

Une rafale de requêtes à long contexte sature le calcul disponible, et les requêtes courtes qui arrivent ensuite ne peuvent plus être ordonnancées rapidement, dégradant le temps de première réponse (TTFT) sur l'ensemble du trafic.

Pourquoi c'est particulièrement grave

Les requêtes courtes sont typiquement interactives : un utilisateur attend devant son écran. Les requêtes longues sont typiquement agentiques : un processus travaille en arrière-plan.

Le mode de défaillance fait donc payer l'attente aux utilisateurs les plus sensibles à la latence, à cause de charges qui ne le sont pas.

La solution : le contrôle d'admission par budget

Allouer des budgets de ressources séparés à différentes classes de requêtes, de sorte que le trafic long contexte en rafale consomme au plus sa propre part de la capacité et ne puisse pas dégrader les SLO à l'échelle du système subis par les autres classes.

     capacité totale du cluster
   ┌───────────────────────────────────────────┐
   │ classe COURTE  │ classe MOYENNE │ LONGUE  │
   │   budget X     │   budget Y     │ budget Z│
   └───────────────────────────────────────────┘
        ▲                                  ▲
        │                                  │
   n'est jamais affamée        ne peut pas déborder
   par les longues             sur les autres classes

Le principe

C'est un cloisonnement (bulkheading), au sens de l'ingénierie de fiabilité : au lieu de partager équitablement une ressource unique — ce qui laisse le plus gros consommateur dominer —, on la compartimente en budgets étanches.

La garantie devient structurelle : peu importe ce que fait le trafic long contexte, il ne peut pas franchir sa cloison.

Le lien avec la tarification

Ces deux politiques expliquent la structure tarifaire de Kimi K3 :

Poste Tarif Ce que cela reflète
Entrée, cache touché 0,30 $ / M Le coût réel après affinité de cache
Entrée, cache manqué 3,00 $ / M Le coût d'un prefill complet
Sortie 15,00 $ / M Le décodage, limité par la mémoire

Et le fait que le tarif soit plat sur toute la fenêtre de contexte — sans majoration au-delà d'un seuil — n'est possible que parce que le contrôle d'admission par budget garantit que les requêtes longues ne dégradent pas le service des autres.

Ce que cette section illustre

Ces choix d'infrastructure ne sont pas des détails d'exploitation : ils déterminent directement ce qu'un fournisseur peut vendre et à quel prix. Le facteur 10 entre cache touché et cache manqué est la traduction commerciale directe du travail décrit en Cache de préfixe hybride.

Vérification de compréhension

Pourquoi ne pas simplement répliquer le cache sur tous les clusters ?

Parce qu'un cache de session à 1 M de jetons pèse des dizaines de gigaoctets. Le répliquer sur \(N\) clusters multiplierait par \(N\) le stockage et la bande passante d'écriture, pour un bénéfice qui ne se matérialise qu'en cas de panne. Le hachage à deux clusters offre la tolérance aux pannes sans aucune réplication.

Comment les classes de requêtes sont-elles définies ?

Le rapport ne le précise pas. La segmentation naturelle est par longueur d'entrée (< 2 K, moyenne, > 100 K), éventuellement croisée avec le type de client ou le niveau de service. C'est un détail d'exploitation, pas de recherche.

Qu'est-ce qu'un SLO et pourquoi le TTFT est-il celui qui compte ?

Un Service Level Objective est une garantie chiffrée (« 95 % des requêtes répondent en moins de X »). Le TTFT (time to first token) est le délai avant le premier jeton produit. C'est celui qui compte parce que c'est le seul que l'utilisateur perçoit comme de l'attente : une fois le flux démarré, la génération se déroule à une vitesse relativement stable.


Chapitre précédent : Noyaux d'inférence

Fin de la partie Infrastructure. Suite : Évaluations.