GPT-OSS în Ziua 0

Asistență în Ziua 0 pentru GPT‑OSS pe H200 prin adaptarea ROSE cu FP8, sink attention și optimizări MoE

AutoriPerplexity Engineering

Perplexity se angajează să pună la dispoziție cele mai bune modele de inteligență artificială persoanelor curioase care solicită răspunsuri precise și de încredere și acțiuni autonome. OpenAI și-a anunțat recent modelele cu pondere deschisă (gpt-oss-20b și gpt-oss-120b). Ca și în cazul multor modele de top, Perplexity se numără printre primele organizații care evaluează gpt-oss-20b și gpt-oss-120b.

În această postare, împărtășim deciziile legate de infrastructură ale stivei noastre interne de inferență care au făcut posibilă asistența din Ziua 0. Ne concentrăm pe servirea acestor modele pe GPU-uri NVIDIA H200, detaliind modificările aduse nucleului, alegerile de implementare și compromisurile dintre viteză și cost.

GPT-OSS pe Hopper

Modelele cu pondere deschisă sunt livrate utilizând cuantificarea MXFP4, ceea ce le ajută să se încadreze în memoria hardware-ului de grad consumer sau să obțină un debit maxim pe NVIDIA Blackwell. Cu toate acestea, pentru evaluarea inițială, am dorit să le rulăm pe clusterele H200 Hopper existente, cu modificări minimale ale motorului de inferență. Hopper nu are nuclee tensor FP4 dedicate, care au fost introduse de Blackwell. În consecință, am decis să servim modelele cu precizie FP8 pentru a minimiza nevoia de nuclee personalizate și a utiliza optim hardware-ul disponibil.

La un nivel înalt, modelele lingvistice mari (LLM) de tip transformer sunt simple din punct de vedere structural:

Embedded de intrare (Input embedding)

O secvență de straturi transformer. Fiecare conține un bloc de atenție și un bloc dens MLP sau rar MoE.

Proiecție logit de ieșire

Atunci când implementăm un nou model transformer, suntem interesați în primul rând să aflăm în ce măsură se potrivesc cu modelele existente, pentru a identifica modificările necesare. OpenAI a împărtășit cu amabilitate o prezentare generală a modelelor lor în avans, permițându-ne să ne ajustăm configurația de inferență în mod corespunzător. Am constatat că modelul a necesitat destul de multe modificări mici.

Atenție: GQA cu Attention Sinks

Fiecare cap de atenție are un parametru sink preantrenat care este inclus în Softmax

Codificare pozițională YaRN, similară cu DeepSeek-V3

Proiecțiile QKV au bias, similar cu Qwen 2

Proiecția de ieșire are bias

MLP: Amestec rar de experți (Sparse Mixture-of-Expert - MoE)

Funcție de activare SwiGLU, diferită față de majoritatea modelelor cu pondere deschisă

Softmax după Top-K pentru ponderile experților

Experții au bias

Așteptându-ne ca numărul de parametri să fie în jur de 100B-200B, am decis să:

Extindem FlashInfer pentru a accepta attention sinks

Reutilizăm implementarea MoE deja construită pentru familia de modele DeepSeek-V3

Alegem scalarea pe blocuri FP8 128x128 ca schemă de cuantificare, extinzând nucleele DeepGEMM pentru a accepta un termen de bias.

Motor de inferență propriu

Eforturile noastre de inferență sunt susținute de motorul nostru propriu de inferență, ROSE. Dezvoltăm ROSE ca pe un cadru flexibil care permite implementarea rapidă a noilor modele. În plus, odată ce ne angajăm să servim un model la scară largă, acesta oferă o platformă pentru a optimiza și a spori performanța pentru a ajunge la cel mai înalt nivel tehnologic.

ROSE expune un motor LLM, care poate încărca un model și genera jetoane decodificate pentru acesta prin intermediul mai multor decodoare, inclusiv decodoare speculative și MTP. Modelele în sine sunt compuse dificil dintr-un set personalizat de straturi care acceptă diverse opțiuni de configurare pentru cuantificare și paralelism. Sub straturi, acesta integrează atât nuclee Triton, cât și CUDA, care implementează și fuzionează eficient calculele efectuate de straturile individuale.

ROSE este construit în principal în Python și se bazează pe PyTorch pentru definițiile modelelor. Deși Python ne permite să fim flexibili și să ne adaptăm la noi modele, migrăm majoritatea componentelor sensibile la performanță, cum ar fi servirea și programarea loturilor (batch scheduling), în Rust.

Pentru a implementa un model nou, definim mai întâi ierarhia modelului și construim un convertor de ponderi pentru acesta. După ce se iau în considerare toate ponderile, definim o trecere înainte (forward pass) pentru cel mai simplu caz de utilizare TP=1 și ne asigurăm că funcționează complet (end-to-end). În cele din urmă, implementăm și testăm suportul pentru diferite forme de paralelism înainte de a lansa un nou container și de a desfășura modelul pe un cluster pentru evaluare. Apoi iterăm performanța, bazându-ne pe feedback de la tablourile de bord și benchmark-uri mai detaliate.

