GPT-OSS på Day 0

Day-0-stöd för GPT-OSS på H200 genom anpassning av ROSE med FP8, sink attention och MoE-optimeringar

FörfattarePerplexity Engineering

Perplexity har som m%c3%a5l att g%c3%a5ra de beste AI-modellerna tillg%c3%a4ngliga f%c3%b6r nyfikna personer som kr%c3%a4ver exakta och tillr%c3%a4litliga svar samt agentbaserade %c3%a5tg%c3%a4rder. OpenAI tillk%c3%a4nnagav nyligen sina modeller med %c3%b6ppna vikter (gpt-oss-20b och gpt-oss-120b). Liksom f%c3%b6r m%c3%a5nga ledande modeller %c3%a4r Perplexity bland de f%c3%b6rsta organisationerna att utv%c3%a4rdera gpt-oss-20b och gpt-oss-120b.

I det h%c3%a4r inl%c3%a4gget delar vi de infrastrukturbeslut f%c3%b6r v%c3%a5r egen inferensstack som gjorde Day-0-st%c3%b6d möjligt. Vi fokuserar p%c3%a5 att k%c3%b6ra dessa modeller p%c3%a5 NVIDIA H200 GPU-er och redogör d%c3%a4rf%c3%b6r f%c3%b6r ändringar i kärnor, distributionsval och avvägningar mellan hastighet och kostnad.

GPT-OSS på Hopper

Modellerna med öppna vikter levereras med MXFP4-kvantisering, vilket gör att de får plats i minnet på konsumenthårdvara eller uppnår maximalt dataflöde på NVIDIA Blackwell. För en första utvärdering ville vi dock köra dem på befintliga H200 Hopper-kluster med minimala ändringar av inferensmotorn. Hopper har inga dedikerade FP4-tensor-kärnor, vilket introducerades av Blackwell. Därför beslutade vi att köra modellerna med FP8-precision i stället för att minimera behovet av anpassade kärnor och utnyttja tillgänglig hårdvara på bästa sätt.

Övergripande sett är transformer-LLM:er strukturellt enkla:

Inbäddning av indata

En sekvens av transformer-lager. Varje lager innehåller ett attentionsblock och ett tätt MLP-block eller ett glest MoE-block.

Utgående logit-projektering

När vi lanserar en ny transformer-modell är vi i första hand intresserade av att ta reda på i vilken utsträckning de matchar befintliga modeller för att identifiera vilka ändringar som krävs. OpenAI delade vänligt nog med sig av en översikt av sina modeller i förväg, vilket gjorde att vi kunde anpassa vår inferensuppsättning därefter. Vi fann att modellen krävde en hel del små ändringar.

Attention: GQA med Attention Sinks

Varje attention-huvud har en förtränad sink-parameter som tas med i beräkningen i Softmax

YaRN-positionskodning, liknande DeepSeek-V3

QKV-projektioner har bias, liknande Qwen 2

Utgående projektion har bias

MLP: Sparse Mixture-of-Expert (MoE)

SwiGLU-aktiveringsfunktion, vilket skiljer sig från de flesta modeller med öppna vikter

Softmax efter Top-K för experivikter

Experter har bias

Eftersom vi förväntade oss att antalet parametrar skulle ligga runt 100B–200B beslutade vi att:

Utöka FlashInfer för att stödja attention sinks

Återanvända den MoE-implementering som redan byggts för DeepSeek-V3-familjen av modeller

Välja FP8 128x128 blockskalning som kvantiseringsschema och utöka DeepGEMM-kärnorna till att stödja en biasterm.

Egen inferensmotor

Våra inferensansträngningar stöds av vår egna inferensmotor, ROSE. Vi utvecklar ROSE till ett flexibelt ramverk som gör det möjligt att snabbt lansera nya modeller. När vi väl har bestämt oss för att köra en modell i stor skala tillhandahåller den dessutom en plattform för att optimera och öka prestandan för att nå den senaste teknikens nivå.

