GPT-OSS a 0. napon

0. napi támogatás a GPT‑OSS-hez H200-on a ROSE adaptálásával FP8-cal, nyelő figyelemmel (sink attention) és MoE optimalizációkkal

SzerzőkPerplexity Engineering

A Perplexity elkötelezett amellett, hogy a legjobb AI-modelleket tegye elérhetővé a kíváncsi felhasználók számára, akik pontos és megbízható válaszokat, valamint ügynöki (agentic) műveleteket várnak. Az OpenAI nemrégiben jelentette be nyílt súlyú modelljeit (gpt-oss-20b és gpt-oss-120b). Számos vezető modellhez hasonlóan a Perplexity is az elsők között értékeli ki a gpt-oss-20b és gpt-oss-120b modelleket.

Ebben a bejegyzésben megosztjuk saját fejlesztésű inferencia-vermünk azon infrastrukturális döntéseit, amelyek lehetvé tették a 0. napi támogatást. A modellek NVIDIA H200 GPU-kon való futtatására fókuszálunk, részletezve a kernelmódosításokat, a telepítési döntéseket, valamint a sebesség és költség közötti kompromisszumokat.

GPT-OSS Hopperen

A nyílt súlyú modellek MXFP4 kvantálással érkeznek, ami segít nekik abban, hogy beleférjenek a fogyasztói kategóriájú hardverek memóriájába, vagy csúcsteljesítményt érjenek el NVIDIA Blackwellen. A kezdeti kiértékeléshez azonban a meglévő H200 Hopper klasztereken szerettük volna futtatni őket, minimális inferenciamotor-módosítással. A Hopper nem rendelkezik dedikált FP4 tenzormagokkal, amelyeket a Blackwell vezetett be. Ennek következtében úgy döntöttünk, hogy a modelleket inkább FP8 precizitással szolgáljuk ki, hogy minimalizáljuk az egyedi kernelek szükségességét, és a legjobban kihasználjuk a rendelkezésre álló hardvert.

Magas szinten a transzformátor alapú nagy nyelvi modellek (LLM-ek) szerkezetileg egyszerűek:

Bemeneti beágyazás (input embedding)

Transzformátor-rétegek sorozata. Mindegyik tartalmaz egy figyelmi (attention) blokkot, valamint egy sűrű MLP- vagy ritka MoE-blokkot.

Kimeneti logit-projekció

Egy új transzformátormodell bevezetésekor elsősorban annak megismerése érdekel bennünket, hogy milyen mértékben illeszkednek a meglévő modellekhez, hogy azonosítani tudjuk a szükséges változtatásokat. Az OpenAI készségesen megosztotta modelljeinek áttekintését előre, lehetővé téve számunkra, hogy ennek megfelelően hangoljuk be az inferenciás beállításainkat. Azt találtuk, hogy a modell valóban számos kisebb változtatást igényelt.

Figyelem (Attention): GQA figyelmi nyelőkkel (Attention Sinks)

Minden egyes figyelmi fej előre betanított nyelő (sink) paraméterrel rendelkezik, amely bekerül a Softmax számításába

YaRN pozicionális kódolás, hasonlóan a DeepSeek-V3-hoz

A QKV-projekciók torzítással (bias) rendelkeznek, hasonlóan a Qwen 2-höz

A kimeneti projekció torzítással (bias) rendelkezik

MLP: Ritka keverékszakértő (Sparse Mixture-of-Expert – MoE)

SwiGLU aktivációs függvény, amely eltér a legtöbb nyílt súlyú modelltől

Softmax a Top-K után a szakértői súlyokhoz

A szakértők torzítással (bias) rendelkeznek

Mivel 100B–200B körüli paraméterszámra számítottunk, úgy döntöttünk, hogy:

Kiterjesztjük a FlashInfer támogatását a figyelmi nyelők (attention sinks) kezelésére

Újrahasznosítjuk a DeepSeek-V3 modellcsaládhoz már megépített MoE-implementációt

Az FP8 128x128-as blokk-skálázást választjuk kvantálási sémaként, kiterjesztve a DeepGEMM kerneleket a torzítási (bias) tag támogatásával.

Saját fejlesztésű inferenciamotor

Inferencia-tevékenységeinket saját fejlesztésű inferenciamotorunk, a ROSE támogatja. A ROSE-t olyan rugalmas keretrendszerré alakítjuk ki, amely lehetővé teszi az új modellek gyors bevezetését. Emellett, ha egy modellt nagy skálán kötelezünk el kiszolgálni, olyan platformot biztosít, amellyel optimalizálható és fokozható a teljesítmény a legkorszerűbb (state-of-the-art) szintek eléréséhez.