ROSE operează pe jetoane numerice, având puține cunoștințe despre formatele de chat în afara testelor de integrare. În paralel, a trebuit să analizăm ajustarea infrastructurii din jur pentru a accepta tokenizerul Harmony și a mapa corect cererile la secvențele de jetoane de intrare.

Cu modelul GPT OSS, am constatat că nu au fost necesare modificări la decodoarele noastre, la sistemele de grafice CUDA sau la infrastructura din jur, permițându-ne să ne concentrăm eforturile pe ajustarea nucleelor care stau la baza modelului.

Nuclee pentru GPT-OSS

Sink Attention

Sink attention introduce un factor de bias suplimentar înainte de softmax, acumulat cu produsul dintre Q și K:

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

În timp ce o implementare naivă este destul de trivială, implementările eficiente de atenție, cum ar fi FlashInfer, paralelizează calculul atenției atât pe capete independente, cât și pe lungimea secvenței KV. În plus, pentru stabilitate numerică, Softmax este calculat online, scăzând în același timp elementul maximal pentru stabilitate numerică:

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

Implementarea online a urmărit un maxim curent m inițializat la -inf și o scară d la 1. Prin inițializarea maximului la valoarea sink a capului curent, ne-am asigura că acesta va fi acumulat corect în Softmax. A trebuit să avem grijă să ne asigurăm că acest maxim va fi inclus doar în primul segment dacă atenția a fost împărțită pe mai multe blocuri de-a lungul lungimii secvenței.

Am ajustat șablonul de nucleu FlashInfer FA2, utilizat atât pentru prefill, cât și pentru decodare, pentru a include parametrii sink.

MoE

Diferența principală dintre stratul MoE al diferitelor modele este de obicei schema de rutare. Așteptându-ne la o variabilitate substanțială, ROSE implementează acest nucleu în Triton, permițându-ne să îl adaptăm cu ușurință la noi modele. În cazul GPT-OSS, a trebuit să ajustăm scorarea ponderilor pentru a efectua softmax doar pe experții selectați Top-K, spre deosebire de unele modele în stil DeepSeek care calculează softmax pe toți experții. Am constatat că este esențial pentru acuratețe să calculăm ponderile experților în precizie bfloat16.

Provocarea cu stratul MoE s-a datorat deciziei noastre de a reutiliza nucleele DeepGEMM existente, cărora le lipsea suportul pentru termeni de bias. Din fericire, în timp ne-am integrat profund cu acestea, făcând modificări pentru a le conecta mai bine cu nucleele noastre personalizate de expediere all-to-all. Am adăugat suport pentru bias la DeepGEMM prin inițializarea registrelor de acumulator WGMMA la valorile de bias încărcate din memorie. Aceasta este o operațiune unică în timpul procesării unui bloc MN, deci costul este probabil neglijabil, iar memoria cache L2 asigură accesul eficient la aceste valori.

Deoarece aceste modele nu beneficiază direct de paralelismul datelor (Data Parallelism), am reutilizat nucleele de expediere și combinare specifice TP. Intrările pentru expediere sunt replicate pe toate rangurile, astfel încât expedierea selectează jetoanele pentru experții disponibili local. Combinarea efectuează acumularea ponderată prin NVLink.

Optimizări de performanță

Chiar dacă obiectivul nostru a fost să implementăm rapid modelele, am dorit să ne asigurăm că performanța este totuși rezonabilă. După ce am verificat corectitudinea în raport cu o implementare de referință furnizată de OpenAI, ne-am profilat implementarea utilizând profilatorul implicit PyTorch, fiind atenți la alocările de blocuri și fire de execuție din nuclee. Funcționalitatea pe care am reutilizat-o a fost concepută pentru modele care aveau o dimensiune ascunsă mai mare, de 7168, substanțial mai mare decât cea de 2880 a modelelor GPT-OSS. Am specializat lansatoarele de nuclee pentru a alege dimensiuni de grilă mai bune, crescând semnificativ debitul.

Tokenizare și canale

Formatul de chat al Harmony are câteva concepte importante pentru structurarea conversațiilor, a conținutului de raționament și a apelurilor de funcții. În acest format, fiecare mesaj constă dintr-un antet și conținut:

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

Antetul poartă metadate — cel mai important, rolul (sistem, dezvoltator, utilizator, asistent, unealtă), canalul și un destinatar, cum ar fi to=functions.<function-name> la invocarea unui apel de funcție.

