# Caches ## Cache-Speicher ![image_502.png](image_502.png) - Deutlich schneller als Zugriff auf Hauptspeicher - viel kleiner als Hauptspeicher ## Grundprinzipien ![image_503.png](image_503.png) ## Speicher-Zugriff über Cache - Transparenter Zugriff für die CPU - Zugriff auf Speicher anhand der Speicheradresse aus der CPU - Daten werden zurückgeliefert - dazwischen: Cache ## Aufbau Cache Speicher ![image_504.png](image_504.png) - Cache Line - Einheit für Kopie eines Memory-Blocks - mehrere Worte - Index - Adressiert die Cache-Line - Data - Daten aus dem Speicher - V - Valid Bit - 1 = Vorhanden - 0 = nicht Vorhanden (_Anfangswert_) - Tag - Blockadresse - welcher zum Index passende Memory-Block ist abgelegt? ### Offset #### Zugriff innerhalb des Caches - Mit Offset innerhalb der Cacheline auf einzelne Wörter/Bytes zugreifen - Beispiel - Byte-Offset im Speicher - 2Bit - Größe Cache-Line - 4 Byte - Wort-Offset für Adressierung der Wörter in Cache-Line - 2 Bit - Offset in ADresse gesamt - 4 Bit #### Offset Beispiel ![image_506.png](image_506.png) ![image_505.png](image_505.png) ### Index: Cache Adressierung ![image_507.png](image_507.png) - Speicherort wird durch Index-Teil der Adresse bestimmt - $Cacheadresse = Speicheradresse \mod ZeilenImCache$ ### Tag: Zuordnung der Daten - Woher ist bekannt welcher Block im Speicher abgelegt ist - Speichern der Blockadresse (TAG) und der Daten - ![image_508.png](image_508.png) ### Assoziativität: Cache-Zeilen mit gleichem Index ![image_510.png](image_510.png) - Durch weiteren Satz von Cache-Lines - Daten mit gleichem Index aber unterschiedlichen Tags speichern - ![image_509.png](image_509.png) #### Grad der Assoziativität - höhere Assoziativität verringert Fehlerzugriffrate - 1-Fach: 10,3% - 2-Fach: 8,6% - 4-Fach: 8,3% - 8-Fach: 8,1% ## Cache-Beispiel ![image_511.png](image_511.png) ![image_512.png](image_512.png) ![image_513.png](image_513.png) ![image_514.png](image_514.png) ![image_515.png](image_515.png) ![image_516.png](image_516.png) ![image_517.png](image_517.png) ## Zusammenfassung Adressierung ![image_518.png](image_518.png) ## Cache Organisation (Assoziativität) - [Direkt abgebildet (direct mapped)](#direkt-abbildender-cache) - ein Datenwort kann in einem Eintrag abgelegt sein - ![image_522.png](image_522.png) - [Voll assoziativ (fully associative)](#voll-assoziativer-cache) - ein Datenwort kann in einem beliebigen Cache-Eintrag abgelegt sein - ![image_524.png](image_524.png) - [Satz assoziativ (set associative)](#n-fach-satzassoziativer-cache) - ein Datenwort kann in wenigen Cache-Einträgen (_typischerweise 2-8_) abgelegt sein - ![image_523.png](image_523.png) ### Direkt abbildender Cache ![image_519.png](image_519.png) ### Voll assoziativer Cache ![image_520.png](image_520.png) ### N-Fach satzassoziativer Cache ![image_521.png](image_521.png) ## Lesezugriff - Wenn Prozessor Wort aus Hauptspeicher lesen will - Cache-Logik prüft, ob Wort schon im Cache ist - **cache hit** - Daten im Cache - Wort an Prozessor weitergeben - Trefferrate = Treffer / Zugriffsrate - **cache miss** - Daten nicht im Cache - Daten aus HS lesen - Fehlerzugriffsrate = 1 - Trefferrate - ![image_525.png](image_525.png) ## Lesen von Daten ### Ersetzungsstrategien im assoziativen Cache - Falls Wort nicht im Cache vorhanden - aus Speicher in Cache laden - Bei direkt abgebildeten Cache - Zuordnung der Adresse des Wortes zu einer Cache-Zeile eindeutig - Beim assoziativen Cache verschiedene Strategien möglich - **Least Recently Used (LRU)** - Wählt Zeile, die am längsten nicht genutzt wurde - Für mehr als 4-Fach zu aufwendig - **Zufällig** - Wähle zufällige Zeile - Ähnliche Trefferrate wie LRU bei hoher Assoziativität - **Round-Robin** - Zyklischer Zugriff ### Initiales Lesen von Daten - Zwei Lese- / Füllstrategien - **on demand, demand fetching** - Beim ersten Lesen einer Information aus HS - ganze Zeile in Cache laden, falls noch nicht drin - **Prädiktiv, prefetch** - Vorhersage, welche Speicherzeilen gebraucht werden - Während Leerlaufphasen in Cache vorladen - Zweiter Programmzähler (Remote PC) - Künftigen Programmablauf bestimmen - Gut weil - Bessere Nutzung [räumlicher Lokalität](Rechnersysteme_Intro.md#r-umliche-lokalit-t) - Prefetching durch Hardware - Stream Buffers zwischen Cache und Speicher - Prefetching durch Software - ```c++ for (int i = 0; i < 1024; i++){ prefetch (array1 [i+k]); // stride k array1[i] = 2* array1[i]; } ``` ## Schreibzugriff - Daten in Cache und HS müssen konsistent bleiben - Wenn Prozess Speicherstelle schreiben möchte, die schon im Cache ist - **write-through** - Schreiben erfolgt sowohl im Cache als auch im HS - langsame Schreibzugriffe - **write-back** - Schreiben nur im Cache - Eintrag markieren - _dirty bit_ - Wenn Cache-Line verdrängt wird in HS schreiben - _Gefahr Inkonsistenz_ - **No-write** - Wort nur im HS schreiben - im Cache als invalid markieren - langsame Schreibzugriffe - ggf. danach langsame Lesezugriffe ### Initiales Schreiben von Daten - **write-around** - nur in HS schreiben - **write-allocate** - fetch on write - erst Cache-Line in den Cache, dann wie oben ### Übliche Kombinationen - write-allocate → write-back - write around → write through ### Schreib-Buffer - ![image_526.png](image_526.png) - beschleunigt Schreiben, da kein Stall erfolgt - Wenn Buffer voll ist - strukturelle Abhängigkeit - Warten bis Schreiben in HS abgearbeitet ist - Bei direkt folgendem Lesezugriff auf zu schreibende Daten - Datenabhängigkeit ## Cache Spezifikation - Definiert durch - Anzahl der Cache-Zeilen C - Größe einer Cache-Zeile L - Assoziativität m - Daraus lässt sich bestimmen - Aufteilung der ADress in Offset, Index, Tag - [Gesamtgröße Cache](#gesamtgr-e-cache) ## Gesamtgröße Cache ![image_527.png](image_527.png) ## Cache-Leistung ![image_528.png](image_528.png) ### Beispiel Cache Leistung ![image_529.png](image_529.png) ![image_530.png](image_530.png) ## Multilevel Cache Organisation ![image_531.png](image_531.png) - Level 1 - Cache für Instruktionen und Daten - Level 2 - vereint für Instruktionen und Daten - Level 3 - auf Board-Ebene (Static RAM)