ROSE tillhandahåller en LLM-motor som kan läsa in en modell och generera avkodade token för den via flera avkodare, inklusive spekulativa och MTP-avkodare. Själva modellerna består av en anpassad uppsättning lager som stöder olika konfigurationsparametrar för kvantisering och parallellitet. Under lagren samlar den både Triton- och CUDA-kärnor som effektivt implementerar och sammansmälter de beräkningar som utförs av enskilda lager.

ROSE är till största delen byggt i Python och förlitar sig på PyTorch för modelldefinitioner. Även om Python gör det möjligt för oss att vara flexibla och anpassa oss till nya modeller migrerar vi de flesta prestandakänsliga komponenter, såsom betjäning och batch-schemaläggning, till Rust.

För att lansera en ny modell definierar vi först modellhierarkin och bygger en viktkonverterare för den. När alla vikter har räknats med definierar vi ett framåtriktat steg (forward pass) för det enklaste TP=1-användningsfallet och säkerställer att det fungerar från ende till annan. Slutligen implementerar och testar vi stöd för olika former av parallellitet innan vi släpper en ny behållare och distribuerar modellen på ett kluster för utvärdering. Därefter itererar vi kring prestanda med hjälp av feedback från både instrumentpaneler och mer finkorniga riktmärken.

ROSE hanterar numeriska token och har liten kännedom om chattformat utanför integrationstester. Parallellt behövde vi undersöka hur vi kunde justera den omgivande infrastrukturen för att stödja Harmony-tokenizer och korrekt mappa förfrågningar till indatatokensekvenser.

Med GPT OSS-modellen fann vi att inga ändringar krävdes i våra avkodare, CUDA-grafverktyg eller omgivande infrastruktur, vilket gjorde att vi kunde fokusera våra ansträngningar på att finjustera de kärnor som ligger till grund för modellen.

Kärnor för GPT-OSS

Sink Attention

Sink attention introducerar en extra bias-faktor före softmax, som adderas till produkten av Q och K:

plaintext
attn = softmax(q @ k^T * sm_scale + sink) * V

Även om en naiv implementering är ganska enkel, parallelliserar effektiva attention-implementeringar, såsom FlashInfer, beräkningen av attention över både oberoende huvud och över KV-sekvensens längd. För numerisk stabilitet beräknas Softmax dessutom online samtidigt som det maximala elementet subtraheras för numerisk stabilitet:

