Memóriakezelés
Processzor megnevezése | AMD K7 | AMD K8 | AMD K10 | Intel Merom | Intel Penryn |
Támogatott memória | DDR-400 | DDR2-800 | DDR2-1066 DDR3 (később) | DDR2-800 (hivatalosan, de egyébként 1066 is) DDR3-1333 | |
Maximálisan elérhető memória-sávszélesség | 6,4 GB/s | 12,8 GB/s | 17 GB/s (DDR2) DDR3 (később) | 12,8 GB/s (DDR2) 21 GB/s (DDR3) | |
Rendszerbusz órajele | 200 MHz FSB Alpha EV6 (3,2 GB/s) | 1000 MHz HyperTransport (8 GB/s) | 1000–2600 MHz HyperTransport (8–20,8 GB/s) | 333–400 MHz FSB AGTL+ (10,6–12,8 GB/s) | |
Hardveres prefetch (CPU-magonként) | Unit-stride prefetcher (L2) | Unit-stride prefetcher (L2) | 2 db Memory prefetcher (RAM); Unit-stride prefetcher (L1); Adaptive prefetcher (L1) | Utasításbehívás és predekód prefetch; Data Cache Unit prefetcher (L1); IP-based prefetcher (L1); 2 db Data Prefetch Logic (L2, azaz megosztott) |
Tesztünk második fejezetében a rendszermemória elérésével foglalkozunk. A memória elérésének tesztelésére ezúttal azért fordítottunk külön figyelmet, mert a K10 megjelenése új ajtókat nyitogatott ezen a téren is. Az új architektúrában még mindig integrált memóriavezérlő dolgozik, de az AMD félretette a több éve mindkét gyártó által legszívesebben használt kétcsatornás működést, és dupla egycsatornás kiépítést fejlesztett ki. Erre miért volt szükség? A hagyományos kétcsatornás memóriaelérésnek az az előnye, hogy egyszerre nagyobb adatmennyiséget lehet rajta átmozgatni, de órajelenként csak egy műveletre (olvasás vagy írás) van lehetőségünk, ami nem optimális az egyre terjedő multitaszkos, egyre több szálon dolgozó környezetekben, amikor esetleg több operációs rendszer és azokon belül több program is egyszerre szeretné elérni a memóriát írásra és olvasásra egyaránt – gondoljunk a virtualizáció térhódítására. Az AMD megoldása kézenfekvőnek tűnik, az új memóriavezérlő órajelenként két műveletet képes elvégezni. De hogy a gyakorlatban ez mit jelent, arra külön kíváncsiak voltunk.
A tesztekben ezúttal is a K7–K8–K10 trió és a Merom–Penryn duó kapott szerepet. Ha emlékszünk még az Athlon 64 előtti időkre, felsejlik, hogy az AMD akkoriban még egy pont-pont összeköttetést, az DEC Alpha által kifejlesztett EV6 processzor rendszerbuszát használta a processzor és az északi híd összekapcsolására. Az EV6-ból származó busz előnye elsődlegesen abban rejlett, hogy riválisánál, a Pentium Próban debütáló GTL rendszerbusz továbbfejlesztett variánsainál nagyobb sávszélességet kínált, többutas rendszerekben pedig dedikált útvonalat biztosított minden végrehajtóegység számára, míg az akkor használatos 440BX csak egy közösen használható rendszerbuszt áldozott fel erre a célra. Az AMD a K8-ban mégsem az EV6-ot vitte tovább, hanem úgy döntött, hogy a memóriavezérlőt egyszerűen a processzorba integrálja (az Alpha az EV7 esetében is éppen így tett). A kétcsatornás memóriavezérlővel rendelkező asztali K8-asok (először S939, majd AM2 platformon) megduplázták az elméletileg elérhető maximális memória-sávszélességet. Ez szép és jó volt, de nem sokat értünk vele, hiszen kétmagos Athlon 64 processzorunk magjai egyetlen közös memóriabuszon voltak kénytelenek osztozni. A megoldás kiegyensúlyozatlan, mert egyszerre csak az egyik processzormag kérhet/küldhet ezen keresztül adatot, miközben olyan magas sávszélesség áll a rendelkezésére, amit soha nem képes kihasználni. A K10-nél egy ilyen esetben már nem egy, hanem két processzor juthat hozzá az igényelt adatokhoz egyetlen ciklus alatt, igaz, az egycsatornás sávszélesség csak fele a korábbinak, mégis ez a jobb megoldás, mert így két processzormag igényeit elégítettük ki egyetlen ciklus alatt ahelyett, hogy egyetlen processzormagra pazaroltuk volna el az összes erőforrást (sávszélességet).
Az Intel esetében más a helyzet, a Core processzorok a rendszerbuszon keresztül kapcsolódnak az északi hídhoz, ami összeköttetésben áll a memóriával. Ha a négymagosokat vesszük alapul, a két kétmagos processzor egyetlen ciklus alatt elküldheti/fogadhatja a szükséges adatokat, ha éppen a rendszerbusz szűkössége ebben nem akadályozza meg. Ha a rendszerbusz nem szűkös, a chipset még akkor is órajelenként csak egyetlen memóriaműveletet tud elvégezni. A helyzet az, hogy átlagos, mindennapi felhasználást feltételezve nem jelent korlátot sem a rendszerbusz, sem a kétcsatornás memóriavezérlő (illetve az órajelenkénti egyetlen művelet). Ugyanez igaz a K8 processzorokra is. A K10-et tehát inkább az erőteljesen többszálú környezetek igényeit figyelembe véve fejlesztették ki, ezt nem is tagadja a gyártó.
Egyszerű halandó felhasználók számára tehát az AMD új megoldása nem fog érzékelhető többletet jelenteni, ez egészen biztos. De azért mi megpróbáltuk kimérni, hogy mennyi az előnye. A grafikonok megértéséhez annyit kell tudni, hogy az AMD (illetve az alaplapgyártók) a K10 esetében a kétcsatornás működést GANGED (’csoportba foglalt’ – utalva a két memóriacsatorna együttes működésére), az egycsatornás vezérlést pedig UNGANGED elnevezéssel illették. A BIOS lehetőséget ad arra, hogy kiválasszuk a nekünk szimpatikusabb változatot. Első körben az egy szálon futó memóriateszteket vettük elő, ilyen az Everest is.
Az Everest lineárisan végzett mérései szerint a K7 éppen eléri a 3,2 GB/s-os sávszélességet. Hiába a kétcsatornás DDR400-as működés, tehát a 6,4 GB/s-os elméleti maximum, ez egyszerűen nem használható ki, mivel a processzor 200 MHz-es FSB-n fut, ezen az órajelen pedig 3,2 GB/s a chipset és a processzor közti sávszélesség.
A K8 esetében már más a helyzet, hiszen a memóriavezérlő a processzor órajelén fut, tehát az elméletileg elérhető sávszélességet a memória órajele és a memóriavezérlő hatékonysága határozza meg. Mi kétcsatornás módban, DDR2-800-as memóriákkal, 1T-s command rate érték mellett teszteltük a K8-at, ahol is az elérhető maximum 12,8 GB/s, az architektúra azonban olvasásban csak 52, írásban pedig mindössze 44%-osan használta ki ezt, míg a másolás 54%-os volt. Ne feledjük, hogy ezek egyetlen szálon mért értékek, tehát hiába két- vagy négymagos a CPU, csak egyetlen processzormag memóriaelérési sebességét tükrözik. Mindezt látva akár arra is gondolhatnánk, hogy a K8-as memóriavezérlője igen hatékony, hiszen egymagos elérésben az elméleti maximum felét az íráson kívül mindenhol hozta, tehát ha két maggal számolunk, és megszorozzuk az értékeket kettővel, akkor úgy tűnik, hogy a K8 az egész rendelkezésre álló sávszélességet ki tudja használni.
Az AMD K10 első látásra nem változott túl sokat ezen a téren. Ezt a processzort már DDR2-1066-os órajelen teszteltük, a ganged és unganged mód között csak olvasásban mértünk ki különbséget, ami jól mutatja, hogy egyetlen szálon terhelve az unganged mód nem tud előnyt kovácsolni a gangeddel szemben, és persze az is látszik, hogy egyetlen processzormag nem képes ennél nagyobb adatmennyiség megmozgatására. Írásban a K10 lassabb volt a K8-nál, másolásban viszont gyorsabb.
Az Intel processzorok is változásokon mentek keresztül, a Merom olvasásban gyorsabb a Penrynnél, köszönhetően a kisebb késleltetésnek. Írásban viszont a Penryn a gyorsabb az írási rutin SSE4.1-es támogatása miatt. Másolásban ugyanolyan gyorsak voltak. A Core-t a K8/K10-zel összehasonlítva nagyon jól látszik, hogy a két implementáció szöges ellentéte egymásnak, az integrált memóriavezérlővel szerelt AMD processzorok sokkal gyorsabban férnek hozzá a memóriához, viszont erre szükségük is van, mert a gyorsítótárak mérete jóval kisebb.
Sciencemarkkal is leteszteltük a memóriaelérést, ez a program is egy szálon dolgozik. A pontos mérési módszereket nem ismerjük, de annyi azért itt is látszik, hogy az IMC-vel rendelkező AMD processzorok komoly fölényben vannak.
Ezek után a memóriaelérési, azaz késleltetési időkkel foglalkoztunk. Elsőként az Everest benchmarkjával teszteltünk, ez lineáris elérési időt mér. Itt is jól látszik, hogy a rendszerbuszos processzorok (K7, Merom, Penryn) hátrányban vannak az IMC-sekkel szemben. Érdekesség, hogy a K10 lassabb volt a K8-nál. Ez minek tulajdonítható? Mivel a K10 már közvetlenül az L1-be olvas, így az L3 cache "kivonható" az egyenletből, ezért csak arra tudunk gondolni, hogy az új memóriavezérlő egy picit lassabban éri el a memóriát, mint elődjében. A teszt azt méri, hogy a memóriaolvasási parancs kiadásától számítva mennyi idő telik el, míg az adat megérkezik a regiszterekbe. Az új memóriavezérlő lineáris elérést feltételezve 7–8 ns-mal lassabb, mint elődje. De mi a helyzet akkor, ha nem lineáris elérést mérünk? A processzor számára szükséges, memóriában található adatok nem csak lineárisan helyezkedhetnek el.
A problémát a legjobban egy LATER nevezetű programmal tudtuk illusztrálni, az alkalmazás a memória véletlenszerű elérését méri kétféle módon, egyrészt az L1-es cache-t is bevonva a munkába, másrészt az L1-et kivonva a forgalomból. Érdekes eredmények születtek. A K7 közel olyan gyors volt (80–100 ns), mint lineáris olvasásban. Jóindulattal ez a K8-ra is igaz (40–70 ns), viszont a K10 eredményei megugrottak, a lineáris olvasásban elért 60 ns-hoz képest 120–160 ns-os értékeket mértünk. Gondolhatnánk azt is, hogy ez egyrészt az L3 cache-nek tulajdonítható, de mint már tudjuk, a K10 közvetlenül az L1-be hívja az adatokat. A megoldás valószínűleg a prefetch logikában keresendő. Az AMD az előbehívók (prefetch) terén komoly változtatásokat eszközölt a K10-ben, a K8-ban egyetlen előbehívó volt, ami az L2-be dolgozott, a K10-ben viszont már két L1-es prefetcher és két memória-prefetch egység található. A K10 gyengébb eredménye talán annak a számlájára írható, hogy míg a K8 egyszerűen csak olvas és olvas (nincs semmi, ami megszabná a következő beolvasandó adat címét), addig a K10-ben az adatelérést a prefetch munkája is befolyásolja. Lineáris elérésnél a prefetchnek nincs nehéz dolga, folyamatosan előretölti az adatokat, ezzel lerövidítve az adatelérés idejét, viszont amikor véletlenszerűen kell elérni a memóriát, a prefetch ha nem is minden egyes alkalommal, de sok esetben rosszul jósol, azaz rossz adatot tölt előre, ami óriási veszteséget okoz. Ezzel egyébként nincs is semmi baj, mert igen ritka az olyan eset, hogy összevissza kelljen ugrálni a memóriában, viszont ez a teszt fényt derített arra, hogy a K10 ezen a téren is megváltozott a K8-hoz képest.
Az Intel Merom a K10-hez hasonlóan viselkedik, viszont a Penryn eredményei előtt először kicsit értetlenül álltunk. A véletlenszerű elérés ilyen mértékű csökkenésére nem lehet kizárólagos magyarázat a megnövelt másodszintű gyorsítótár, itt valami másnak is történnie kellett. A megoldás valószínűleg a megnövelt szintű asszociativitásban keresendő, a Merom L2-es gyorsítótára 16 utas, a Penryné viszont 24 utas. Minél több cellára osztjuk fel a leképzett memóriablokkokat, annál nagyobb esélyünk van arra, hogy a cache-ben megtalálható a megcímzett adat, és annál ritkábban kell felülírni a cache-cellákat. Ha az asszociativitást is bevonjuk a képletbe, akkor érthető, hogy a K10 és a Merom közel megegyező eredményeket értek el. A K10 elsőszintű gyorsítótára csak kétutas, a Meromé nyolcutas, ebben a tekintetben a Merom előnyben van, viszont ezt az előnyt elveszti a rendszerbusz lassúsága miatt.
Az előzőleg tárgyalt programok sajnos csak egy szálon mérnek, ezért keresnünk kellett egy olyan benchmarkot, mellyel több szálon is képesek vagyunk a memóriaelérés tesztelésére. Végül megtaláltuk a Rightmark Multi-Threaded Memory Testet, ami pontosan erre lett kifejlesztve. A programmal annyi szálon lehet memóriaolvasást vagy írást végezni, ahány logikai processzort lát az operációs rendszer. Be kell állítani a tesztelés során használt memóriablokkok méretét, a művelet típusát (olvasás, írás, szoftveres prefetch-csel olvasás, non-temporal írás), a használt regiszterek típusát, ezek a:
- 64 bit MMX: MOVQ reg, [mem]; MOVQ [mem], reg és MOVNTQ [mem], reg
- 128 bit SSE2: MOVDQA reg, [mem]; MOVDQA [mem], reg és MOVNTDQ [mem], reg
lehetnek.
Beállítható a szoftveres prefetch hossza is. Mi 64 MB-os blokkokat alkalmaztunk (tehát a 64 MB-ot osztottuk annyi felé, ahány szálon folyt a tesztelés, két szálon 32 MB, négy szálon 16 MB), és 128 bites regisztereket használtunk. A program lényege tehát a több szálon végzett konkurens memóriaelérés tesztelése, ezzel egy csapásra le tudtuk mérni azt is, hogy memóriaolvasás és memóriaírás egyidejű végrehajtása során a K10 tényleg annyira jó-e (megjelent az írásokat tároló puffer), hogy a K10 több szálon mennyit fejlődött, és még azt is, hogy az Intel processzorok tényleg annyira rosszak-e, merthogy a fáma szerint a rendszerbusz szűkös négy Core-magnak, ezért szűk keresztmetszetté válik.
Az egyszerű olvasási teszt, mint neve is mutatja, egyszerűen a memóriaolvasást méri, az L2 cache is beleszól az eredménybe, az így kapott érték pedig az „átlagos”, mindennapi memóriaolvasást jelképezi.
Az olvasás szoftveres prefetch-csel egy szoftveres prefetch segítségével méri az olvasást, ezzel megkerülve az L2 cache-t valóban csak a maximálisan elérhető memóriaolvasási sávszélességet méri. Ez a módszer a processzor OoO-végrehajtását segíti ki azáltal, hogy előre betölti azokat az adatokat, amikre később szüksége lesz a végrehajtó egységeknek, így nem alakulnak ki függőségek és várakozási sorok, tehát gyorsul az adatfeldolgozás. A mindennapi életben ilyennel nem nagyon találkozunk.
Az írás egyszerű lineáris írást mér, az L2 cache sebessége is számít, az eredmény pedig amolyan átlagos, mindennapi írási sebességnek felel meg.
A non-temporal írás a cache-hierarchiát megkerülve, külön erre a célra bevezetett utasítások segítségével mér maximálisan elérhető, tiszta memóriaírási sávszélességet. Ez a módszer nagy mennyiségű adat kiírása során a cache olvasási/írási kényszere alól menti fel a processzort (ugyanis nem kell állandóan felülírni a cache-cellákat, lásd fentebb), így az írási sebesség drasztikusan megnőhet a sima íráshoz képest. A valóságban ezzel sem nagyon találkozni, csak speciálisan olyan feladatoknál, amikor erre van szükség.
A teszteket ezúttal a valós felhasználáshoz közelebbi beállítások mellett végeztük el, a K7 és K8-ason kívül minden processzor 2,66 GHz-en járt (Intel: 8x333, DDR3-1333, AMD K10: 10x266 MHz, DDR2-1066 beállítás, az L3 cache 2,13 GHz-en járt), a K7-et 2 GHz-en, a K8-at pedig 2,8 GHz-en járattuk DDR2-800-as memóriasebesség mellett.
Először a Rightmarkot is egy szálon teszteltük, elsőként a sima olvasással és írással, az eredmények, pontosabban az arányok nagyjából megegyeztek az Everestben mértekkel, bár a K7 és a K8 írásban itt rosszabbul szerepelt. A K10 ganged módban itt is gyorsabb volt egy hangyányival, mint unganged módban.
Szoftveres prefetch olvasással és NT-írással a K10-en kívül az összes architektúra feltámadt, a K10 csak írásban javult, de arányaiban nézve sokkal kisebb mértékben. A K7 NT-írása közel háromszor volt gyorsabb a sima írásnál, a K8 is több mint duplájára gyorsult, és a Core processzorok is háromszoros gyorsuláson mentek keresztül. Ez csak egyet jelenthet, hogy a K10-en a cache-hierarchia igen kiegyensúlyozott, és csak alig fogja vissza a memóriaelérést, legalábbis egy szálon futó alkalmazások esetén! Ezen nincs is miért meglepődni, hiszen az egyes processzormagok elkülönített másodszintű gyorsítótárral rendelkeznek, így az írásoknál nem kell a többi processzormag L1D gyorsítótárait frissíteni. Ezzel szemben a többi architektúra a memóriaműveletek során beleütközik valamiféle korlátba (cache-szervezés lassúsága, koherenciakezelés stb.), ami visszafogja teljesítményüket (közös L2 a Core processzorokban, keskeny adatútvonalak a K8-ban).
Két programszálon tesztelve az egyik szálon olvastunk, a másikon írtunk a memóriából/ba. A sima olvasási tesztekben a K10 unganged módban 24%-kal volt gyorsabb, mint ganged módban, és 37%-kal magasabb sávszélességet ért el, mint a K8. Ez egyértelműen arra utal, hogy a K10-ben egy továbbfejlesztett, és valóban többszálas működésre kihegyezett memóriavezérlő dolgozik. A K10 ganged, tehát kétcsatornás módban csak egy picit volt gyorsabb, mint a K8, amely szintén kétcsatornás módban működik. Érdemes a Core processzorokról is szót ejteni, négymagos Intel CPU-kat teszteltünk, tehát a 2 x 4–6 MB cache sokat nyom a latba. Olvasásban még nem maradtak le túlságosan a K10-től (a K8-nál gyorsabbak voltak, de ez a nagyméretű gyorsítótárak miatt nem túl meglepő), viszont írásban már igencsak lemaradoztak. Ha összeadjuk az egyes architektúrák olvasási és írási értékét, akkor sorrendben 5748, 7282, 6131, illetve 5272, 5250, 5691 és 5606 MB/s-ot kapunk. Mint látható, a legmagasabb értéket a K10 érte el unganged módban, a rendelkezésére álló 17 GB/s-nak az 42%-át, a Core processzorok a 21,3 GB/s-os sávszélességnek (DDR3-1333-as beállítás) mindössze a 26–28%-át képesek elérni, és ez még csak a kétszálas teszt volt. A Core processzoroknál érdemes külön figyelmet szentelni az eltérő magokon elindított tesztek eredményeire is, összességében ezekben az esetekben nem változott meg jelentősen a kép, az összeadott olvasási és írási eredmények alig térnek el egymástól.
A szoftveres prefetchelt olvasás és non-temporal store tesztben az arányok kicsit megváltoztak, de ez inkább csak a non-temporal store eredményekre igaz, az olvasási eredmények alig változtak. A K8 ismét több mint duplájára gyorsult. Ugyanez elmondható a K10-ről is, és a Core processzorok is több mint kétszeres gyorsulást mutattak be. Az egyszálas eredmények alapján a K8 és a Core architektúrák szereplése nem meglepő, és ha jobban átgondoljuk a dolgokat, akkor a K10 esetében sem. A K10-ben három gyorsítótár található, ezeket folyamatosan karban kell tartani, ami rengeteg „energiát”, sávszélességet igényel a processzortól, folyamatosan figyelni kell, hogy az egyes magoknak milyen adatokra van szüksége, frissíteni kell nem kevesebb, mint kilenc egymástól függő cache celláit, ez pedig itt szépen kibukott, ami egyébként nem probléma, mert a valós tesztben, tehát ahol számít, ott a K10 volt a leggyorsabb.
Következzenek a legérdekesebb eredmények, itt már négy szálon teszteltük a processzorokat, két szálon olvastunk, a másik kettőn írtunk. Ez a felállás nem mellesleg napjaink programjaiban igencsak valószínűtlen, de most architektúrák erősségeinek és gyengéinek felfedésére vállalkoztunk, ezért extrém körülményeket kellett teremtenünk. Az egyszerű olvasás-írás tesztben nyilvánvalóvá vált, hogy a K10 erre teremtetett, unganged módban sokkal jobban szerepelt, mint ganged módban, és gyorsabb volt a Core processzoroknál is. Érdekes látni, hogy ganged módban az egyes programszálak szinte hajszál pontosan ugyanakkora sávszélességet kaptak a processzortól, míg unganged módban a leglassabb írás is 29%-kal nagyobb sávszélességgel rendelkezett. Meglepő vagy sem, olvasásban a Core processzorok sem szerepeltek rosszul, viszont ne feledkezzünk meg arról, hogy ez egy négy szálon futó teszt volt, és a két írási szál jócskán lemaradt. Mindenesetre a K10 itt 7573 MB/s-ot, ezzel szemben a Penryn összesen csak 5455 MB/s-os össz sávszélességet tudott elérni. Utóbbi egyébként nagyjából megegyezik a kétszálas tesztben elért 5691 MB/s-mal, ami talán azt jelenti, hogy a rendszerbusz nem igazán szűk keresztmetszet, de ne felejtsük el, hogy ebben benne van a másodszintű gyorsítótár sebessége is.
Éppen ezért számunkra ebből a szempontból érdekesebb, beszédesebb a szoftveres prefetch-csel végzett olvasási és non-temporal írási eredmények összege. Mint látható, a K10 mindkét módban szépen begyorsult, de továbbra is az unganged mód maradt a király. Nagyon szép eredmény a K10-től unganged módban, hogy négy szálon terhelve képes a 17 GB/s-os (pontosabban 2 x 8,5 GB/s) sávszélességnek a 72%-át kihasználni (12 300 MB/s), ganged módban a kihasználtság csak 65%-os. Ha unganged módban a memóriacsatornák kihasználtságát nem együttesen értékeljük, akkor a 8,5 GB/s-os max sávszél 73 illetve 70%-a kerül felhasználásra. Az Intel processzorok legjobb esetben is csak 35%-ra képesek terhelni a memóriákat (7429 MB/s), de ha a rendszerbusz kihasználtságára vagyunk kíváncsiak, akkor a 10,6 GB/s értéknek a 70%-át éri el a Penryn – a legjobb esetben, de ez még mindig 40%-kal alacsonyabb érték, mint amit a K10 ért el, így kijelenthetjük, hogy ezen a téren tényleg a K10 a legfejlettebb architektúra. Szervervonalon az Intel-rendszer FB-DIMM memóriákkal valószínűleg jobban szerepelt volna, hiszen FB-DIMM-eket használva a memóriacsatornák számának növekedésével együtt növekszik a konkurens műveletek elvégzésének hatékonysága is (ahány modul, annyi konkurens olvasás-írás lehetséges), na de ez egy másik téma.
A cikk még nem ért véget, kérlek, lapozz!