Canalele (cum ar fi analiza, comentariile și răspunsul final) fac ca rezultatele modelului să fie mai transparente și segmentate. Deoarece formatul impune această separare, modelul poate raționa în mod transparent (și poate fi inspectat pentru depanare) fără a scurge lanțul de gândire în producție. Etichetele destinatarului (anteturile to=) spun exact timpului de execuție ce actor ar trebui să primească următorul flux de date (payload) – fie că este vorba despre o funcție, modelul în sine sau utilizatorul final.

Motorul nostru de inferență ROSE este agnostic în ceea ce privește formatul. Acesta primește un lot de jetoane de intrare și transmite în flux jetoane de ieșire. În stiva noastră de inferență, sarcina de a formata intrările într-un prompt tokenizat și de a analiza rezultatele LLM înapoi în mesaje structurate este gestionată de serviciul frontal dedicat al API-ului JSON. Am integrat Harmony adăugând un nou formator/analizor pluggable la această interfață frontală, permițând backend-ului să rămână neschimbat, în timp ce frontend-ul gestionează curat regulile de formatare a chat-ului, apelurile de funcții și streamingul. Această separare a responsabilităților menține arhitectura modulară, permițând adoptarea rapidă de noi formate și caracteristici de răspuns cu modificări minimale ale backend-ului.

Cost și performanță

Având în vedere dimensiunea relativ mică a modelelor GPT-OSS, limităm implementarea unei replici la un singur nod pentru a evita suprasolicitarea comunicării între noduri. Implementarea noastră acceptă combinații flexibile de paralelism al experților (EP), paralelism al datelor (DP) și paralelism al tensorilor (TP). Pentru a determina configurația optimă de implementare, am evaluat toate combinațiile de strategii de sharding pe dimensiuni de lot de la 1 la 128. Datorită Dezagregării Prefill-Decode, putem discuta separat despre compromisul performanță-cost pentru prefill și decodare.

Pentru estimările costurilor, presupunem o rată de piață nominală H200 de 3,00 $/oră (rețineți: acesta nu este prețul nostru real pentru GPU).

Am descoperit că setarea batch_size=1 și DP=1 generează cea mai bună performanță de prefill. Diferitele configurații TP oferă apoi diverse compromisuri între latența primului jeton și cost. Tabelele de mai jos prezintă latența prefill-ului și costul per milion de jetoane de intrare pentru diverse configurații și lungimi de intrare.

GPT-OSS 120B:

Lungime intrare

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 $

Latenta de prefill și costul per un milion de tokenuri de intrare pentru GPT-OSS 120B în funcție de configurația de paralelism și de lungimea intrării.

GPT-OSS 20B:

Lungime intrare

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 $

Latenta de prefill și costul per un milion de tokenuri de intrare pentru GPT-OSS 20B în funcție de configurația de paralelism și de lungimea intrării.

Pentru decodare, am descoperit că EP4 DP1 TP4 este cea mai bună configurație pentru majoritatea cazurilor. Cele patru grafice de mai jos ilustrează compromisul dintre viteza de decodare și costul per milion de jetoane de ieșire atât pentru modelele 120B, cât și pentru cele 20B la lungimi de secvență de 8192 și 32768.

Costul doar pentru decodare per un milion de tokenuri de ieșire versus viteza de decodare pentru GPT-OSS 120B la lungimea secvenței de 8.192, comparând configurațiile EP1, EP2, EP4 și EP8.
Costul doar pentru decodare per un milion de tokenuri de ieșire versus viteza de decodare pentru GPT-OSS 120B la lungimea secvenței de 32.768, comparând configurațiile EP1, EP2, EP4 și EP8.
Costul doar pentru decodare per un milion de tokenuri de ieșire versus viteza de decodare pentru GPT-OSS 20B la lungimea secvenței de 8.192, comparând configurațiile EP1, EP2, EP4 și EP8.
Costul doar pentru decodare per un milion de tokenuri de ieșire versus viteza de decodare pentru GPT-OSS 20B la lungimea secvenței de 32.768, comparând configurațiile EP1, EP2, EP4 și EP8.

De asemenea, am luat în considerare utilizarea modelului mai mic de 20B ca model ciornă pentru decodare speculativă (speculative decoding) pentru modelul mai mare de 120B. Cu toate acestea, deoarece numărul de parametri activați este similar (3B vs. 5B), accelerările rezultate au fost marginale.

Referințe

Prefill și decodare dezagregate

Accelerarea Sonar prin speculație​

Latență mai mică și debit mai mare cu implementarea DeepSeek pe mai multe noduri

​Comunicare eficientă și portabilă pentru amestecul de experți (Mixture-of-Experts)

​pplx-kernels

DeepGEMM

FlashInfer: Motor de atenție eficient și personalizabil pentru servirea inferenței LLM

Modele lingvistice de streaming eficiente cu Attention Sinks

Raport tehnic DeepSeek-V3​

​Formatul de răspuns OpenAI Harmony | Rețetar OpenAI​

Citare

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