GPT-OSS au Jour 0
Prise en charge dès le premier jour (Day-0) pour GPT-OSS sur H200 en adaptant ROSE avec FP8, l'attention sink et les optimisations MoE
Perplexity s'engage à mettre les meilleurs modèles d'IA à la disposition des personnes curieuses qui exigent des réponses précises et dignes de confiance, ainsi que des actions autonomes. OpenAI a récemment annoncé ses modèles à poids ouverts (gpt-oss-20b et gpt-oss-120b). Comme pour de nombreux modèles de premier plan, Perplexity est l'une des premières organisations à évaluer gpt-oss-20b et gpt-oss-120b.
Dans cet article, nous partageons les décisions d'infrastructure de notre pile d'inférence interne qui ont rendu possible une prise en charge dès le premier jour (Day-0). Nous nous concentrons sur l'exploitation de ces modèles sur des GPU NVIDIA H200, en détaillant les modifications du noyau, les choix de déploiement et les compromis entre vitesse et coût.
GPT-OSS sur Hopper
Les modèles à poids ouverts sont livrés avec une quantification MXFP4, ce qui leur permet de s'adapter à la mémoire du matériel grand public ou d'atteindre un débit de pointe sur NVIDIA Blackwell. Cependant, pour l'évaluation initiale, nous voulions les exécuter sur des clusters H200 Hopper existants avec un minimum de modifications du moteur d'inférence. Hopper ne possède pas de cœurs tensoriels FP4 dédiés, introduits par Blackwell. Par conséquent, nous avons décidé d'utiliser les modèles avec une précision FP8 afin de minimiser le besoin de noyaux personnalisés et d'optimiser l'utilisation du matériel disponible.
À haut niveau, les LLM de type transformeur sont structurellement simples :
Intégration des entrées
Une séquence de couches de transformeur. Chacune contient un bloc d'attention et un bloc MLP dense ou MoE clairsemé.
Projection de logit de sortie
Lors de la mise en place d'un nouveau modèle de transformeur, nous cherchons principalement à savoir dans quelle mesure ils correspondent aux modèles existants afin d'identifier les changements nécessaires. OpenAI a eu la gentillesse de partager un aperçu de ses modèles à l'avance, ce qui nous a permis d'ajuster notre configuration d'inférence en conséquence. Nous avons constaté que le modèle nécessitait effectivement un certain nombre de petites modifications.
Attention : GQA avec Attention Sinks
Chaque tête d'attention dispose d'un paramètre « sink » pré-entraîné qui est pris en compte dans le Softmax
Encodage positionnel YaRN, similaire à DeepSeek-V3
Les projections QKV ont des biais, similaires à Qwen 2
La projection de sortie a un biais
MLP : Mélange d'experts clairsemé (MoE)
Fonction d'activation SwiGLU, différente de la plupart des modèles à poids ouverts
Softmax après Top-K pour les poids des experts
Les experts ont des biais
Attendant un nombre de paramètres compris entre 100B et 200B, nous avons décidé de :
Étendre FlashInfer pour prendre en charge les « attention sinks »
Réutiliser l'implémentation MoE déjà créée pour la famille de modèles DeepSeek-V3
Choisir la mise à l'échelle par blocs FP8 128x128 comme schéma de quantification, en étendant les noyaux DeepGEMM pour prendre en charge un terme de biais.
Moteur d'inférence interne
Nos efforts d'inférence sont soutenus par notre moteur d'inférence interne, ROSE. Nous développons ROSE pour qu'il soit un framework flexible permettant d'intégrer rapidement de nouveaux modèles. De plus, une fois que nous nous engageons à servir un modèle à grande échelle, il fournit une plateforme pour optimiser et améliorer les performances afin d'atteindre l'état de l'art.
ROSE expose un moteur LLM, qui peut charger un modèle et générer des jetons décodés pour celui-ci via plusieurs décodeurs, y compris des décodeurs spéculatifs et MTP. Les modèles eux-mêmes sont composés d'un ensemble personnalisé de couches, qui prennent en charge diverses configurations pour la quantification et le parallélisme. Sous les couches, il regroupe à la fois des noyaux Triton et CUDA qui implémentent et fusionnent efficacement les calculs effectués par les couches individuelles.
ROSE est principalement construit en Python et s'appuie sur PyTorch pour les définitions de modèles. Bien que Python nous permette d'être flexibles et de nous adapter aux nouveaux modèles, nous migrons la plupart des composants sensibles aux performances, tels que le service et la planification par lots, vers Rust.
Pour mettre en place un nouveau modèle, nous définissons d'abord la hiérarchie du modèle et construisons un convertisseur de poids pour celui-ci. Une fois tous les poids comptabilisés, nous définissons une passe avant (forward pass) pour le cas d'utilisation le plus simple TP=1 et nous nous assurons qu'il fonctionne de bout en bout. Enfin, nous implémentons et testons la prise en charge de diverses formes de parallélisme avant de publier un nouveau conteneur et de déployer le modèle sur un cluster pour évaluation. Nous itérons ensuite sur les performances, en nous appuyant sur les commentaires des tableaux de bord et des analyses comparatives plus fines.
ROSE fonctionne sur des jetons numériques, avec peu de connaissances sur les formats de Chat en dehors des tests d'intégration. En parallèle, nous avons dû examiner l'ajustement de l'infrastructure environnante pour prendre en charge le tokenizer Harmony et mapper correctement les requêtes aux séquences de jetons d'entrée.
Avec le modèle GPT OSS, nous avons constaté qu'aucune modification n'était requise pour nos décodeurs, nos harnais de graphes CUDA ou l'infrastructure environnante, ce qui nous a permis de concentrer nos efforts sur le réglage des noyaux soutenant le modèle.
Noyaux pour GPT-OSS
Attention Sink
L'attention sink introduit un facteur de biais supplémentaire avant le softmax, accumulé avec le produit de Q et K :
attn = softmax(q @ k^T * sm_scale + sink) * VBien qu'une implémentation naïve soit assez triviale, des implémentations d'attention efficaces, telles que FlashInfer, parallélisent le calcul de l'attention à la fois sur des têtes indépendantes et sur la longueur de la séquence KV. De plus, pour la stabilité numérique, Softmax est calculé en ligne tout en soustrayant l'élément maximal pour la stabilité numérique :
softmax(x) = e^x / sum(e^x) = e ^ (x - max(x)) / sum(e ^ (x - max(x))L'implémentation en ligne suivait un maximum courant m initialisé à -inf et une échelle d à 1. En initialisant le maximum à la valeur sink de la tête actuelle, nous nous assurions qu'il serait accumulé correctement dans le Softmax. Nous avons dû veiller à ce que ce maximum ne soit inclus dans le premier bloc que si l'attention était divisée sur plusieurs blocs le long de la longueur de la séquence.
Nous avons ajusté le modèle de noyau FlashInfer FA2, utilisé à la fois pour le pré-remplissage et le décodage, pour inclure les paramètres sink.
MoE
La principale différence entre la couche MoE de différents modèles est généralement le schéma de routage. Anticipant une variabilité substantielle, ROSE implémente ce noyau en Triton, ce qui nous permet de l'adapter facilement à de nouveaux modèles. Dans le cas de GPT-OSS, nous avons dû ajuster le score de pondération pour effectuer le softmax uniquement sur les experts sélectionnés Top-K, contrairement à certains modèles de style DeepSeek qui calculent le softmax sur tous les experts. Nous avons trouvé qu'il est essentiel pour la précision de calculer les poids des experts avec une précision bfloat16.
Le défi avec la couche MoE était dû à notre décision de réutiliser les noyaux DeepGEMM existants, qui manquaient de prise en charge des termes de biais. Heureusement, au fil du temps, nous nous sommes profondément intégrés avec eux, en apportant des modifications pour mieux les connecter avec nos noyaux de répartition personnalisés « all-to-all ». Nous avons ajouté la prise en charge des biais à DeepGEMM en initialisant les registres d'accumulateur WGMMA aux valeurs de biais chargées depuis la mémoire. Il s'agit d'une opération ponctuelle lors du traitement d'un bloc MN, le coût est donc probablement négligeable et le cache L2 garantit un accès efficace à ces valeurs.
Comme ces modèles ne bénéficient pas facilement du parallélisme de données, nous avons réutilisé la répartition uniquement TP et les noyaux de combinaison. Les entrées pour la répartition sont répliquées sur tous les rangs, ainsi la répartition sélectionne les jetons pour les experts localement disponibles. La combinaison effectue l'accumulation pondérée via NVLink.
Optimisations des performances
Même si notre objectif était de mettre en place les modèles rapidement, nous voulions nous assurer que les performances restaient raisonnables. Après avoir vérifié l'exactitude par rapport à une implémentation de référence fournie par OpenAI, nous avons profilé notre implémentation à l'aide du profileur PyTorch par défaut, en surveillant les allocations de blocs et de fils (threads) sur les noyaux. La fonctionnalité que nous avons réutilisée a été conçue pour des modèles ayant une dimension cachée plus grande de 7168, nettement plus grande que celle de 2880 des modèles GPT-OSS. Nous avons spécialisé les lanceurs de noyaux pour choisir de meilleures dimensions de grille, augmentant considérablement le débit.
Tokénisation et canaux
Le format de Chat d'Harmony contient plusieurs concepts importants pour structurer les conversations, le contenu de raisonnement et les appels de fonction. Dans ce format, chaque message se compose d'un en-tête et d'un contenu :
<|start|>{header}<|message|>{content}<|end|>L'en-tête contient des métadonnées — plus important encore, le rôle (système, développeur, utilisateur, assistant, outil), le canal et un destinataire tel que to=functions.<function-name> lors de l'appel d'une fonction.
Les canaux (tels que l'analyse, le commentaire et la réponse finale) rendent les sorties du modèle plus transparentes et segmentées. Parce que le format impose cette séparation, le modèle peut raisonner de manière transparente (et être inspecté pour le débogage) sans divulguer la chaîne de pensée en production. Les balises de destinataire (en-têtes to=) indiquent à l'exécution quel acteur doit recevoir la prochaine charge utile — qu'il s'agisse d'une fonction, du modèle lui-même ou de l'utilisateur final.
Notre moteur d'inférence ROSE est agnostique au format. Il reçoit un lot de jetons d'entrée et diffuse en retour des jetons de sortie. Dans notre pile d'inférence, la tâche de formater les entrées en une invite tokénisée et d'analyser les résultats du LLM en messages structurés est gérée par le service frontal API JSON dédié. Nous avons intégré Harmony en ajoutant un nouveau formateur/analyseur enfichable à ce frontal, permettant au backend de rester inchangé tandis que le frontal gère proprement les règles de format de Chat, les appels d'outils et le streaming. Cette séparation des préoccupations maintient l'architecture modulaire, permettant une adoption rapide de nouveaux formats, de fonctionnalités de réponse avec des changements de backend minimes.
Coût et performances
Compte tenu de la taille relativement petite des modèles GPT-OSS, nous limitons le déploiement d'une réplique à un seul nœud pour éviter les frais généraux de communication entre les nœuds. Notre implémentation prend en charge des combinaisons flexibles de parallélisme d'experts (EP), de parallélisme de données (DP) et de parallélisme de tenseur (TP). Pour déterminer la configuration de déploiement optimale, nous avons comparé toutes les combinaisons de stratégies de partitionnement sur des tailles de lot allant de 1 à 128. Grâce à la Désagrégation du Pré-remplissage et du Décodage, nous sommes en mesure de discuter du compromis performance-coût séparément pour le pré-remplissage et le décodage.
Pour les estimations de coûts, nous supposons un tarif de marché nominal H200 de 3,00 $/heure (note : ceci n'est pas notre prix réel de GPU).
Nous avons découvert que le réglage de batch_size=1 et DP=1 donne les meilleures performances de pré-remplissage. Différentes configurations TP offrent ensuite des compromis variables entre la latence du premier jeton et le coût. Les tableaux ci-dessous présentent la latence de pré-remplissage et le coût par million de jetons d'entrée pour diverses configurations et longueurs d'entrée.
GPT-OSS 120B :
Longueur d'entrée | 8192 | 32768 | 65536 | 128000 |
EP1 DP1 TP1 | 0,364s, 0,037 $ | 2,421s, 0,062 $ | 7,375s, 0,094 $ | 23,902s, 0,156 $ |
EP2 DP1 TP2 | 0,190s, 0,039 $ | 1,245s, 0,063 $ | 3,786s, 0,096 $ | 12,116s, 0,158 $ |
EP4 DP1 TP4 | 0,165s, 0,067 $ | 0,900s, 0,092 $ | 2,449s, 0,125 $ | 7,165s, 0,187 $ |
EP8 DP1 TP8 | 0,179s, 0,145 $ | 0,839s, 0,171 $ | 2,003s, 0,204 $ | 5,119s, 0,267 $ |
Latence de préremplissage et coût par million de jetons d’entrée pour GPT-OSS 120B selon la configuration de parallélisme et la longueur d’entrée.
GPT-OSS 20B :
Longueur d'entrée | 8192 | 32768 | 65536 | 128000 |
EP1 DP1 TP1 | 0,239s, 0,024 $ | 1,610s, 0,041 $ | 4,895s, 0,062 $ | 16,037s, 0,104 $ |
EP2 DP1 TP2 | 0,127s, 0,026 $ | 0,833s, 0,042 $ | 2,522s, 0,064 $ | 8,143s, 0,106 $ |
EP4 DP1 TP4 | 0,108s, 0,044 $ | 0,593s, 0,060 $ | 1,616s, 0,082 $ | 4,766s, 0,124 $ |
EP8 DP1 TP8 | 0,116s, 0,094 $ | 0,547s, 0,111 $ | 1,310s, 0,133 $ | 3,365s, 0,175 $ |
Latence de préremplissage et coût par million de jetons d’entrée pour GPT-OSS 20B selon la configuration de parallélisme et la longueur d’entrée.
Pour le décodage, nous avons découvert que EP4 DP1 TP4 est la meilleure configuration pour la plupart des cas. Les quatre graphiques ci-dessous illustrent le compromis entre la vitesse de décodage et le coût par million de jetons de sortie pour les modèles 120B et 20B à des longueurs de séquence de 8192 et 32768.
Nous avons également envisagé d'utiliser le plus petit modèle 20B comme modèle de brouillon pour le décodage spéculatif pour le plus grand modèle 120B. Cependant, comme le nombre de paramètres activés est similaire (3B contre 5B), les accélérations résultantes étaient marginales.
Références
Pré-remplissage et décodage désagrégés
Accélérer Sonar grâce à la spéculation
Latence plus faible et débit plus élevé avec le déploiement DeepSeek multi-nœuds
Communication efficace et portable par mélange d'experts
FlashInfer : Moteur d'attention efficace et personnalisable pour le service d'inférence LLM
Modèles de langage en streaming efficaces avec Attention Sinks
Format de réponse OpenAI Harmony | OpenAI Cookbook
Citation
@online{perplexity2025GptOssOnDay0,
author = {{Perplexity} and Nandor Licker and Lequn Chen and Vladimir Zaytsev and Kevin Hu and Lauren Kolm and Jesse Dwyer},
title = {{GPT-OSS on day 0}},
date = {2025-08-08},
url = {https://www.perplexity.ai/hub/blog/gpt-oss-on-day-0}
}