Le déploiement de grands modèles de langage (LLM) en production est un défi classique d'ingénierie. D'un côté, vous voulez un débit maximal pour servir un maximum de requêtes, réduisant le coût par token. De l'autre, vous avez besoin d'une faible latence pour garantir une expérience utilisateur réactive. Le regroupement statique, où vous collectez simplement un nombre fixe de requêtes avant le traitement, échoue souvent à équilibrer efficacement ces besoins concurrents. C'est ici que le regroupement dynamique brille.
Le regroupement dynamique regroupe intelligemment les requêtes à la volée, en s'adaptant à la charge actuelle et aux caractéristiques des requêtes. Dans cet article, nous explorerons l'architecture du regroupement dynamique, les seuils de latence critiques impliqués et la manière de mettre en œuvre des stratégies efficaces dans les frameworks modernes de service de LLM.
Le défi central : La courbe de latence du regroupement
Lors du service des LLM, le regroupement améliore l'utilisation du matériel (en particulier sur les GPU) en maintenant les unités de calcul occupées. Cependant, l'attente qu'un lot se remplisse introduit une latence d'attente. Si vous attendez trop longtemps qu'un lot atteigne sa limite de taille, vos métriques de latence de queue (p99) augmenteront de façon exponentielle. Inversement, si vous traitez les lots trop hâtivement, vous sacrifiez le débit.
L'objectif du regroupement dynamique est de trouver le « point idéal » où le gain marginal de débit apporté par l'ajout d'une autre requête au lot est équilibré par l'augmentation marginale de la latence pour toutes les requêtes de ce lot.
Composants clés d'un regroupement dynamique
Un système de regroupement dynamique robuste se compose généralement de trois composants principaux : une file d'attente de requêtes, un planificateur et un gestionnaire de contraintes de latence.
- La file d'attente : Contient les requêtes d'inférence entrantes. Elle doit être légère et rapide, souvent implémentée à l'aide d'une file d'attente prioritaire ou d'un simple tampon FIFO.
- Le planificateur : Décide quelles requêtes inclure dans le prochain lot. Les planificateurs avancés peuvent prioriser les requêtes plus courtes ou les utilisateurs à haute priorité.
- Le gestionnaire de latence : La condition d'« arrêt ». Il garantit que si une requête a attendu trop longtemps, elle est forcée d'être incluse dans le prochain lot, même si le lot n'est pas complet.
Stratégie d'implémentation : Regroupement basé sur les délais d'attente
La stratégie la plus courante et la plus efficace est le regroupement basé sur les délais d'attente. Le système attend qu'un lot atteigne soit une taille maximale ($N_{max}$), soit que la requête la plus ancienne dépasse un temps d'attente maximum ($T_{max}$), selon ce qui se produit en premier.
Voici une implémentation conceptuelle simplifiée en Python démontrant cette logique :
class DynamicBatcher:
def __init__(self, max_batch_size=32, max_wait_time_ms=50):
self.max_batch_size = max_batch_size
self.max_wait_time_ms = max_wait_time_ms
self.request_queue = []
def add_request(self, request):
self.request_queue.append(request)
def get_next_batch(self):
batch = []
if not self.request_queue:
return batch
# Trier par heure d'arrivée pour gérer la priorité FIFO
self.request_queue.sort(key=lambda x: x.arrival_timestamp)
start_time = self.request_queue[0].arrival_timestamp
for request in self.request_queue:
# Vérifier la contrainte de latence
current_wait = (now() - request.arrival_timestamp)
if current_wait > self.max_wait_time_ms:
break
# Vérifier la contrainte de taille
if len(batch) >= self.max_batch_size:
break
batch.append(request)
# Supprimer les requêtes traitées de la file d'attente
# (Les détails d'implémentation sont omis pour brièveté)
return batch
Optimisation avancée : Décodeur spéculatif et gestion du cache KV
Alors que le regroupement traite efficacement les entrées, le décodage est souvent le goulot d'étranglement. Lors du regroupement de longueurs d'invites variées, le temps d'inactivité du GPU pendant la phase de décodage augmente. Les systèmes avancés combinent désormais le regroupement dynamique avec le décodage spéculatif, où un modèle « brouillon » plus petit propose des tokens que le modèle plus grand doit vérifier. Cela réduit le nombre d'étapes de décodage séquentiel, permettant au regroupement dynamique de maintenir un haut débit même avec des contraintes de latence strictes.
Conclusion
Le regroupement dynamique n'est pas seulement une fonctionnalité ; c'est une nécessité pour une infrastructure LLM évolutive. En ajustant soigneusement la taille maximale du lot et le temps d'attente maximum, les ingénieurs peuvent adapter leur infrastructure de service à des objectifs de niveau de service (SLO) spécifiques. Que vous serviez un chatbot nécessitant une latence inférieure à 100 ms ou un service de résumation en arrière-plan où le débit est roi, comprendre l'interplay entre le regroupement et la latence est la clé d'un déploiement réussi.