HyperThreading Technológia Bevezetés
Az utóbbi évtizedben a processzorok teljesítményét az órajel növelésén kívül architekturális fejlesztésekkel is próbálták növelni a processzorgyártók, nem kevés sikerrel, gondoljunk itt például a szuperskalár feldolgozásra, a branch predictionre (programelágazások eredményét megjósoló egység), a soron kívüli végrehajtásra vagy az egyre fejlődő cachetechnológiára. A megoldások mindegyike persze jelentősen megnöveli a processzorba épített tranzisztorok számát, a magméretet, és így a fogyasztást is. A fő probléma az, hogy a teljesítmény növekedése nem áll egyenes arányban a komplexitás növekedésével. Emiatt a klasszikus processzortervezési elvektől el kell térni, és erre próbált egy megoldást adni az Intel (asztali processzoroknál) új megoldása, a Hyperthreading (2002). Tudjuk ugyanis, hogy a szerverekbe és munkaállomásokba szánt XEON család esetében a többszálú végrehajtás jóideje elérhető, egyedül az asztali CPU-knál nem volt ez engedélyezve, bár napjainkban a megnövekedett teljesítményigények (videófeldolgozás, stb.) miatt, már a kétmagos processzorok is fellelhetőek akár otthonainkban is.
Mit jelent a HyperThreading? A processzorok egyik teljesítménynövelő eszköze a szuperskalár architektúra, azaz kevésbé szépen nevezve az utasítások végrehajtásának párhuzamossága (ILP - Instruction Level Parallelism) volt - ebbe a kategóriába tartozik például az Athlon 3 db ALU egysége. Ezzel a probléma az, hogy például az egész számmal végzett műveletek sorrendje nehezen megjósolható, tehát megfelelő hatásfokkal nehezen párhuzamosítható. A mai operációs rendszerek és programok azonban már nem csak az utasítások szintjén hajtanak végre több párhuzamos műveletet. Több, egymás mellett futó programszálból áll az, amivel játszunk, szöveget szerkesztünk, filmet nézünk vagy épp netezünk. Ezen szálak párhuzamos feldolgozásához (TLP Thread Level Parallelism) szükséges erőforrás-megosztás könnyen megoldható, ha például többprocesszoros rendszereket használunk. A szálak lehetnek azonos vagy különböző alkalmazás szálai, és az operációs rendszer szintjén végrehajtandó szálak is. Jelenleg ez a technológia a processzorokban az időosztásos többszálúságként (TSM - Time-Slice Multithreading) van jelen, amikor is egy szálon dolgozik a CPU, majd fix idő múlva vagy eseményvezérelten vált egy másik szálra. Ez persze több kihasználatlan ciklust is eredményez a váltások közti "üresjáratokban", azonban elég jól hasznosíthatók a RAM késleltetési idők (amikor egy szálnak várnia kell a memóriahozzáférésre), mivel közben lehetőség nyílik más szálak végrehajtására. Természetesen ennél jobb a valódi többszálúság, azaz amikor egy végrehajtó egység megszakítás nélkül tud egy threaddel "foglalkozni". A multiprocesszoros rendszerekkel eddig is nagy teljesítményt lehetett elérni ebben a tekintetben, az elterjedésüknek az egyik korlátja az volt, hogy a chipek teljesítménye olyan gyorsan növekedett, hogy mire olcsóvá váltak volna a duál vagy többprocesszoros rendszerek, addigra mindig megjelent az új típus, amelynek sebessége már megközelítette a két vagy több CPU-ból álló eszközökét. Mostanában azonban a hűtőteljesítmény- és magméretbeli korlátok miatt újra érdemes lett gondolkozni több, párhuzamos processzor alkalmazásán. A Hyperthreading filozófiája szerint hajtsunk végre egy magon több szálat, párhuzamosan!
A HyperThreading architektúra
A Hyperthreading technológiával rendelkező processzorok úgy jelennek meg a programok számára, mint több logikai egység (logikai processzor, későbbiekben LP). Ez úgy történik, hogy a processzor két szimmetrikus állapottároló, a külső egységek számára hozzáférhető egységgel rendelkezik, melyek osztoznak a processzor A baloldalon a klasszikus felépítésű processzorok működése látható, míg a jobb oldalon a Hyperthreading működés. végrehajtó egységein. Az operációs rendszer és a feladatok, mint két-két különálló LP-t programozhatnak, majd a processzor végrehajtja a két LP feladatait, ez a programok számára valódi párhuzamos végrehajtásként fog látszani. Így az Intel szerint jóval hatékonyabban használjuk a CPU-t a megvalósításhoz szükséges tranzisztorszám és magméret mindössze 5%-os növekedése mellett, azaz maga a logikai állapotokat tároló egység (architectural state store) elenyészően kevés helyet foglal a közösen használt erőforrások mellett (cache, végrehajtó egységek, branch predictors, vezérlőlogikák, buszok). Minden LP-nak megvan a maga interrupt vezérlője, ami a programvezérlési lehetőségeket nagymértékben tágítja. (Az interrupt - azaz megszakítás vezérlő úgy működik, hogy a processzor külső eszköz által adott megszakításkérés hatására abbahagyja az aktuális programfolyamatot, elkezd egy másik, az adott eszközhöz előzetesen hozzárendelt kódot végrehajtani, majd annak végeztével visszatér az eredeti programrészlethez ott, ahol abbahagyta. Gondoljunk például az egérre, megmozdításakor a processzor abbahagyja a végrehajtást, a mutató koordinátáit frissíti, majd folytatja az eredeti programot...) A megvalósítás A megvalósítás során a célok a következők voltak: • Kis magméret-növekedés. Ezt sikerült is megvalósítani, mivel az állapotok tárolása relatíve kevés tranzisztort igényel. • Az egyik LP várakozása esetén (cache hibák, rossz jóslás, eredményre várás) a másik gond nélkül folytathassa a műveleteket. Ehhez az szükséges, hogy a belső mag összes tárolóját ne használhassa egyszerre egy szál, ami elérhető tárhasználat-limittel vagy pedig a Az Intel Pentium 4 Xeon processzor belső felépítése. tárolók megosztásával. • Egy szál esetén a sebesség ugyanolyan gyors legyen, mintha nem lenne megosztva a mag. Ilyenkor viszont egyesíteni kell az erőforrásokat, amik esetleg fel vannak osztva a két szál számára. Az utóbbi két célhoz az Intel mérnökei az ábrán látható felépítést választották, azaz bufferek, átmeneti tárolók választják el egymástól a fő pipeline egységeket. Nézzük végig a pipeline blokkjait, azaz hogyan is hajtódik végre egy utasítás a Hyperthreadinggel rendelkező processzorban!
HyperThreading működés
1. Az utasítás felhozása a Level-1 cache-ből (más néven Execution Trace Cache, a továbbiakban TC). Mindkét LP-nak van hozzáférése a TC-hez, azonban ha egyszerre kérnek adatot, akkor felváltva az egyik órajelre az egyik, második órajelre a másikhoz fordul a cache vezérlő. Ugyanakkor, ha az egyik szál valamilyen okból várakozni kényszerül, a másik a TC teljes kapacitását kihasználhatja. Ez akkor működik, ha bent van az L1-ben a megfelelő kód, ekkor egyből az UOP Queue-val jelölt részhez érünk. A következő 2 pontban foglaltak csak akkor hajtódnak végre, ha az L1 cache-ben nincs benne az UOP (mikrokód, a végrehajtó egység számára közvetlenül értelmezhető utasítás). 2. A branch prediction logic, tehát a feltételes ugrásokat megbecsülő egység részben megosztott a két LP között, részben közös, a megosztott részek maguk a "gondolkodó" egységek, míg az ún. global history array, azaz a megelőző utasításokat tartalmazó rész közös, mivel ez egy nagyméretű tároló, aminek a megosztása jelentős tranzisztorszámnövekedéssel járt volna. 3. Az utasítás-dekódernek az IA-32 utasításkészletével nincs egyszerű dolga, hiszen a CISC felépítésből adódóan változó hosszúságú utasítások fordulnak elő. Általánosságban ezt az egységet akkor használja a processzor, ha a TC hibázott, mivel a sikeres cache találat esetén megadja a mikrokódot. Viszont ha mégsem, akkor a két szál egyidejűleg is fordulhat a dekóderhez, ez esetben egy dekóderen osztozik a két LP, azonban annak tárolnia kell mindkét LP által kezdeményezett utasításdekódolás állapotait, mivel ezek szükségesek ahhoz, hogy LP-váltás esetén is helyesen működjön a dekóder egység. 4. Az UOP queue, azaz a mikrokódokat tartalmazó sor (futószalagként lehet elképzelni, mindig a végére rakjuk a következő utasítást, a végén meg leveszi a CPU) két részre osztott, mivel nem sok tranzisztort igényel, de biztosítja a fent megjelölt célok utolsó két követelményét. 5. A soronkívüli végrehajtó egység (OOOEU – Out Of Order Execution Unit), amely képes az utasításokat az eredeti sorrendjüktől eltérő módon, sebességre optimalizálva végrehajtani, limitálja az adott LP-nek adható erőforrásokat olyan módon, hogyha mindkettő használja az OOOEU-t, akkor túlzott igények esetén várakoztatja az adott LP-t, de ha csak az egyik LP használja, akkor az összes erőforrást biztosítja számára. Az OOOEU lelke, az ütemező szintén limitálja a maximálisan lefoglalható tárolók számát, amelyekből a végrehajtó egységek kapják az adatot, azaz egyik szál sem sajátíthatja ki úgy a mag erőforrásait, hogy közben a másik szál is jelen van, ellenben kizárólag egy szál esetén gond nélkül működik a teljes kapacitás kihasználása. 6. A végrehajtó egység lényegében a Hyperthreadingtől függetlenül működik, hiszen gyakorlatilag ugyanúgy végre kell hajtania a megfelelő műveleteket a megfelelő adatokkal. Az eredmények visszaírásáról (write-back) a speciális retirement logic gondoskodik, ami azért speciális, mert az architecture state-eket figyelve a megfelelő LP-be írja vissza a megfelelő eredményt.
Processzoron kívüli műveletek, események Hyperthreadinggel A memóriakezelés - mint ahogy mindezekből kiderül - nem különösebben problémás, mivel az ütemezők a végrehajtóegységnek store (tárolás) és load (betöltés) parancsokat adnak ki, amiket az gond nélkül végrehajt, a szálak pedig külön-külön "tudják", hogy melyek is az ő adataik a A processzor három állapota. memóriában. A cache már problémásabb, mivel egyrészt a közös adatokhoz való hozzáférés lassítja a feldolgozást ("lelassul a cache", gyakorlatilag felére), másrészt pont ez a közös adattárolás ad lehetőséget olyan megoldásokra, mint például az, amikor az egyik LP lekéri a másik processzor számára szükséges adatot a cache-be, eközben a másik dolgozik, majd amikor szükség lesz az adatra, akkor szintén az egyik kiolvas, míg a másik dolgozik. Egy- és többtaszkos üzemmódok: a Hyperthreading-gel rendelkező processzorok esetében három állapot létezik, ST0, ST1 és MT. Az első kettő az egytaszkos üzemmódot jelöli, attól függően, hogy melyik LP aktív, MP pedig mindkét LP aktív állapotát jelző multitaszkos működés. A váltás úgy történik, hogy az IA-32 architektúrában egy HALT utasítással leállítjuk az egyik logikai processzort, mely, ha MT állapotban van, értelemszerűen "átadja" a vezérlést a másik LP-nek. Ha bármelyik LP ST állapotban van, akkor az LP-re érkező megszakításkérés MP állapotba helyezi a CPU-t. Ennek kihasználásához természetesen szükség van az operációs rendszer erős támogatására is, mivel mit sem ér az architektúra egy olyan rendszeren, ami nem váltogatja ST és MT állapotok között a processzort, másrészt a tervezett többszálúságra is szükség van.
Érvek pro és kontra
Ami nekünk fontos: a teljesítmény, ám erről egyelőre csak az Intel mérései állnak rendelkezésünkre... ...és kontra Na igen, a kétségek. Az Intel által megadott teljesítményadatok szépek, de átgondolva, hogy a két logikai processzor ugyanazon erőforrásokat használja, valós környezetben soknak tűnnek (bár lehet, hogy Az Intel egy nem reprezentetív mérése. kénytelenek leszünk visszavonni véleményünket, ha készítünk egy tesztet). Az operációs rendszernek teljes mértékben támogatni kell az architektúrát - érdemes újra azokra a grafikonokra gondolni, amelyeken a valós többprocesszoros rendszerek Windows XP alatt először 50%, majd 25%, 10%ot profitálnak egy-egy újabb processzorból. Itt még igazi erőforrástöbblet sem lesz. Másrészt elemzők szerint a valós életben előforduló programok általában egymás után több szálon ugyanazokat a processzor-erőforrásokat használják, itt semmiképpen nem gyorsabb a Hyperthreading. Végül pedig érdemes megjegyezni, hogy bár a név nagyon hangzatos, és mint új dolog tűnt fel, de mind a Sun, mind az IBM tervezett és gyártott már ilyen processzorokat. A sebességnövelés e módszere akkor kerül terítékre, amikor több tranzisztort már nehéz elhelyezni a magon, de ha megnézzük az AMD Quantispeed technológiáját, akkor láthatjuk, hogy
azonos számú tranzisztorból nagyobb teljesítmény lehet kicsikarni a puszta erőforrások növelésével. Végső soron azt mondhatjuk, hogy az Intel jelentős lépést tett afelé, hogy a processzorai ne csak a nagy órajel miatt teljesítsenek jól, és ezt a lépést várhatóan kevés "anyagárból" hozta. Senki se várjon azonban olyan eredményeket, mint néhol az Interneten olvasható: "Intel innovation could double chip power", ami azért nagyon messze áll a valóságtól.
További információk
Az architektúra az összes P4-ben benne van, a Xeonokban már régóta engedélyezve, ám a normál P4-ekben a 3.06 GHz-s verziótól. Hivatalosan. Mert újabban egyre több helyen arról cikkeznek, hogy nem is annyira a 3.06 GHz, mint inkább a C1-es stepping a lényeg. Ha ez igaz, akkor kitűnően tuningolható C1-es 1.8A GHz-es P4-eseket is vásárolhatnak a spórolni vágyó, ám minden technológiát kihasználó hardcore felhasználók.
http://www.intel.com http://prohardver.hu/index.html Készítette: Naszádi László 2005-11-07