A ROSE egy LLM-motort bocsát rendelkezésre, amely képes betölteni a modellt, és dekódolt tokeneket generálni hozzá több dekóderen keresztül, beleértve a spekulatív és az MTP dekódereket is. Maguk a modellek egyedi rétegkészletből állnak, amelyek különféle konfigurációs lehetőségeket támogatnak a kvantáláshoz és a párhuzamosításhoz. A rétegek alatt Triton- és CUDA-kerneleket egyaránt tartalmaz, amelyek hatékonyan valósítják meg és fuzionálják az egyes rétegek által végzett számításokat.

A ROSE elsősorban Pythonban íródott, és a modelldefiníciókhoz a PyTorch-ra támaszkodik. Míg a Python rugalmasságot biztosít számunkra az új modellekhez való alkalmazkodáshoz, a legtöbb teljesítményérzékeny komponenst, például a kiszolgálást és a kötegelt ütemezést (batch scheduling), átmigráljuk Rustba.

Egy új modell bevezetéséhez először definiáljuk a modellhierarchiát, és építünk hozzá egy súlykonvertert. Miután minden súlyt figyelembe vettünk, definiálunk egy előrehaladó futást (forward pass) a legegyszerűbb, TP=1-es használati esethez, és biztosítjuk, hogy az végpontok között működjön. Végül implementáljuk és teszteljük a párhuzamosítás különféle formáinak támogatását, mielőtt kiadnánk egy új konténert, és üzembe helyeznénk a modellt egy klaszteren kiértékelés céljából. Ezután a teljesítményen iterálunk, a vezérlőpultokról (dashboards) és a finomabb szemcséjű teljesítménymérésekből (benchmarks) érkező visszajelzésekre támaszkodva.

A ROSE numerikus tokeneken operál, a csevegési (chat) formátumokról az integrációs teszteken kívül keveset tud. Párhuzamosan meg kellett vizsgálnunk a környező infrastruktúra igazítását is, hogy támogassa a Harmony tokentestírót (tokenizer), és helyesen képezze le a kéréseket a bemeneti tokensorozatokra.

A GPT OSS modell esetében azt találtuk, hogy sem a dekódereinkben, sem a CUDA gráf-illesztőprogramokban (harnesses), sem a környező infrastruktúrában nem volt szükség változtatásokra, így erőfeszítéseinket a modellt támogató kernelek finomhangolására összpontosíthatjuk.

Kernelek a GPT-OSS-hez

Nyelő figyelem (Sink Attention)

A nyelő figyelem egy extra torzítási (bias) tényezőt vezet be a softmax előtt, amely a Q és K szorzatával halmozódik fel:

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

Míg egy naiv implementáció meglehetősen triviális, a hatékony figyelmi implementációk, mint például a FlashInfer, független fejeken és a KV sorozathosszon keresztül is párhuzamosítják a figyelem számítását. Ezenfelül a numerikus stabilitás érdekében a Softmax számítása online történik, miközben a maximális elemet is kivonják a numerikus stabilitás fenntartásához:

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

Az online implementáció egy futó maximumot (m) követett, amelyet -inf-re, valamint egy d skálát, amelyet 1-re inicializáltak. A maximum aktuális fej nyelőértékére történő inicializálásával biztosíthattuk, hogy az helyesen halmozódjon fel a Softmaxban. Ügyelnünk kellett arra, hogy ez a maximum csak az első darabban szerepeljen, ha a figyelem több blokkra lett felosztva a sorozathossz mentén.

Módosítottuk a FlashInfer FA2 kernel sablont – amelyet előfeltöltéshez (prefill) és dekódoláshoz egyaránt használnak –, hogy tartalmazza a nyelő paramétereit.

MoE

A különböző modellek MoE rétege közötti fő különbség általában az útválasztási (routing) séma. Mivel jelentős variálhatóságra számítottunk, a ROSE Tritonban implementálja ezt a kernelt, ami lehetővé teszi számunkra, hogy könnyen alkalmazzuk az új modellekre. A GPT-OSS esetében a súlypontozást úgy kellett módosítanunk, hogy a softmaxot csak a Top-K által kiválasztott szakértők körében végezzük el, ellentétben néhány DeepSeek-stílusú modellsel, amelyek az összes szakértőre kiterjedően számítják ki a softmaxot. Azt találtuk, hogy a pontosság szempontjából kritikus fontosságú a szakértői súlyok kiszámítása bfloat16 pontossággal.