plaintext
softmax(x) = e^x / sum(e^x) = e ^ (x - max(x)) / sum(e ^ (x - max(x))

Online-implementeringen spårade ett löpande maximum m som initierades till -inf och en skala d till 1. Genom att initiera maximum till det aktuella huvudets sink-värde säkerställer vi att det läggs till i Softmax på rätt sätt. Vi behövde se till att detta maximum endast inkluderas i det första segmentet om attention delades upp över flera block längs sekvenslängden.

Vi har justerat mallen för FlashInfer FA2-kärnan, som används för både prefill och avkodning, för att inkludera sink-parametrarna.

MoE

Huvudskillnaden mellan MoE-lagret i olika modeller är oftast routningsschemat. Eftersom vi förväntade oss stor variation implementerar ROSE denna kärna i Triton, vilket gör det enkelt att anpassa den till nya modeller. När det gäller GPT-OSS var vi tvungna att justera viktpoängsättningen för att endast utföra softmax över de utvalda Top-K-experterna, till skillnad från vissa modeller i DeepSeek-stil som beräknar softmax över alla experter. Vi fann att det är avgörande för noggrannheten att beräkna experternas vikter med bfloat16-precision.

Utmaningen med MoE-lagret berodde på vårt beslut att återanvända de befintliga DeepGEMM-kärnorna, som saknade stöd för biasterm. Lyckligtvis integrerades vi djupt med dem över tid och gjorde ändringar för att bättre koppla ihop dem med våra anpassade all-to-all-dispatch-kärnor. Vi lade till bias-stöd i DeepGEMM genom att initiera WGMMA-ackumulatorregistren till de bias-värden som lästs in från minnet. Detta sker en gång under bearbetningen av ett MN-block, varför kostnaden är försumbar och L2-cachen säkerställer effektiv åtkomst till dessa värden.

Eftersom dessa modeller inte drar någon direkt nytta av dataparallellitet återanvände vi dispatch- och combine-kärnor som enbart använder TP. Inditarna till dispatch replikeras över alla ranger (ranks), så dispatch väljer de token som finns tillgängliga lokalt för experterna. Combine utför den viktade ackumuleringen över NVLink.

Prestandajusteringar

Även om vårt mål var att snabbt få igång modellerna ville vi säkerställa att prestandan ändå var rimlig. Efter att ha säkerställt korrektheten mot en referensimplementering som tillhandahållits av OpenAI profilerade vi vår implementering med standardprofileraren i PyTorch och höll koll på block- och trådallokeringar över kärnor. Den funktionalitet vi återanvände byggdes för modeller som hade en större dold dimension på 7168, vilket är avsevärt större än 2880 för GPT-OSS-modellerna. Vi specialiserade kärnlanserarna för att välja bättre rutnätsdimensioner, vilket ökade dataflödet avsevärt.

Tokenisering och kanaler

Harmonys chattformat har flera viktiga begrepp för att strukturera konversationer, resonemangsinnehåll och funktionsanrop. I detta format består varje meddelande av ett huvud och innehåll:

plaintext
<|start|>{header}<|message|>{content}<|end|>

Huvudet innehåller metadata – framför allt rollen (system, utvecklare, användare, assistent, verktyg), kanalen och en mottagare som to=functions.<function-name> vid anrop av ett verktyg.

Kanaler (som analys, kommentarer och slutgiltigt svar) gör modellens utdata mer transparenta och segmenterade. Eftersom formatet framtvingar denna uppdelning kan modellen resonera på ett transparent sätt (och granskas för felsökning) utan att kedjeresonemang (chain-of-thought) läcker ut i produktionen. Mottagartaggar (to=-huvuden) talar om för körtiden exakt vilken aktör som ska ta emot nästa nyttolast (payload) – oavsett om det är en funktion, själva modellen eller slutanvändaren.

Vår inferensmotor ROSE är formatagnostisk. Den tar emot en batch med indatatoken och strömmar tillbaka utdatatoken. I vår inferensstack hanteras uppgiften att formatera indata till en tokeniserad prompt och tolka LLM-resultat tillbaka till strukturerade meddelanden av den dedikerade JSON API-klienttjänsten (frontend). Vi integrerade Harmony genom att lägga till en ny utbytbar formaterare/parser till denna frontend, vilket gör att backend kan förbli oförändrad samtidigt som frontend rent och snyggt hanterar chattformatsregler, funktionsanrop och strömning. Denna ansvarsfördelning håller arkitekturen modulär, vilket möjliggör snabb anpassning av nya format och svarsfunktioner med minimala ändringar i backend.

Kostnad och prestanda

Med tanke på den relativt lilla storleken på GPT-OSS-modellerna begränsar vi distributionen av en replik till en enda nod för att undvika overhead från kommunikation mellan noder. Vår implementering stöder flexibla kombinationer av expertparallellitet (EP), dataparallellitet (DP) och tensorparallellitet (TP). För att fastställa den optimala distributionskonfigurationen körde vi riktmärken (benchmarks) för alla kombinationer av shardningsstrategier över batchstorlekar från 1 till 128. Tack vare Prefill-Decode Disaggregation kan vi diskutera avvägningen mellan prestanda och kostnad separat för prefill och avkodning.

För kostnadsuppskattningar antar vi ett nominellt marknadspris för H200 på 3,00 USD/timme (observera: detta är inte vårt faktiska GPU-pris).

Vi upptäckte att inställningen batch_size=1 och DP=1 ger bäst prefill-prestanda. Olika TP-konfigurationer ger sedan olika avvägningar mellan svarstid för första token (first-token latency) och kostnad. Tabellerna nedan visar prefill-svarstid och kostnad per miljon indatatoken för olika konfigurationer och indatalängder.

GPT-OSS 120B:

Indatalängd

8192

32768

65536

128000

EP1 DP1 TP1

0,364s, 0,037 USD

2,421s, 0,062 USD

7,375s, 0,094 USD

23,902s, 0,156 USD

EP2 DP1 TP2

0,190s, 0,039 USD

1,245s, 0,063 USD

3,786s, 0,096 USD

12,116s, 0,158 USD

EP4 DP1 TP4

0,165s, 0,067 USD

0,900s, 0,092 USD

2,449s, 0,125 USD

7,165s, 0,187 USD

EP8 DP1 TP8

0,179s, 0,145 USD

0,839s, 0,171 USD

2,003s, 0,204 USD

5,119s, 0,267 USD

GPT-OSS 120B förifylld latens och kostnad per miljon inmatningstoken efter parallellitetskonfiguration och inmatningslängd.

GPT-OSS 20B:

Indatalängd

8192

32768

65536

128000

EP1 DP1 TP1

0,239s, 0,024 USD

1,610s, 0,041 USD

4,895s, 0,062 USD

16,037s, 0,104 USD

EP2 DP1 TP2

0,127s, 0,026 USD

0,833s, 0,042 USD

2,522s, 0,064 USD

8,143s, 0,106 USD

EP4 DP1 TP4

0,108s, 0,044 USD

0,593s, 0,060 USD

1,616s, 0,082 USD

4,766s, 0,124 USD

EP8 DP1 TP8

0,116s, 0,094 USD

0,547s, 0,111 USD

1,310s, 0,133 USD

3,365s, 0,175 USD

GPT-OSS 20B förifylld latens och kostnad per miljon inmatningstoken efter parallellitetskonfiguration och inmatningslängd.

För avkodning upptäckte vi att EP4 DP1 TP4 är den bästa konfigurationen i de flesta fall. De fyra diagrammen nedan illustrerar avvägningen mellan avkodningshastighet och kostnad per miljon utdatatoken för både 120B- och 20B-modellerna vid sekvenslängder på 8192 och 32768.

Endast avkodning: kostnad per miljon utdata-token jämfört med avkodningshastighet för GPT-OSS 120B vid sekvenslängd 8 192, med jämförelse av konfigurationerna EP1, EP2, EP4 och EP8.
Endast avkodning: kostnad per miljon utdata-token jämfört med avkodningshastighet för GPT-OSS 120B vid sekvenslängd 32 768, med jämförelse av konfigurationerna EP1, EP2, EP4 och EP8.
Endast avkodning: kostnad per miljon utdata-token jämfört med avkodningshastighet för GPT-OSS 20B vid sekvenslängd 8 192, med jämförelse av konfigurationerna EP1, EP2, EP4 och EP8.
Endast avkodning: kostnad per miljon utdata-token jämfört med avkodningshastighet för GPT-OSS 20B vid sekvenslängd 32 768, med jämförelse av konfigurationerna EP1, EP2, EP4 och EP8.

Vi har också övervägt att använda den mindre 20B-modellen som utkastmodell för spekulativ avkodning (speculative decoding) för den större 120B-modellen. Eftersom antalet aktiverade parametrar är likartat (3B vs. 5B) blev dock hastighetsökningen marginell.

Referenser

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

​pplx-kernels

DeepGEMM

FlashInfer: Efficient and Customizable Attention Engine for LLM Inference Serving

Efficient Streaming Language Models with Attention Sinks

DeepSeek-V3 Technical Report​

​OpenAI Harmony Response Format | OpenAI Cookbook​

Citering

BibTeX
@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}
}