Hirdetés

AMD Trinity megateszt: APU újratöltve

A Piledriver v1 fejlesztései

Maguk az x86-os Piledriver-modulok apróbb csiszolásokon estek át a Bulldozer-modulokhoz képest, de az alapkoncepció nem változott. A Trinity-ben helyet kapott verzió újításai a következők:

  • az integer magokban és a Flex FP-ben található ütemezők hatékonyságát a végrehajtó egységek kihasználásának növelése érdekében javították;
  • az integer magok Load/Store egységében az olvasási sor méretét 40-ről 44-re növelték, azaz 10%-kal több, függőben levő memóriaolvasási műveletet kezelhet egyszerre 1-1 mag;
  • az L1 adat TLB és az utasítás Translation Lookaside Buffer mérete egyaránt 32-ről 64 bejegyzésre nőtt, így kevesebb időigényes virtuális->fizikai memóriacím-fordítás szükséges a programok futása közben;
  • az elágazásbecslés hatékonyabb lett, kevesebb téves elágazásjóslatot eredményezve: a hibrid branch prediktor két egységből áll, amelyek kétféle szempont szerint elemzik azt, hogy a következő órajelben mely utasítások kerüljenek beolvasásra az utasításcache-ből. Arra az esetre, ha a két jóslat ellentmond egymásnak, egy kis logika nyomon követi, hogy melyik jósol egy-egy adott szituációban korrektebben, és annak eredményét fogja használni legközelebb;
  • a lebegőpontos és az egész számos osztó utasítások, a felhasználói és kernel mód között váltó instrukciók, valamint az atomi (LOCK) műveletek végrehajtása gyorsabb lett;
  • a Flex FP különböző alegységekből áll, az ezek közötti adattovábbítás további 1 órajellel növeli a művelet végrehajtási idejét; a Piledriver-ben a leggyakoribb ilyen eset, a kiszámított eredmények memóriába írása (amely az adott lebegőpontos számítási alegységből a STORE alegységbe történő továbbítást jelenti) már nem igényli ezt a +1 órajelet;
  • négy új utasításkészlet költözik be a CPU-ba: az Intel Haswellben alkalmazandó 3 paraméteres FMA-utasítások (a Bulldozer a rugalmasabb 4 paraméteres utasításokat kezeli); a 32 bites egyszeres és a 16 bites félpontosságú lebegőpontos számok közötti konverziót megvalósító F16C készlet két utasítása; továbbá a BMI- és TBM-készletek, amelyek egyrészt lehetővé teszik egy-egy 16, 32 vagy 64 bites egész érték bizonyos bitjeinek feltételtől függő csoportos 1-re állítását és/vagy törlését – kiváltva ezzel 2-3 korábbi külön utasítást –, másrészt implementálják az ANDNOT műveletet és a BEXTR utasítás révén az ilyen számok összefüggő bitmezőinek kiemelését.


[+]

Az adatokat spekulatívan előbetöltő hardveres elemek (prefetch-erek) működése is megváltozott, ennek megértéséhez merüljünk bele a cache-ek működésébe! Az a kifejezés, hogy "16 kB 4-utas csoportasszociatív cache 64 byte vonalmérettel, LRU cserélési algoritmussal" (angolul: 4-way set-associative cache, 64 byte line size, LRU replacement policy) a következőket jelenti:

  • Ez a cache 64 byte-os elemekből álló tömb, jelen esetben 256 ilyen elemből áll. Ha a CPU-nak szüksége van a memóriából akár egyetlen bájtra is, beolvassa a teljes 64 bájtos memóriarészt (64 byte vonalméret, cache line size), amelyben az adott byte van, és elhelyezi a 256 elem egyikébe. Ez a beolvasás akkor is megtörténik, ha csak ír erre a címre a processzor, kivéve, ha speciális tároló utasításokkal (non-temporal store, azaz nem-átmeneti tárolás) kifejezetten tiltja ezt.
  • Nem akármelyikbe teheti be, hanem csak 4 elem valamelyikébe (4-utas, 4-way), azaz 4 db 64 byte-os elem alkot egy csoportot (set), azaz ebben a cache-ben 64 ilyen csoport van. Egy-egy memóriacím csak egy-egy meghatározott csoport 4 elemében jelenhet meg, azaz ha a CPU-nak szüksége van egy adatra, akkor csak 4 elemet kell megnéznie a cache-ben, hogy ott van-e, nem kell mind a 256-ot átnéznie, így gyorsabb is a cache (kisebb a késleltetése) és a cache-vezérlő logika is sokkal egyszerűbb.
  • Hátránya is van persze ennek, hiszen egy-egy csoport a fizikai memória eléggé nagy – de nem folyamatos – szeletét képezi le, azaz gyakran felülíródnak bennük az adatok; azt, hogy a csoport 4 eleme közül adott pillanatban melyik íródjon felül, azt a Least-Recently-Used (LRU) algoritmus határozza meg. A cache-vezérlő mindegyik csoportra külön-külön karbantart egy-egy sorrendet, hogy a 4-4 db 64 bájtos elem közül melyikre történt legrégebben hivatkozás, melyikre legutóbb; a legrégebben használt adatot írja felül ilyenkor.


[+]

Adatot a memóriából vagy egy lentebbi cache-szintről azonban nem csak a CPU-magok igényelhetnek, hanem az előbetöltők önállóan is olvasnak be adatokat. Ezek olyan részegységek a cache-ek mellett, amelyek autonóm módon figyelemmel követik, hogy a végrehajtó egységek milyen memóriacímekről olvasnak be adatokat, és ezekben szabályosságot találva spekulatív módon betöltik a jövőben valószínűleg igényelt 64 bájtos szeleteket:

  • ha sikeres a jóslat, akkor a memóriaolvasásra való várakozást elrejtette, ezzel növekszik a végrehajtási sebesség;
  • ha sikertelen, akkor viszont egy értékes adatot írt felül az adott csoportban, amit ráadásul sok esetben vissza is kell olvasni.

Az eddigi prefetch-erek hatására a spekulatívan beolvasott adat került az adott csoport LRU-sora élére, amivel az 'éppen most' használt elem lett a csoportban, tehát egy valóban szükséges adat be- vagy visszaolvasása esetén nem ezt a téves jóslatot, hanem egy másik, ugyancsak értékes elemet írt felül a cache-vezérlő a csoportban, amit aztán megint csak vissza kell olvasni... És így tovább; ezáltal egy kis dominó-effektus indult el az adott 4 x 64 bájtos csoportban. A Piledriver prefetchere azonban a spekulatívan beolvasott adatot azonnal "legrégebben" használtnak jelöli meg:

  • ha valóban szüksége van a CPU-magnak az adott adatra, azt azonnal fel is fogja használni;
  • ha nincs szükség rá, akkor ezt fogja legközelebb hasznos adat felülírni, a többi értékes adatot nem éri bántódás.

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

Azóta történt

Előzmények

Hirdetés