Cache im PC - einfach nicht so einfach
Mit den Ausführungen auf dieser Seite soll nur ein kleiner Einblick in die Welt des Cache gegeben werden. Eine vollständige Abhandlung würde diesen Rahmen hier sprengen - Literatur dazu ist in vielfältiger Form im Handel erhältlich.
Vorbemerkungen
Erstmals wurde zur Beschleunigung der Speicherzugriffe in 386er-Computer ein Cache eingesetzt (ab ca. 25MHz Taktfrequenz), denn der Zugriff auf den Hauptspeicher (DRAM) dauerte für diese CPU's (schon) zu lange.
Der Cache als aus statischen RAM-Bausteinen (SRAM) aufgebauter spezieller Speicherbereich war zur damaligen Zeit noch sehr teuer und auch noch relativ langsam (ca. 25..50ns, im Gegensatz zu 3..15ns heutiger Caches).
Deshalb war der Cache-Speicher auch anders aufgebaut: es gab nur einen Cache und der war relativ klein (meist 32..128kByte). Trotz dieser Einschränkungen war damit aber eine Leistungssteigerung möglich,
denn übliche DRAM-Bausteine hatten Zugriffszeiten von 100..200ns und auch die Taktfrequenzen der Prozessoren waren noch nicht so hoch.
Mit Einführung der 486er-Prozessoren wurde der Cache dann geteilt: Der Prozessor selber beinhaltete einen (relativ kleinen) Cache, der üblicherweise mit vollem Prozessortakt läuft (L1-Cache, "Prozessorcache") und einen externen Cache (L2-Cache, "Speichercache"),
der relativ groß ist aber meist nur mit "Bus-Geschwindigkeit" läuft (Ausnahmen z.B. PPro, PII ..). Eine dem Cache verwandte Arte ist übrigens der sogenannte Prefetch-Queue (Warteschlange) im Prozessor, die aber andere Aufgaben hat und
auch etwas anders als übliche Caches aufgebaut ist (existierte auch schon in Oldie-Prozessoren, das aber nur am Rande).
Da diese Art von Speicher (statischer RAM) teurer ist als der als Hauptspeicher eingesetzte (dynamischer RAM),
wurde bei der Einführung der EDO-RAM-Speicher im Pentium versucht Kosten zu sparen, indem man den externen (L2-)Cache einfach wegließ und auch auf den Motherboards keinen Platz zum Nachrüsten dafür vorsah.
Das die verbesserten Zugriffszeiten des EDO-RAM kein Ausgleich für den weggelassenen Cache sein konnte war schnell auch den Herstellern klar, denn das effektive Wirkprinzip des Cache läßt sich durch EDO's nicht nachbilden.
Aufbau und Arten
Prinzipieller Aufbau eines Caches. Ab 486er für den L2-Cache (extern) - der L1-Cache (CPU-intern) ist ähnlich aufgebaut. |
|
Es gibt verschiedene Arten von Caches (interne Arbeitsweise):
- Asynchroner Cache (A-Cache):
- Diese Cache-RAMs sind wie die DRAMs in Bänken organisiert und arbeiten asynchron zum Prozessor-Takt mit Enable-Signalen.
- Synchroner Cache (S-Cache):
- Synchrone SRAMs (Synchronous SRAM) sind im Gegensatz zu den asynchronen Cache-RAMs optimaler an das Motherboard angepaßt, da sie mit einem zur CPU synchronen Takt arbeiten und so Wartezyklen eingespart werden. Die Zugriffszeiten liegen typisch unter 20ns und können auf den meisten Boards optional zu den A-Cache-Bausteinen eingesetzt werden.
- Burst-Cache (B-Cache):
- Burst-SRAMs sind in der Lage selbständig nach Übermittlung der Startadresse die darauffolgenden Adressen (intern) selbst zu erzeugen. Durch diese Art der Adressierung fällt ein großer Teil des Overheads weg, wodurch die Daten schneller zur Verfügung gestellt werden können.
- Pipelined-Burst-Cache (PB-Cache):
- In fast allen neueren PCs sind die PB-SRAMs zu finden, die gegenüber den Burst-SRAMs bei aufeinanderfolgenden Burst-Zugriffen die Daten durch eine überlappende Übertragung von Startadresse und Daten einen Zyklus einsparen können (die Startadresse wird quasi im SRAM im voraus gespeichert und der Datenzugriff schon vorbereitet).
Organisation des Caches
Während in 386er- und älteren 486er-Prozessoren der L1-Cache aus einem Stück bestand (Unified Cache, d.h. Daten und Programmcode in einem gemeinsamen Cache), sind die L1-Caches der modernen Prozessoren zweigeteilt in einen jeweils gleich großen Daten- und einen Code-Cache mit jeweils eigener TLB (Translation Lookaside Buffer zur Umsetzung der linearen Adresse in die physikalische). Dies hat den Vorteil, das das Programm nicht ständig noch genutzte Daten aus den Cache wirft und umgekehrt. Zwar ist dieses Verfahren nicht so (Cache-)Speicher-effektiv, da z.B. im Extremfall der eine (Halb-)Cache nur halbvoll ist, während der andere aus allen Nähten platzt, aber die Performance wird trotzdem gesteigert, da nicht ständig kurz vorher rausgeworfene Daten wieder neu eingeladen werden müssen. Eine Unterscheidung des L2-Cache in Daten - und Code-Cache ist eher selten, wenn überhaupt anzutreffen.
Moderne L1-Caches sind zumeist als 4-Wege set-assoziativer Cache aufgebaut (zur Erläuterung siehe Glossar).
Die Cache-Bausteine
Der Cache auf einem Motherboard kann in unterschiedlichen Bauweisen auftreten:
- als DIP-Bausteine gesteckt/gelötet
Diese Art wird bei 386er-/486er-Boards am häufigsten verwendet. Zu erkennen an dem "Schaltkreisbergwerk" in einer Ecke des Boards. Meist ist eine Konfiguration wie folgt üblich:
(8* 8kx8 bedeutet 8 Bausteine mit einer Organisation von 8kBit mit 8Bit Datenbusbreite)
Cache-Konfigurations-Beispiele |
Größe | Cache-RAM | Cache-Tag-RAM | Cache-Dirty-RAM |
64kByte | 8* 8kx8 | 2* 4kx4 | 1* 4kx4 |
64kByte | 8* 8kx8 | 1* 8kx8 | 1* 4kx4 |
64kByte | 8* 8kx8 | 3* 4kx4 | 1* 4kx4 |
128kByte | 4* 32kx8 | 1* 8kx8 | 1* 8kx8 |
256kByte | 8* 32kx8 | 2* 16kx4 | 1* 16kx4 |
256kByte | 8* 32kx8 | 1* 32kx8 | 1* 16kx4 |
512kByte | 8* 64kx8 | 1* 32kx8 | 1* 64kx4 |
|
Diese Konfigurationen wurden auf einer Vielzahl von Boards entdeckt; es sind aber auch andere Kombinationen möglich.
Die Bestückungsvarianten sind meist im Manual vermerkt oder aber auf dem Motherboard. Bei Unstimmigkeiten zwischen Board und Manual sollte man immer dem Board vertrauen,
denn Änderungen werden im Manual (wenn überhaupt) meist erst später eingearbeitet. Leider gibt es immer mal wieder eine Zeit der Einsparungen. So wurde zu Zeiten,
als SRAM noch teuer war ab und zu auch mal der Dirty-Baustein eingespart. Das hatte natürlich für den (oder das ?) Cache eine empfindlichen Performance-Einbuße zur Folge.
- als PLCC-Bausteine aufgelötet (meist bei 586er-Boards)
hier läßt sich leider keine genaue Zuordnung treffen, da hier jeder Hersteller sein eigenes Süppchen kocht. Meist ist er er in der Nähe des PCI-Chipset zu finden und
aus üblicherweise zwei Bausteinen bestehend aufgebaut. Das Dirty- und das TAG-RAM sind sind auch in der Nähe zu finden (zwei Bausteine mit kleinerem PLCC- oder FP-Gehäuse).
- als COAST-Modul gesteckt
Dieses 160polige-Modul ("Cache On A Stick") wird in einen speziellen Sockel gesteckt (sieht aus wie ein PCI-Steckplatz mitten auf dem Board).
Es wird meist zur Erweiterung des vorhandenen On-Board-Caches dazu gesteckt; es gibt aber auch Boards, die keinen On-Board-Cache besitzen und deshalb unbedingt ein solches COAST-Modul zur (schnelleren) Arbeit benötigen.
Das COAST-Modul ist üblicherweise ein PB-Cache und hat sich heutzutage als Quasi-Standard (von intel) durchgesetzt (Ausnahmen gibt es in der Bauweise leider auch hier, z.B. einige ältere ASUS- und GigaByte-Boards).
Ansicht eines 160poligen Standard-COAST-Moduls |
|
Berechnung des Caches
Die Größe des benötigten Caches bzw. der maximal gecachten Hauptspeichergröße bei Set-Associative- oder Direct-Mapped-Cache läßt sich wie folgt berechnen:
CACHE |
= |
MEMORY 2TAGBIT |
|
|
in Byte |
TAG |
= |
CACHE DATA |
x TAGBIT |
|
in Bit |
DIRTY |
= |
CACHE DATA |
|
|
in Bit |
MEMORY |
= |
CACHE DATA |
x 2TAGBIT |
|
in Byte |
|
Beispiel: Hauptspeicher (DRAM)=32MB, 8bit-Tag, Cache-Line=16bit. minimal benötigte Cache-Speichergröße: 33554432/28 = 131072 => 128kByte minimale TAG-RAM-Größe: (131072/16)*8 = 65536 => 64kBit (8kByte) Benötigter Dirty-Bit-Speicher: 131072/16 = 8192 => 8kBit |
Abkürzungen |
CACHE |
|
Größe des benötigten Caches (in Bytes) |
MEMORY |
|
Größe des Speichers (in Bytes) |
TAG |
|
Größe des benötigten Tag-RAM (in Bits) |
TAGBIT |
|
Größe eines Tag (in Bits) |
DATA |
|
Größe einer Cache-Line (in Bytes) |
DIRTY |
|
Größe des benötigten "dirty bit"-Speichers |
Cache as Cache can - Glossar
(hier am Beispiel 486er + höher)
- Assoziativer Cache:
- Eine aufwendige Cache-Verwaltung, die zu jeder Index-Adresse mehrere Einträge gestattet (zweifach, vierfach ... voll-assoziativ). Dadurch wird das Risiko des gefürchteten Trashings erheblich kleiner. Man benötigt aber zwei, vier ... jede Menge Komparatoren die, alle gleichzeitig aktiv sein müssen. Nicht voll-assoziative Caches müssen sich außerdem die zeitliche Reihenfolge der Einträge merken, damit bei Überfüllung immer der älteste rausgeworfen wird (LRU-Algorithmus: Least Recently Used). Der 486er verfügt über einen 8-KByte-Vierfach-Assoziativ-Cache.
- Burst:
- Optimale Performance erreicht der 486er bei einem Cache Read Miss, wenn er eine komplette Cache-Line (vier DWords) in einem Schwung (Burst) einliest. Am schnellsten ist der 2-1-1-1-Burst, der für das erste Byte 2 CPU-Takte und für die drei folgenden nur noch je einen Takt benötigt.
- Cache-Line:
- Die Verwaltungseinheit eines Cache. Beim 486er besteht sie aus vier DWords (also 16 Byte). Jede Cache-Line benötigt daneben einen Eintrag im Tag-RAM. Second-Level-Caches haben im Regelfall ebenfalls eine Cache-Line von 4 DWords.
- Cache-Bereich:
- Die meisten Second-Level-Caches geizen mit Adreßbits für Tag-RAMs und Komparatoren, so daß sie nur einen Teil des 4-GB-Adreßraums des 486er cachen können (der 486er selbst cacht alles).
- Cache Read Miss:
- Das angeforderte Datum steht nicht im Cache und muß vom Hauptspeicher nachgeladen werden.
- Cache Read Hit:
- Das angeforderte Datum steht bereits im Cache. Beim First-Level-Cache vermag die CPU darauf genausoschnell zuzugreifen, wie auf die internen Register. Beim Second-Level-Cache wird das Datum in der Regel per Burst fast wait-state-frei an die CPU und parallel an den 1st-Level-Cache geschickt.
- Cache Write Hit:
- Die betroffene Adresse ist gecacht, Cache und Hauptspeicher müssen aktualisiert werden. Ein Write Thru unterscheidet zwischen ... Clean und ... Miss.
- Cache Write Hit Clean:
- (Write Thru) Die betroffene Adresse ist gecacht und noch unverändert, also nicht dirty. Dieser Zugriff dauert oft einen Takt länger, da nicht nur das Datum im Cache abgespeichert, sondern auch noch das Dirty-Bit gesetzt werden muß.
- Cache Write Hit Dirty:
- (Write Thru) Die betroffene Adresse ist gecacht, aber bereits dirty. Der Cache-Controller braucht nur das Datum im Cache abzuspeichern.
- Cache Write Miss:
- Dieser Zugriff geht im Regelfall völlig am Cache vorbei direkt auf den Hauptspeicher.
- Castoff:
- Auch beim Write Thru müssen irgendwann Daten zum Hauptspeicher zurückgeschrieben werden, wenn der Cache den Eintrag für ein neues Datum benötigt ('Castoff'). Ein spezieller Castoff-Buffer, der eine ganze Cache-Line aufnimmt, kann hierbei viel Zeit sparen.
- Daten-Kohärenz:
- Der wichtigste Job des Cache-Controllers: alle beteiligten Prozessoren und Bus-Master müssen mit übereinstimmenden aktuellen Daten arbeiten. Bei größeren Multiprozessorsystemen wird dieses durch aufwendige Daten-Konsistenz-Protokolle (M.E.S.I.) erreicht.
- Direct Mapped Cache:
- Eine einfache Cache-Verwaltung; nur ein Komparator ist nötig, um den Eintrag im Tag-RAM an der Index-Adresse mit dem Rest der Zugriffsadresse ('die Map-Adresse') zu vergleichen. Der Nachteil ist, daß er für jede Index-Adresse nur einen einzigen Eintrag erlaubt und so Trashing leicht möglich wird.
- Dirty-Bit:
- Bei Write Thru muß sich der Cache-Controller merken, welche gecachten Daten im Cache eventuell nicht mit den zugehörigen im Hauptspeicher übereinstimmen, da zwischenzeitlich auf die Adresse geschrieben wurde (ein Vergleich auf wirkliche Änderung findet in aller Regel nicht statt). Unglücklich ist, daß zumeist nur ein Dirty-Bit für eine ganze Cache-Line gesetzt wird. Beim Castoff müssen dann alle vier DWords zurückgeschrieben werden, selbst wenn sich nur ein Byte geändert hat.
- First-Level-Cache (L1-Cache):
- Ist beim 486er der interne Cache des Prozessors, der mit dem externen Second-Level-Cache korrespondiert.
- Index-Adresse:
- Der Teil der Zugriffsadresse, der direkt das Tag-RAM adressiert. Bei 64 KB Cache mit einer Cache-Line von 4 DWords sind das die Adreßbits A15..A4.
- Interleave:
- Eine Methode, SRAMs oder DRAMs verschachtelt im Adreßraum anzulegen; dadurch erreicht man bei adreßmäßig aufeinanderfolgenden Zugriffen (was ja bei Bursts und Opcode-Fetches die Regel ist) einen deutlich schnelleren Zugriff beziehungsweise kann langsamere RAMs einsetzen. DieVerschachtelung kann dword-weise (siehe SiS-Chipsatz), aber auch page-weise (Chips) erfolgen.
- Non-Cacheable-Areas:
- In einigen Fällen muß man bestimmte Speicherbereiche vorn Cachen ausnehmen, insbesondere wenn sich dort Kommunikationsbereiche wie Dual-Ported-RAMs, Memory Mapped I/O (XGAs), Coprozessoren und so weiter befinden.
- Page Mode:
- Der Zugriff auf Daten, die innerhalb einer DRAM-Page liegen (je nach DRAM zwischen 256 Byte und 2 KByte), ist beim Page-Mode (mit CAS-only) gut doppelt so schnell wie beim klassischen RAS-/CAS-Zugriff. Dafür dauern aber Page-Wechsel etwas länger.
- Posted Write Cache:
- Ein Cache mit Write-Buffern.
- Second-Level-Cache (L2-Cache):
- Ein zweiter Cache zwischen dem kleineren, aber schnelleren First-Level-Cache und dem größeren, aber noch langsameren Hauptspeicher. Er muß dafür sorgen, daß der 1st-Level-Cache immer komplett in ihm abgebildet ist ("Consistency by Inclusion").
- Set:
- Jedes Tag und die zugeordnete Cache-Line sind Element eines Set. Die 8-bit-Adresse A11-A4 bestimmt das gewünschte aus 256 möglichen Sets. Ein Set setzt sich also im Prinzip aus einem Cache-Directory-Eintrag und dem zugehörigen Cache-Speichereintrag für jeden Weg zusammen.
- Tag-RAM:
- Sehr schnelles und teures SRAM, in dem sich der Cache-Controller die Adressen der gecachten Daten vermerkt, sowie gegebenenfalls einige Attribute: Dirty bei Write Thru, oder auch Valid-Bits oder LRU-Bits bei assoziativen Caches.
- Trashing:
- Das Zweitschlimmste (nach der Daten-Inkohärenz), was einem Cache passieren kann. Bei unglücklichen Adreßlagen schmeißen sich aufeinanderfolgende Zugriffe immer wieder gegenseitig aus dem Cache, was viel Zeit kostet. Assoziative Caches verringern dieses Risiko insbesondere bei kleinen Caches erheblich; ab etwa 64 kByte ist aber auch bei Direct Mapped Caches das Risiko schon recht klein. Trashing kann auch beim Page-Mode der DRAMs auftreten (dauernde Page-Wechsel). Hier verringert Interleave das Risiko.
- Valid-Bit:
- Manche Caches (etwa der 1st-Level des 486er) merken sich zu jeder Adresse in einem Bit, ob diese gültig ist oder nicht. Der Vorteil ist, daß man dann den Cache sehr leicht ein- oder ausschalten kann. Die meisten Second-Level-Caches verzichten auf das "teure" Valid-Bit und müssen dann beim Einschalten des Cache durch aufwendige Füllroutinen dafür sorgen, daß der Cache nur gültige Einträge enthält. Write-Thru-Caches müssen ferner beim Abschalten des Cache alle Dirty-Einträge zurückschreiben.
- Weg (Way):
- Gibt die Assoziativität des Cache-Systems an.
- Write Thru (Write Through):
- Jedes geschriebene Datum gelangt sofort oder gepuffert über einen oder mehrere Write-Buffer an denHauptspeicher. Bei einem Cache Write Hit wird parallel dazu der Cache-Eintrag aktualisiert. Diese Methode benutzt der 486er selbst, der mit vier Write-Buffern (4 x DWord) ausgerüstet ist.
- Write Back (Write Copy):
- Der Cache speichert das neue Datum zwischen und merkt sich in einem Dirty-Bit, daß der Hauptspeicher an der zugehörigen Adresse nicht mehr aktuell ist. Der 486er muß nicht auf das Abspeichern warten, sondern kann ohne Zeitverlust weitermachen. Die meisten Write-Back-Caches machen das aber nur bei einem Cache Write Hit. Ein Cache Write Miss hingegen wird dann immer direkt auf den Hauptspeicher geführt und nicht gecacht.
- Write Buffer:
- Nehmen das zu schreibende Datum auf und schreiben es erst 'bei Gelegenheit', wenn der Bus frei ist zurück. Wenn die Schreibvorgänge nicht zu schnell aufeinanderfolgen, können sie aus CPU-Sicht daher wait-state-frei erfolgen. Der 486er hat gleich vier solcher Buffer.