Az MoE réteggel kapcsolatos kihívás abból adódott, hogy úgy döntöttünk, újrahasznosítjuk a meglévő DeepGEMM kerneleket, amelyekből hiányzott a torzítási (bias) tagok támogatása. Szerencsére idővel mélyen integrálódtunk velük, és olyan változtatásokat eszközöltünk, amelyekkel jobban összekapcsolhatók az egyedi all-to-all diszpécser kerneleinkkel. Hozzáadtuk a bias támogatást a DeepGEMM-hez a WGMMA akkumulátorregisztereknek a memóriából betöltött bias értékekre történő inicializálásával. Ez egy egyszeri művelet egy MN-blokk feldolgozása során, így a költsége valószínűleg elhanyagolható, az L2 cache pedig biztosítja ezen értékek hatékony elérését.

Mivel ezek a modellek nem profitálnak közvetlenül az adatpárhuzamosságból (Data Parallelism), újrahasznosítottuk a kizárólag TP-t (tensor parallelism) használó diszpécser és kombináló kerneleket. A diszpécser bemenetei minden rangon replikálódnak, így a diszpécser kiválasztja a lokálisan elérhető szakértők tokenjeit. A kombinálás (combine) végzi el a súlyozott halmozást az NVLinken keresztül.

Teljesítmény-finomhangolások

Annak ellenére, hogy célunk a modellek gyors bevezetése volt, szerettük volna biztosítani, hogy a teljesítmény továbbra is elfogadható maradjon. Miután ellenőriztük a helyességet az OpenAI által biztosított referenciainplementációval szemben, profiloztuk az implementációnkat az alapértelmezett PyTorch profilerrel, figyelve a blokk- és szálallokációkra a kernelekben. Az újrahasznosított funkcionalitást olyan modellekhez építették ki, amelyek nagyobb, 7168-as rejtett dimenzióval rendelkeztek, ami jelentősen nagyobb, mint a GPT-OSS modellek 2880-asa. A kernelindítókat (kernel launchers) úgy specializáltuk, hogy jobb rácsdimenziókat válasszanak ki, ami jelentősen növelte az áteresztőképességet.

Tokenizálás és csatornák

A Harmony csevegési (chat) formátuma számos fontos koncepcióval rendelkezik a beszélgetések, a következtetési tartalom és a függvényhívások strukturálásához. Ebben a formátumban minden üzenet egy fejlécből és tartalomból áll:

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

A fejléc metaadatokat hordoz – legfontosabban a szerepkört (rendszer, fejlesztő, felhasználó, asszisztens, eszköz), a csatornát, valamint egy címzettet, például to=functions.<function-name> formában egy függvényhívás indításakor.

A csatornák (például elemzés, kommentár és végső válasz) átláthatóbbá és szegmentáltabbá teszik a modell kimeneteit. Mivel a formátum kikényszeríti ezt a szétválasztást, a modell átlátható módon tud következtetni (és hibakeresés céljából ellenőrizhető) anélkül, hogy a gondolatmenet (chain-of-thought) kiszivárogna a termelési környezetbe. A címzettcímkék (to= fejlécek) pontosan megmondják a futtatókörnyezetnek (runtime), hogy melyik szereplőnek kell megkapnia a következő adatkészletet – legyen az egy függvény, maga a modell vagy a végfelhasználó.

Inferenciamotorunk, a ROSE formátumfüggetlen. Bemeneti tokenek kötegét (batch) fogadja, és kimeneti tokeneket streamel vissza. Az inferencia-vermünkben a bemenetek tokenizált prompttá formázásának és az LLM eredmények strukturált üzenetekké történő elemzésének a feladatát a dedikált JSON API előtér-szolgáltatás (frontend service) látja el. A Harmony-t úgy integráltuk, hogy egy új, cserélhető formázót/elemzőt adtunk ehhez az előtérhez, lehetővé téve, hogy a háttérrendszer (backend) változatlan maradjon, miközben az előtér tisztán kezeli a csevegési formátum szabályait, a függvényhívásokat és a streamelést. Ez az aggályok szétválasztása (separation of concerns) modulárisan tartja az architektúrát, lehetővé téve az új formátumok és válaszfunkciók gyors bevezetését minimális háttérrendszer-módosítással.

