Ich fange gerade an, das Konzept der direkt zugeordneten assoziativen Caches zu lernen. Ich habe einige elementare Zweifel. Hier geht's.
Angenommen, Adressen sind 32 Bit lang, und ich habe einen 32KB Cache mit 64Byte Blockgröße und 512 Frames, wie viele Daten sind tatsächlich im "Block" gespeichert? Wenn ich eine Anweisung habe, die von einem Wert von einer Speicherstelle lädt, und wenn dieser Wert eine 16-Bit-Ganzzahl ist, ist es so, dass einer der 64Byte-Blöcke jetzt nur einen 16-Bit- (2Bytes) Ganzzahlwert speichert. Was ist mit den anderen 62 Bytes innerhalb des Blocks? Wenn ich jetzt einen anderen Ladebefehl habe, der auch einen 16 Bit Ganzzahlwert lädt, geht dieser Wert nun in einen anderen Block eines anderen Rahmens, abhängig von der Ladeadresse (Wenn die Adresse dem selben Rahmen des vorherigen Befehls zugeordnet wird, wird der vorherige Wert entfernt und der Block speichert wieder nur 2 Bytes in 64 Bytes). Richtig?
Bitte vergib mir, wenn das wie ein sehr dummer Zweifel erscheint, es ist nur so, dass ich meine Konzepte richtig verstehen will.
Ich habe diese E-Mail geschrieben, damit jemand Caches erklären kann, aber ich denke, dass Sie es auch nützlich finden könnten.
Sie haben 32-Bit-Adressen, die sich auf Bytes im RAM beziehen können. Sie möchten die Daten, auf die Sie zugreifen, zwischenspeichern können, um sie später zu verwenden.
Nehmen wir an, Sie möchten einen 1-MiB-Cache (2 20 Bytes).
Was machst du?
Sie haben zwei Einschränkungen, die Sie erfüllen müssen:
- Caching sollte so einheitlich wie möglich über alle Adressen sein. d. h., Sie möchten keine bestimmte Art von Adresse beeinflussen.
- Wie machst du das? Benutze den Rest! Mit mod können Sie beliebige ganze Zahlen gleichmäßig über den gewünschten Bereich verteilen.
- Sie möchten die Buchhaltungskosten minimieren . Das bedeutet z.B. Wenn Sie in Blöcken von 1 Byte zwischenspeichern, möchten Sie nicht 4 Byte Daten speichern, nur um zu verfolgen, wo 1 Byte gehört.
- Wie machst du das? Sie speichern Blöcke, die größer als nur 1 Byte sind.
Nehmen wir an, Sie wählen 16-Byte-Blöcke (2 4 -Byte). Das heißt, Sie können 2 20 / 2 4 = 2 16 = 65,536 Datenblöcke zwischenspeichern.
Sie haben jetzt ein paar Optionen:
- Sie können den Cache so gestalten, dass Daten aus einem beliebigen Speicherblock in any der Cache-Blöcke gespeichert werden können. Dies würde als voll assoziativer Cache bezeichnet werden.
- Der Vorteil ist, dass es die "fairste" Art von Cache ist: Alle Blöcke werden komplett gleich behandelt.
- Der Kompromiss ist die Geschwindigkeit: Um herauszufinden, wo der Speicherblock abgelegt werden soll, müssen Sie alle Cache-Blöcke nach einem freien Speicherplatz durchsuchen. Das ist wirklich langsam.
- Sie können den Cache so entwerfen, dass Daten aus einem Speicherblock nur in einem einzelnen -Cache-Block gespeichert werden können. Dies würde als Direct-Mapped-Cache bezeichnet werden.
- Der Vorteil ist, dass es die schnellste Art von Cache ist: Sie überprüfen nur 1, ob sich das Objekt im Cache befindet oder nicht.
- Der Nachteil ist, dass jetzt, wenn Sie ein schlechtes Speicherzugriffsmuster haben, Sie zwei Blöcke hintereinander treten lassen können, wobei noch unbenutzte Blöcke im Cache verbleiben.
- Sie können eine Mischung aus beidem machen: Ordnen Sie einen einzelnen Speicherblock mehreren Blöcken zu. Dies ist, was echte Prozessoren tun - sie haben assoziative N-Wege-Caches.
Direkt gemappter Cache:
Jetzt haben Sie 65.536 Datenblöcke, wobei jeder Block aus 16 Bytes besteht.
Sie speichern es als 65.536 "rows" in Ihrem Cache, wobei jede "row" aus den Daten selbst besteht, zusammen mit den Metadaten (in Bezug darauf, wo der Block gehört, ob er gültig ist, ob er geschrieben wurde, etc.) p>Frage: Wie wird jeder Block im Speicher auf jeden Block im Cache abgebildet?
Antwort: Nun, Sie verwenden einen direkt zugeordneten Cache, der mod verwendet. Das bedeutet, dass die Adressen 0 bis 15 dem Block 0 im Cache zugeordnet werden; 16-31 werden auf Block 2 abgebildet, etc ... und es wird umgebrochen, wenn Sie die 1-MiB-Marke erreichen.
Wie lautet die Speicheradresse M, wie finden Sie die Zeilennummer N? Einfach: N = M% 2 20 / 2 4 .
Aber das sagt Ihnen nur, wo Sie die Daten speichern und nicht wie sie abrufen . Sobald Sie es gespeichert haben und versuchen, erneut darauf zuzugreifen, müssen Sie wissen, welcher 1-MB-Speicherbereich hier gespeichert wurde, oder?Das ist also ein Stück Metadaten: die Tag-Bits. Wenn es in Zeile N ist, müssen Sie nur wissen, was der Quotient während der Mod-Operation war. Dies ist für eine 32-Bit-Adresse 12 Bits groß (da der Rest 20 Bits ist).
Ihr Tag wird also 12 Bit lang - insbesondere die obersten 12 Bits einer beliebigen Speicheradresse.
Und Sie wussten bereits, dass die untersten 4 Bits für den Versatz innerhalb eines Blocks verwendet werden (da der Speicher Byte-adressiert ist und ein Block 16 Byte ist).
Das lässt 16 Bits für die "Index" -Bits einer Speicheradresse übrig, die verwendet werden können, um zu finden, zu welcher Zeile die Adresse gehört. (Es ist nur eine Division + Rest-Operation, aber binär.)Sie benötigen auch andere Bits: z.B. Sie müssen wissen, ob ein Block tatsächlich gültig ist oder nicht, denn wenn die CPU eingeschaltet ist, enthält sie ungültige Daten. Sie fügen also 1 Bit Metadaten hinzu: das Valid-Bit.
Es gibt noch andere Dinge, über die Sie lernen werden, die für die Optimierung, Synchronisierung usw. verwendet werden, aber das sind die grundlegenden. :)
Ich gehe davon aus, dass Sie die Grundlagen von Tag, Index und Offset kennen, aber hier ist eine kurze Erklärung, die ich in meiner Computerarchitektur-Klasse gelernt habe. Blöcke werden in 64-Byte-Blöcken ersetzt, so dass jedes Mal, wenn ein neuer Block in den Cache gestellt wird, alle 64 Bytes ersetzt werden, unabhängig davon, ob Sie nur ein Byte benötigen. Aus diesem Grund gibt es bei der Adressierung des Caches einen Offset, der das Byte angibt, das Sie vom Block erhalten möchten. Nehmen wir Ihr Beispiel: Wenn nur 16-Bit-Integer geladen wird, sucht der Cache nach dem Block durch den Index, überprüft das Tag, um sicherzustellen, dass es die richtigen Daten ist, und holt dann das Byte gemäß dem Offset. Wenn Sie nun einen anderen 16-Bit-Wert laden, sagen wir mit dem gleichen Index, aber einem anderen Tag, wird der 64-Byte-Block durch den neuen Block ersetzt und die Informationen aus dem angegebenen Offset abgerufen. (angenommen, direkt zugeordnet)
Ich hoffe, das hilft! Wenn Sie weitere Informationen benötigen oder dies immer noch unscharf ist, lassen Sie es mich wissen, ich kenne ein paar gute Seiten, die das gut lehren.
Tags und Links caching operating-system