Hirdetés

AMD Bulldozer – kislapát vagy munkagép?

A Bulldozer motorterében

Abban a tekintetben, hogy a processzoron belül mi az az elemi feldolgozó egység, amely a támogatott utasításkészletek összes utasítását fel tudja dolgozni, a korábban megszokott "mag" kifejezést a Bulldozerben a "modul" vette át, tehát a Zambezi egy négymodulos CPU, amely modulonként 2 programszál és órajelenként 4 utasítás végrehajtására képes. A modulok belül több alegységre bonthatóak, amelyek közül néhányból teljes egészében kettő van, ezek dedikáltan egy-egy szálhoz tartoznak, míg mások mindkét utasításfolyamot kezelik felváltva vagy párhuzamosan.


(A korábbi architektúrák ábrája itt található)

Az utasítások végrehajtása a következő utasítások kiválasztásával, azok előfeldolgozásával és dekódolásával kezdődik, ezeket az összefoglaló néven front-endnek hívott megosztott részegységek végzik, órajelenként váltva a két szál között. Mindkét szál utasításait egyetlen 64 kB méretű, kétutas csoportasszociatív L1 I-cache (utasítás cache) tárolja, amelyből az elágazásbecslés által megadott címtől az előfeldolgozó órajelenként 32 bájtot olvashat ki és küldhet dekódolásra; egyik órajelben az egyik szálét, a következő órajelben a másik szálét.

A dekóder órajelenként 4 utasítás fordítását végzi el és küldi a végrehajtó egységek felé rögzített, Dispatch Groupnak nevezett makro-op négyesekben. A dekóder képes az egymást követő összehasonlító és ugró utasítások egyesítésére, így bizonyos esetekben órajelenként 4 helyett 5 x86/x64-utasítást továbbít egy-egy Dispatch Groupban. Amennyiben egy modulon csak egy programszál fut, az megkapja a front-end teljes kapacitását, azaz órajelenként ezen szál 4-5 lefordított utasítása lép be a végrehajtó egységek – összefoglalva back-endnek nevezett – területére.

Mindkét programszálhoz dedikált egész számos műveletvégző egység tartozik, amelyeket az AMD magoknak nevez, így a Zambeziben 8 mag van. Ezek egyrészt az adott szálhoz tartozó összes belső műveletet és azok eredeti programsorrendjét tárolják a Re-Order Bufferben (ROB), másrészt végrehajtják az egész számokon dolgozó SISD utasításokat és kezelik a memória-alrendszert. Egy-egy mag 4 végrehajtó egységet tartalmaz, amelyek közül kettő, EX0 és EX1, a számítási műveleteket végzi: az osztások és a K10-zel bemutatkozó LZCNT/POPCNT bitszámlálások az EX0-ba kerülnek, a szorzások és az ugrások az EX1-be, a többi műveletet pedig mindkét végrehajtó képes elvégezni 1 órajel alatt. A másik kettő, az AG0 és az AG1, a memóriaolvasások és -írások címeit számolja ki, és azokat a Load-Store Unit felé továbbítja, amely két részből áll: az olvasási sor 40 elemű, az írási sor 24 elemű, és a műveletek átrendezhetőek egymás között.

Modulonként egyetlen FPU-t találunk, amely megosztott a két programszál között: feladata az összes lebegőpontos számítás, valamint a egész számos SIMD funkciók ellátása. Alapjaiban változott meg felépítése a korábbiakhoz képest: 4 db 128 bites végrehajtót tartalmaz, amelyek közül a 2 FMAC jellemzően lebegőpontos számokon dolgozik, kettő pedig egész számokon; továbbá majdnem mindegyikük egy-egy speciális feladat ellátásáért is felel:

  • mindkét FMAC képes a lebegőpontos összeadás/kivonás, összehasonlítás, szorzás, osztás/reciprokképzés és gyökvonás elvégzésére, illetve az új utasításkészletként hozzáadott FMA kiszámítására (FP egység);
  • az egyik FMAC kapja továbbá az egész számok SIMD szorzásait és a szintén d:=a*b+c formájú műveleteit (IMAC egység), valamint az integer<->lebegőpontos és lebegőpontos SP<->DP konverziókat (CVT egység);
  • a másik FMAC-hoz kerülnek a SIMD vektorok belső adatátrendezései (XBR egység a shuffle és blend típusú utasításokhoz);
  • a két SIMD integer pipeline a szorzáson kívüli műveleteket végzi el egész számokon;
  • az egyik SIMD integer egység végzi a tárolási műveleteket, illetve az FPU-ból az integer magok felé irányuló adattovábbításokat (STORE egység);
  • a registerből registerbe történő adatmásolások nem igényelnek végrehajtó egységet, ezeket a register fájl önállóan kezeli, órajelenként legfeljebb 4x128 bitet (Move Elimination).

