GPT-OSS am Day 0
Day-0-Support für GPT-OSS auf H200 durch Anpassung von ROSE mit FP8, Sink-Attention und MoE-Optimierungen
Perplexity hat sich verpflichtet, wissbegierigen Nutzern, die präzise und vertrauenswürdige Antworten sowie agentenbasiertes Handeln erwarten, die besten KI-Modelle zur Verfügung zu stellen. OpenAI kündigte vor Kurzem seine Open-Weight-Modelle (gpt-oss-20b und gpt-oss-120b) an. Wie bei vielen führenden Modellen gehört Perplexity zu den ersten Organisationen, die gpt-oss-20b und gpt-oss-120b evaluieren.
In diesem Beitrag stellen wir die Infrastrukturentscheidungen unseres internen Inferenz-Stacks vor, die den Day-0-Support ermöglicht haben. Wir konzentrieren uns auf den Betrieb dieser Modelle auf NVIDIA H200 GPUs und erläutern die Kernel-Änderungen, Bereitstellungsentscheidungen sowie das Abwägen von Geschwindigkeit und Kosten.
GPT-OSS auf Hopper
Die Open-Weight-Modelle werden mit MXFP4-Quantisierung bereitgestellt, wodurch sie auf Consumer-Hardware passen oder auf NVIDIA Blackwell den maximalen Durchsatz erzielen. Für die erste Evaluierung wollten wir sie jedoch auf bestehenden H200-Hopper-Clustern mit minimalen Änderungen an der Inferenz-Engine ausführen. Hopper verfügt nicht über dedizierte FP4-Tensor-Cores, die mit Blackwell eingeführt wurden. Folglich entschieden wir uns, die Modelle stattdessen mit FP8-Präzision zu betreiben, um den Bedarf an benutzerdefinierten Kernels zu minimieren und die verfügbare Hardware optimal zu nutzen.
Auf einer hohen Abstraktionsebene sind Transformer-LLMs strukturell einfach:
Input-Embedding
Eine Sequenz von Transformer-Layern. Jeder enthält einen Attention-Block sowie einen dichten MLP- oder spärlichen MoE-Block.
Output-Logit-Projektion
Bei der Implementierung eines neuen Transformer-Modells sind wir in erster Linie daran interessiert, inwieweit diese den bestehenden Modellen entsprechen, um die erforderlichen Änderungen zu identifizieren. OpenAI hat uns freundlicherweise vorab einen Überblick über ihre Modelle gegeben, was es uns ermöglichte, unser Inferenz-Setup entsprechend anzupassen. Wir stellten fest, dass das Modell eine ganze Reihe kleinerer Änderungen erforderte.
Attention: GQA mit Attention-Sinks
Jeder Attention-Head verfügt über einen vorab trainierten Sink-Parameter, der in den Softmax einfließt.
YaRN-Positionskodierung, ähnlich wie bei DeepSeek-V3
QKV-Projektionen mit Biases, ähnlich wie bei Qwen 2
Output-Projektion mit Bias
MLP: Sparse Mixture-of-Expert (MoE)
SwiGLU-Aktivierungsfunktion, abweichend von den meisten Open-Weight-Modellen
Softmax nach Top-K für Expert-Gewichte
Experts mit Biases
Da wir von einer Parameteranzahl im Bereich von 100B bis 200B ausgingen, entschieden wir uns für Folgendes:
Erweiterung von FlashInfer zur Unterstützung von Attention-Sinks
Wiederverwendung der bereits für die DeepSeek-V3-Modellfamilie entwickelten MoE-Implementierung.
Wahl von FP8 128x128 Block-Skalierung als Quantisierungsschema und Erweiterung der DeepGEMM-Kernel zur Unterstützung eines Bias-Terms.
Interne Inferenz-Engine
Unsere Inferenz-Bemühungen werden durch unsere interne Inferenz-Engine ROSE unterstützt. Wir bauen ROSE zu einem flexiblen Framework aus, das eine schnelle Implementierung neuer Modelle ermöglicht. Sobald wir uns dazu entschließen, ein Modell in großem Maßstab bereitzustellen, bietet es zudem eine Plattform, um die Leistung zu optimieren und auf ein branchenführendes Niveau zu heben.
ROSE stellt eine LLM-Engine bereit, die ein Modell laden und durch mehrere Decoder, einschließlich spekulativer Decoder und MTP-Decoder, dekodierte Tokens generieren kann. Die Modelle selbst bestehen aus einer benutzerdefinierten Layer-Kombination, die verschiedene Konfigurationseinstellungen für Quantisierung und Parallelität unterstützen. Unter den Layern bündelt sie sowohl Triton- als auch CUDA-Kernel, die die von einzelnen Layern durchgeführten Berechnungen effizient implementieren und verschmelzen.
ROSE ist primär in Python geschrieben und basiert für Modelldefinitionen auf PyTorch. Während Python uns Flexibilität bietet und die Anpassung an neue Modelle erleichtert, migrieren wir die meisten leistungsabhängigen Komponenten wie Serving und Batch-Scheduling auf Rust.
Um ein neues Modell einzuführen, definieren wir zunächst die Modellhierarchie und erstellen einen Weight-Converter dafür. Nachdem alle Gewichte erfasst sind, definieren wir einen Forward-Pass für den einfachsten TP=1-Anwendungsfall und stellen sicher, dass dieser durchgängig funktioniert. Abschließend implementieren und testen wir die Unterstützung für verschiedene Formen der Parallelität, bevor wir einen neuen Container freigeben und das Modell zur Evaluierung auf einem Cluster bereitstellen. Danach iterieren wir hinsichtlich der Leistung und stützen uns dabei auf das Feedback aus Dashboards und detaillierten Benchmarks.
ROSE arbeitet mit numerischen Tokens und verfügt über wenig Kenntnis von Chat-Formaten außerhalb von Integrationstests. Parallel dazu mussten wir die umgebende Infrastruktur anpassen, um den Harmony-Tokenizer zu unterstützen und Anfragen korrekt auf Input-Token-Sequenzen abzubilden.
Beim GPT-OSS-Modell stellten wir fest, dass keine Änderungen an unseren Decodern, CUDA-Graph-Harnesses oder der umgebenden Infrastruktur erforderlich waren, sodass wir uns darauf konzentrieren konnten, die das Modell unterstützenden Kernel zu optimieren.
Kernel für GPT-OSS
Sink-Attention
Sink-Attention führt einen zusätzlichen Bias-Faktor vor dem Softmax ein, der mit dem Produkt aus Q und K akkumuliert wird:
attn = softmax(q @ k^T * sm_scale + sink) * VWährend eine naive Implementierung relativ trivial ist, parallelisieren effiziente Attention-Implementierungen, wie FlashInfer, die Attention-Berechnung über sowohl unabhängige Heads als auch über die KV-Sequenzlänge hinweg. Für die numerische Stabilität wird Softmax zudem online berechnet, wobei das maximale Element subtrahiert wird:
softmax(x) = e^x / sum(e^x) = e ^ (x - max(x)) / sum(e ^ (x - max(x))Die Online-Implementierung verfolgte ein laufendes Maximum m, initialisiert auf -inf, und einen Skalierungsfaktor d auf 1. Durch die Initialisierung des Maximums auf den Sink-Wert des aktuellen Heads stellten wir sicher, dass dieser korrekt in den Softmax akkumuliert wurde. Wir mussten darauf achten, dass dieses Maximum nur im ersten Chunk enthalten war, falls die Attention über mehrere Blöcke entlang der Sequenzlänge aufgeteilt wurde.
Wir haben die FlashInfer FA2-Kernel-Vorlage, die sowohl für Prefill als auch für Decode verwendet wird, um die Sink-Parameter erweitert.
MoE
Der Hauptunterschied zwischen der MoE-Layer verschiedener Modelle ist in der Regel das Routing-Schema. Da wir mit erheblichen Unterschieden rechneten, implementiert ROSE diesen Kernel in Triton, wodurch wir ihn leicht an neue Modelle anpassen können. Im Fall von GPT-OSS mussten wir das Weight-Scoring so anpassen, dass Softmax nur über die Top-K-ausgewählten Experten durchgeführt wird, im Gegensatz zu einigen DeepSeek-ähnlichen Modellen, die Softmax über alle Experten berechnen. Wir haben festgestellt, dass es für die Genauigkeit entscheidend ist, die Expert-Gewichte in bfloat16-Präzision zu berechnen.
Die Herausforderung bei der MoE-Layer lag in unserer Entscheidung, die bestehenden DeepGEMM-Kernel wiederzuverwenden, denen die Unterstützung für Bias-Terme fehlte. Glücklicherweise konnten wir sie im Laufe der Zeit tief integrieren und Anpassungen vornehmen, um sie besser mit unseren benutzerdefinierten All-to-All-Dispatch-Kerneln zu verbinden. Wir haben die Bias-Unterstützung zu DeepGEMM hinzugefügt, indem wir die WGMMA-Akkumulatorregister mit den aus dem Speicher geladenen Bias-Werten initialisiert haben. Dies ist ein einmaliger Vorgang bei der Verarbeitung eines MN-Blocks, daher sind die Kosten voraussichtlich vernachlässigbar und der L2-Cache stellt einen effizienten Zugriff auf diese Werte sicher.
Da diese Modelle nicht unmittelbar von Datenparallelität profitieren, haben wir TP-only-Dispatch- und Combine-Kernel wiederverwendet. Die Inputs für Dispatch werden über alle Ränge repliziert, wodurch Dispatch die Tokens für die lokal verfügbaren Experten auswählt. Combine führt die gewichtete Akkumulation über NVLink durch.
Leistungsoptimierungen
Obwohl unser Ziel darin bestand, die Modelle schnell bereitzustellen, wollten wir sicherstellen, dass die Leistung dennoch angemessen ist. Nachdem wir die Korrektheit anhand einer von OpenAI bereitgestellten Referenzimplementierung sichergestellt hatten, profilierten wir unsere Implementierung mithilfe des Standard-PyTorch-Profilers und achteten dabei auf Block- und Thread-Zuweisungen über die Kernel hinweg. Die wiederverwendete Funktionalität war für Modelle mit einer größeren Hidden-Dimension von 7168 entwickelt worden, was wesentlich größer ist als die 2880 der GPT-OSS-Modelle. Wir spezialisierten die Kernel-Launcher darauf, bessere Grid-Dimensionen zu wählen, was den Durchsatz erheblich steigerte.
Tokenisierung und Kanäle
Das Chat-Format von Harmony enthält mehrere wichtige Konzepte für die Strukturierung von Konversationen, Argumentationsinhalten und Funktionsaufrufen. In diesem Format besteht jede Nachricht aus einem Header und einem Inhalt:
<|start|>{header}<|message|>{content}<|end|>Der Header enthält Metadaten – am wichtigsten sind die Rolle (system, developer, user, assistant, tool), der Kanal und ein Empfänger wie to=functions.<function-name> beim Aufruf eines Tools.
Kanäle (wie Analyse, Kommentar und endgültige Antwort) machen die Ausgaben des Modells transparenter und segmentierter. Da das Format diese Trennung erzwingt, kann das Modell transparent argumentieren (und zur Fehlerbehebung überprüft werden), ohne dass die Gedankenkette (Chain-of-Thought) in die Produktion gelangt. Empfänger-Tags (to=-Header) teilen der Runtime genau mit, welcher Akteur den nächsten Payload erhalten soll – ob dies eine Funktion, das Modell selbst oder der Endbenutzer ist.
Unsere Inferenz-Engine ROSE ist formatunabhängig. Sie empfängt einen Batch von Input-Tokens und streamt Output-Tokens zurück. In unserem Inferenz-Stack wird die Aufgabe, Inputs in einen tokenisierten Prompt zu formatieren und LLM-Ergebnisse wieder in strukturierte Nachrichten zu parsen, vom dedizierten JSON-API-Frontend-Service übernommen. Wir haben Harmony integriert, indem wir diesem Frontend einen neuen pluggable Formatter/Parser hinzugefügt haben, sodass das Backend unverändert bleiben kann, während das Frontend Chat-Formatregeln, Tool-Aufrufe und Streaming sauber verwaltet. Diese Trennung der Zuständigkeiten hält die Architektur modular und ermöglicht eine schnelle Übernahme neuer Formate und Antwortfunktionen bei minimalen Backend-Änderungen.
Kosten und Leistung
Angesichts der relativ geringen Größe der GPT-OSS-Modelle beschränken wir die Bereitstellung eines Replikats auf einen einzelnen Knoten, um den Overhead durch Knoten-übergreifende Kommunikation zu vermeiden. Unsere Implementierung unterstützt flexible Kombinationen aus Expert Parallelism (EP), Data Parallelism (DP) und Tensor Parallelism (TP). Um das optimale Deployment-Setup zu bestimmen, haben wir alle Kombinationen von Sharding-Strategien über Batch-Größen von 1 bis 128 gebenchmarkt. Dank Prefill-Decode Disaggregation können wir das Verhältnis von Leistung und Kosten für Prefill und Decode getrennt betrachten.
Für Kostenschätzungen nehmen wir einen nominalen H200-Marktpreis von 3,00 $/Stunde an (Hinweis: Dies ist nicht unser tatsächlicher GPU-Preis).
Wir haben festgestellt, dass die Einstellung batch_size=1 und DP=1 die beste Prefill-Leistung liefert. Unterschiedliche TP-Konfigurationen bieten dann verschiedene Kompromisse zwischen Latenz des ersten Tokens und Kosten. Die nachstehenden Tabellen zeigen die Prefill-Latenz und die Kosten pro Million Input-Tokens für verschiedene Konfigurationen und Eingabelängen.
GPT-OSS 120B:
Eingabelänge | 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 $ |
GPT-OSS 120B Prefill-Latenz und Kosten pro Million Eingabetokens nach Parallelismuskonfiguration und Eingabelänge.
GPT-OSS 20B:
Eingabelänge | 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 $ |
GPT-OSS 20B Prefill-Latenz und Kosten pro Million Eingabetokens nach Parallelismuskonfiguration und Eingabelänge.
Für Decode haben wir festgestellt, dass EP4 DP1 TP4 in den meisten Fällen die beste Konfiguration ist. Die vier Diagramme unten veranschaulichen das Verhältnis zwischen Decode-Geschwindigkeit und Kosten pro Million Output-Tokens für die 120B- und 20B-Modelle bei Sequenzlängen von 8192 und 32768.
Wir haben auch in Erwägung gezogen, das kleinere 20B-Modell als Draft-Modell für speculative decoding für das größere 120B-Modell zu verwenden. Da jedoch die Anzahl der aktivierten Parameter ähnlich ist (3B vs. 5B), waren die resultierenden Geschwindigkeitsvorteile marginal.
Referenzen
Disaggregated Prefill and Decode
Accelerating Sonar Through Speculation
Lower Latency and Higher Throughput with Multi-node DeepSeek Deployment
Efficient and Portable Mixture-of-Experts Communication
FlashInfer: Efficient and Customizable Attention Engine for LLM Inference Serving
Efficient Streaming Language Models with Attention Sinks
OpenAI Harmony Response Format | OpenAI Cookbook
Zitieren
@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}
}