Költség és teljesítmény

Tekintettel a GPT-OSS modellek viszonylag kis méretére, a replika üzembe helyezését egyetlen csomópontra korlátozzuk, hogy elkerüljük a csomópontok közötti kommunikációs többletterhelést. Implementációnk támogatja a szakértői párhuzamosság (EP), az adatpárhuzamosság (DP) és a tenzorpárhuzamosság (TP) rugalmas kombinációit. Az optimális üzembe helyezési beállítás meghatározásához teljesítménymérést végeztünk a shardelési stratégiák minden kombinációján 1 és 128 közötti kötegméretekkel (batch sizes). A Prefill-Decode Disaggregation (szétválasztott előfeltöltés és dekódolás) révén képesek vagyunk külön-külön tárgyalni a teljesítmény és a költség közötti kompromisszumot az előfeltöltés és a dekódolás tekintetében.

A költségbecslésekhez 3,00 USD/óra névleges H200-as piaci árat feltételezünk (megjegyzés: ez nem a mi tényleges GPU-árunk).

Azt tapasztaltuk, hogy a batch_size=1 és DP=1 beállítás biztosítja a legjobb előfeltöltési teljesítményt. A különböző TP-konfigurációk ezután eltérő kompromisszumokat nyújtanak az első tokenre vonatkozó késleltetés (latency) és a költség között. Az alábbi táblázatok a különböző konfigurációkhoz és bemeneti hosszakhoz tartozó előfeltöltési késleltetést és az egymillió bemeneti tokenre eső költséget mutatják be.

GPT-OSS 120B:

Bemeneti hossz

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 előtöltési késleltetése és milliónkénti bemeneti tokenköltsége párhuzamossági konfiguráció és bemeneti hossz szerint.

GPT-OSS 20B:

Bemeneti hossz

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 előtöltési késleltetése és milliónkénti bemeneti tokenköltsége párhuzamossági konfiguráció és bemeneti hossz szerint.

A dekódolás tekintetében azt találtuk, hogy a legtöbb esetben az EP4 DP1 TP4 a legjobb konfiguráció. Az alábbi négy ábra szemlélteti a dekódolási sebesség és az egymillió kimeneti tokenre eső költség közötti kompromisszumot mind a 120B, mind a 20B modell esetében 8192-es és 32768-as sorozathossznál.

Csak dekódolásos milliónkénti kimeneti tokenköltség a dekódolási sebességhez viszonyítva GPT-OSS 120B esetén 8 192-es szekvenciahosszon, az EP1, EP2, EP4 és EP8 konfigurációk összehasonlításával.
Csak dekódolásos milliónkénti kimeneti tokenköltség a dekódolási sebességhez viszonyítva GPT-OSS 120B esetén 32 768-os szekvenciahosszon, az EP1, EP2, EP4 és EP8 konfigurációk összehasonlításával.
Csak dekódolásos milliónkénti kimeneti tokenköltség a dekódolási sebességhez viszonyítva GPT-OSS 20B esetén 8 192-es szekvenciahosszon, az EP1, EP2, EP4 és EP8 konfigurációk összehasonlításával.
Csak dekódolásos milliónkénti kimeneti tokenköltség a dekódolási sebességhez viszonyítva GPT-OSS 20B esetén 32 768-os szekvenciahosszon, az EP1, EP2, EP4 és EP8 konfigurációk összehasonlításával.

Megfontoltuk azt is, hogy a kisebb 20B modellt spekulatív dekódolási vázlatmodellként (draft model) használjuk a nagyobb 120B modellhez. Mivel azonban az aktivált paraméterek száma hasonló (3B vs. 5B), az eredményül kapott sebességnövekedés csekély volt.

Hivatkozások

Szétválasztott előfeltöltés és dekódolás (Disaggregated Prefill and Decode)

A Sonar felgyorsítása spekuláció révén​

Alacsonyabb késleltetés és magasabb áteresztőképesség többcsomópontos DeepSeek üzembe helyezéssel

​Hatékony és hordozható keverékszakértő (Mixture-of-Experts) kommunikáció

​pplx-kernels

DeepGEMM

FlashInfer: Hatékony és testreszabható figyelmi motor LLM inferencia kiszolgálásához

Hatékony streamelő nyelvi modellek figyelmi nyelőkkel (Attention Sinks)

DeepSeek-V3 technikai jelentés​

​OpenAI Harmony válaszformátum | OpenAI Szakácskönyv (Cookbook)​

Idézet

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