Hirdetés

Új hozzászólás Aktív témák

  • P.H.

    senior tag

    A memória-alrendszer

    - Load/Store Unit

    Miután valamely AGU kiszámította a szükséges memóriacímet, K8 esetében a olvasási ás írási kérelmek az LSU (Load/Store Unit) egységbe kerülnek, ez két puffert tartalmaz, az LS1 és LS2 sorokat. Először mindkét típusú kérés a 12 elemű LS1-be kerül, amely órajelenként kettőt továbbít ezek közül az L1 D-cache felé, szigorúan programsorrendben. Cache-tévesztés esetén a műveletek átkerülnek a 32 elemű LS2 sorba, innen férhetnek hozzá az L2 cache-hez, illetve szükség esetén a rendszermemóriához.

    K10 esetén ez némileg módosult: az LS1 a továbbiakban kizárólag az olvasási kérelmeket fogadja, az írási műveletek azonnal az LS2-be kerülnek. Az LS1-beli betöltések out-of-order módon futnak le, közben figyelemmel kísérve az LS2-beli tárolási címeket. Ahogy korábban leírtuk, a K10 a 128 bites írásokat 2 db 64 bites egységben kezeli, tehát azok két elemet foglalnak az LS2 egységben.

    - L1 cache-ek

    A K8 és K10 egyaránt két elsőszintű gyorsítótárat tartalmaz: 64 KB-ot az adatoknak és külön 64 KB-ot az utasításoknak. Mindkettő 2-utas csoportasszociatív (2-way set-associative). A kis asszociativitás számos alkalommal okoz konfliktusokat az azonos csoporthoz tartozó vonalakon, ez gyakori cache-tévesztéshez vezet, hátrányosan befolyásolva a teljesítményt (a kis asszociativitást általában nagyobb L1 cache-mérettel kompenzálják, ahogyan az AMD is teszi). A L1 D-cache legfőbb előnye a két port: órajelenként 2 db olvasási és/vagy írási műveletet képes teljesíteni.

    Sajnos a K10 esetében is azonos L1-méret és -asszociativitás maradt. Az egyetlen szembetűnő módosítás az adatút-szélességek növekedése. Amint az előző fejezetben említettük, 2 db 128 bites olvasást tud órajelenként megvalósítani, mely jótékony hatással van a memória-argumentumokkal dolgozó SSEx-feldolgozásra.

    - L2 cache

    K8 és K10 (dual- és quad-core) esetén egyaránt minden mag saját L2 cache-sel rendelkezik, melyek K10 esetében is azonos paraméterekkel rendelkeznek: 512 KB/mag és 16-utas asszociativitás. Ezen külön L2-táraknak előnyeik és hátrányaik is van a Core 2 egyesített L2-jével összehasonlítva: többek között előnye, hogy több mag erős terhelése esetén is mentes a konfliktusoktól és hozzáférési versenyhelyzetektől; hátránya pl., hogy ha csak egy mag van erősen leterhelve, az kevesebb gyorsítótárral gazdálkodhat.

    Az L2 cache exkluzív szervezésű: nem található meg ugyanaz az adat az L1-ben és az L2-ben egyidőben. A két szint 2 db egyirányú buszon cserél adatot, az egyiken fogad, a másikon küld. K8 esetén mindkét adatút 64 bites, így 8 órajel szükséges egy 64 byte-os egység cseréjéhez (ennél kisebb adatméret nem értelmezhető ezen a szinten). Ennek következménye, hogy az L2->mag átvitel aránylag magas késleltetéssel rendelkezik, főleg több vonal párhuzamos igénylése esetén.

    Bár még nem tisztázott teljesen, valószínűleg ez a két busz K10 esetén 128 bitre szélesedik, jelentősen csökkentve az említett késleltetést.

    - L3 cache

    A meglehetősen kisméretű L2 cache-méretek ellensúlyozására a K10 egységesített 2 MB L3 gyorsítótárat alkalmaz, 32-utas asszociativitással. Ez adaptív és exkluzív szervezésű: egyaránt tartalmazza azokat az adatokat, melyek a bármely mag L2-cacheből kerülnek ki (helyhiány és cserélődés miatt), és a több mag által használt adatvonalakat. Amikor a mag L3-olvasási műveletet kezdeményez, az egy speciális vizsgálatot is maga után von: ha az adatot csak egy mag használja, az kikerül az L3-ból, helyet adva az adott mag L2-cache-éből kikerülő adatnak. Ha azonban az adatot más mag is használta, az benn marad az L3-tárban továbbra, és egy régebben használt L3-vonal kerül kiírásra a rendszermemóriába, helyet adva a bekerülő L2-vonalnak.

    Látható, hogy az L3-cache jelentős hatással van a magok közti kommunikáció sebességére. Amint korábban kiderült, a korábbi Athlon64 processzorok magjai a memóriabuszon keresztül cserélnek adatokat, nagyban lassítva a közösen módosított adatok cseréjét (Shared/Modified, MOESI protokoll szerint), K10 ezt az L3 cache-en keresztül oldja meg: ha az egyik mag a kérdéses adathoz fordul, a másik mag elhelyezi a módosított adatot az L3 cache-ben, így az előbbi sokkal kisebb késleltetéssel férhet hozzá ahhoz. Amint lesz lehetőségünk, ezt azonnal leteszteljük.

    Az L3-cache késleltetése természetesen nagyobb lesz, mint az L2-táraké, mindenesetre az AMD dokumentációiból az derül ki, hogy sebessége függ majd a terheléstől is: ha kisebb a terhelés a CPU-n, a késleltetése csökken, nagyobb terhelés esetén pedig a sávszélessége nő. Hogy hogyan is működik ez a valóságban, alkalomadtán ezt is megvizsgáljuk.

    - Translation Lookaside Buffer-ek

    A cache-ek mellett még egy típusú gyorsító puffert találunk a processzorokban, a TLB-ket, ezek a virtuális címekhez tartozó, laptáblák alapján számolt fizikai címeket tárolják. A méretük határozza meg, hány lap hozzáférhető költséges table-walk eljárás nélkül (mely több 10 vagy 100 órajelet vehet igénybe). Ez főleg azoknál az alkalmazásoknál fontos, melyek véletlenszerű memóriahozzáféréseket használnak, sűrűn fordulva más-más lapokhoz. A K10 nagyobb TLB-méretekkel rendelkezik, ahogy a táblázatokban látható: főként a 2 MB-os lapokhoz tartoző bejegyzések száma nőtt, továbbá megjelent az 1 GB-os lapméret támogatása, melynek hatása elsősorban a nagy méretű adatokkal dolgozó szerveralkalmazások esetében mutatkozik meg. Megfelelő OS-támogatás esetén a 2 MB és 1 GB lapméreteket kihasználó programok látványos gyorsulást mutathatnak.

    - Memóriavezérlő

    Ha a kért adat a cache-ek egyikében sem található meg, a memóriahozzáférési kérést az integrált memóriavezérlő kapja meg. Integrált volta csökkenti a memóriakésleltetést, viszont a CPU-t bizonyos memóriatípusokhoz köti, növeli a lapka méretét és csökkentheti a kihozatalt. Az integrált vezérlő a K8 egyik nagy újítása volt, viszont számos esetben nem volt elég hatékony. A K10 esetében viszont jelentős fejlesztésen esett át.

    Elsősorban, az adatátvitel az eddigi egyetlen 128 bites vonal mellett további 2 db, független 64 bites vonalon történik, így egyszerre két vagy több mag hatékonyabban dolgozhat a rendszermemóriával.

    Másodsorban az ütemező és átrendező algoritmusokat átgyúrták: a vezérlő összegyűjti a különböző az olvasási és írási hozzáféréseket, így a memóriabusz jobban kihasználható. Továbbá a kiírandó adatok egy, egyelőre ismeretlen méretű pufferben tárolódnak átmenetileg (valószínűleg 16-30 elemű, 64 byte elemméretű pufferre számíthatunk). Ezzel a csoportosítással az egymást követő váltakozó írási és olvasási műveletek esetén elkerülhető a memóriabusz folyamatos átkapcsolása, számottevően növelve annak teljesítményét.

    Harmadsorban, a memóriavezérlő elemzi a beérkező kérések sorozatait és immár önállóan is képes előbetöltésre (prefetch).

    - Előbetöltés

    A prefetch egy kényes kérdés K8 esetében. A kis késleltetésű integrált memóriavezérlő által az AMD sokáig kiemelkedő memóriaeredményeket tudott felmutatni, viszont DDR2 memóriák bevezetése után nem tudott lépést tartani a Core 2-vel és annak erőteljes előbetöltési módszereivel. A K8 két előbetöltési mechanizmust alkalmaz, egyet-egyet az utasításoknak és az adatoknak, utóbbi egyszerűen az L2-be tölti be az adatokat. A K10 prefetch-módszereit az alábbiak szerint módosították.

    Először is közvetlenül az L1 D-cache-be tölti be az adatokat, így nem kell számolni az L2 késleltetésével. Bár ez, főképp az alacsony asszociativitás miatt, növeli az L1-beli cserélődések számát (felesleges adatok jelenhetnek meg benne), az AMD állítása szerint általánosságban pozitív hatással bír.

    Másodszor az alkalmazott adaptív prefetch-módszer immár dinamikusan határozza meg az előbetöltési távolságot, ebben a programban elhelyezett előbetöltő utasításokat is figyelembe tudja venni, ezáltal csökkenti a feleslegesen betöltött adatok mennyiségét. Sokkal rugalmasabbá vált ezáltal, korábban a K8 csak a valójában hozzáférttel szomszédos cache-vonalat volt képes előbetölteni.

    Harmadszor maga az integrált memóriavezérlő is kapott egy saját prefetch-képességet: elemzi a magokból érkező memóriahozzáféréseket, az eredmények alapján az írási puffereibe előbetölt adatokat, hozzájárulva a memóriabusz jobb kihasználásához. Mivel a saját puffereibe dolgozik, nincs negatív hatása a cache-ek tartalmára, viszont érezhetően csökkenti az adathozzáférések késleltetését.

    Összességében, bár a K10 memória-alrendszerét átdolgozták, azt kell mondanunk, még mindig nem érte utol az Intel processzorokat ezen a téren. Többek között nem képes a pillanatnyilag ismeretlen címre menő korábbi írások elé rendezni a későbbi olvasásokat, alacsonyabb az L1 asszociativitása, keskenyebb a bus (és az sávszélesség) az L1 és L2 között, kisebb az L2 cache. És nem utolsósorban egyszerűbbek az előbetöltési algoritmusok, melyek a Core 2 esetében még mindig hatékonyabbak (például a K10-nek nincs L2->L1 előbetöltési képessége az L2 késleltetésének elrejtésére). Ezek hatása alkalmazásonként eltérő, de az esetek nagy többségében az Intel processzorok hatékonyabbnak tekinthetők ebből a szempontból.

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

Új hozzászólás Aktív témák