Az elődök, azaz a K10 és K12 processzorok FPU-ja csak 3 db 128 bites végrehajtóból áll, amelyek között teljesen másképp kerülnek felosztásra az elvégzendő számítások:

  • az FSTORE feladata az integer<->lebegőpontos és a lebegőpontos SP<->DP konverziók, valamint a tárolási műveletek végrehajtása;
  • az FMUL felel a lebegőpontos szorzásokért, osztásokért/reciprokképzésekért és gyökvonásokért;
  • az FADD kapja a lebegőpontos összeadásokat, kivonásokat, összehasonlításokat és az FPU->integer adattovábbításokat;
  • ugyancsak az FADD és az FMUL hajtja végre integer SIMD műveleteket és a vektorok átrendezésit (shuffle és pack/unpack utasítások), kivéve az integer SIMD szorzásokat, amelyek az FMUL-ra korlátozódnak;
  • a registerből registerbe történő adatmásolások időigénye 2 órajel, ezeket az FADD, az FMUL és a FSTORE egyaránt képes elvégezni.

Látható, hogy a Bulldozernél a lebegőpontos számítások több erőforrást kaptak, és csak minimális mértékben keverednek az egész számok műveleteivel. Mivel 2-2 csaknem azonos képességű lebegőpontos és egész számos végrehajtó van, ezért azok két szál futtatásakor az igényeknek megfelelően rugalmasan, de legrosszabb esetben is fele-fele arányban eloszthatók köztük.

A 128 bites lebegőpontos műveletek végrehajtási ideje megnőtt a korábbi generációkéhoz képest 4-ről 5 órajelre, viszont az FMA-műveletek is ennyit igényelnek. Továbbá a felsorolt, speciális feladatokat ellátó részegységek közötti adattovábbítás további 1 órajel késleltetést jelent. A 256 bites AVX műveletek helyzete speciális, mivel a végrehajtók csak 128 bitesek. Ezek az utasítások 2 db 128 bites belső műveletre fordulnak le, ezt a két felet külön-külön hajtja végre az FPU: amennyiben lehetőség van rá, akkor a kettőt egyszerre a 2 FMAC-ban, amennyiben erre nincs lehetőség (pl. az egyik FMAC foglalt), akkor 2 egymást követő órajelben indítja el a két műveletet. Ez egyben azt is jelenti, hogy órajelenként maximum 1 db 256 bites lebegőpontos utasítás végrehajtására képes.

A cache felépítése teljesen megváltozott a korábbiakhoz képest: mindegyik cache-szinten történt változás, ahogy közeledünk a végrehajtó egységek felé, úgy egyre nagyobb. Külön L1 adatcachet kapott a két integer mag, méretük 16-16 kB-ra csökkent; ezt némileg ellensúlyozza, hogy négyutasra nőtt az asszociativitásuk. Ezek write-through irányelvet követnek, azaz minden egyes adatmódosítás azonnal megjelenik az eggyel magasabb szintű gyorsítótárban is, ennek következtében az L1 adatcache írási sebessége lecsökken az L2 nagyságrendjébe. Azonban azért, hogy ez a sebességveszteség minél észrevehetetlenebb legyen, az L1 és az L2 cache-ek közé beékeltek egy Write Coalescing Cache-nek (WCC) nevezett 4 kB-os gyorstárat, amely az azonos 64 bájtos cache-vonalra érkező írásokat gyűjti össze és egyben továbbítja azokat az L2-höz. Az L1 adatcache-ek késleltetése 3 órajelről 4 órajelre nőtt, és órajelenként 2 db 128 bites olvasást vagy 1 db 128 bites olvasást és 1 db 128 bites írást tud kezelni.

Az L2 cache mérete 2 MB-ra nőtt, 16-utas asszocaivitású és a modul két magja közösen használja. Méretével együtt a késleltetése is nőtt, 21 órajelre. Ez utóbbihoz valamelyest hasonló megoldást már láthattunk a Core Duo, valamint Core 2 processzorok esetében, ahol két mag osztozott egyetlen nagyobb 2, 4 vagy éppen 6 MB-os L2 cache-en.

Az immár 64-utas asszociativitású L3 cache mérete 8 MB, és csak az L2-kből kikerülő, a végrehajtás során korábbiakban módosított értékeket tárolja, tehát a csak olvasott értékek nem kerülnek bele. Ahogy a fenti képen is látható, ez a gyorsítótár négy különálló, egyenként 2 MB-os alcache szeletből áll össze. Egy úgynevezett column-select aliasing eljárással próbálták növelni a szükséges terület felhasználásának hatékonyságát.

A cikk még nem ért véget, kérlek, lapozz!

Azóta történt

Előzmények

Hirdetés