Erhöhen der Cache-Zeilengröße, wenn Cache und RAM nicht asynchron arbeiten

Ich möchte ein Prozessordesign verbessern. Es hat einen einfachen, direkt zugeordneten Cache, und ich möchte die Trefferquote verbessern. Ich habe daran gearbeitet, die Cache-Zeilengröße von einem Datenwort auf vier zu erhöhen, aber da derzeit alle Zugriffe auf den Cache und das RAM blockieren (ich meine, dass der Betrieb der gesamten CPU blockiert ist, wenn sie auf einen Datenlesevorgang wartet oder schreiben), denke ich, dass ich lediglich die Verzögerung verschiebe, die für den Zugriff auf den RAM erforderlich ist, bis zu dem Moment, in dem Daten in derselben Cacheline benötigt werden. Wenn ich richtig liege, wird der Prozessor dadurch nicht schneller ausgeführt (und wahrscheinlich nur langsamer, da mehr Daten zwischen Cache und RAM übertragen werden).

Ist das so oder übersehe ich etwas?

Antworten (5)

Indem Sie die Aktivität des Speichers nicht von der Aktivität der CPU entkoppeln, werfen Sie den größten Teil des Vorteils eines Caches weg.

Aber basierend darauf, wie Sie Ihr System bisher beschrieben haben, scheint Ihre Analyse richtig zu sein: Durch Erhöhen der Zeilengröße werden einige der Daten tatsächlich vorab abgerufen, dies führt jedoch zu keinem Leistungsgewinn. Tatsächlich könnte dies zu einem leichten Leistungsverlust führen, wenn die vorab abgerufenen Daten nie wirklich verwendet werden – die Zeit, die für das Abrufen aufgewendet wurde, war einfach verschwendet.

Ich kann sehen, dass. Die Sache ist, dass ich ein bestehendes Design verbessere, es ist nicht mein eigenes. Also hoffte ich, dass eine Erhöhung der Cacheline-Größe mir eine bessere Trefferquote geben würde. Aber anscheinend muss ich mir etwas anderes einfallen lassen ... Ich könnte die Aktivitäten entkoppeln, aber ich fürchte, das wird zu viel Aufwand für die kurze Zeit, die mir bleibt.
Der größte Vorteil eines Caches liegt in einem Cache-Treffer. Beispielsweise ist das Anhalten eines Zyklus (für einen 2-Zyklen-Cache-Trefferzugriff) weniger als das Anhalten von acht Zyklen für einen Speicherzugriff. Zulassen, dass nicht abhängige Anweisungen fortfahren (z. B. unter Verwendung einer Anzeigetafel oder sogar eines Ladeverzögerungsschlitzes <Expletiv gelöscht>) verbessert die Leistung, aber typischerweise ist die Speicherlatenz wesentlich höher und die Speicherbandbreite wesentlich niedriger als die Cache-Latenz und -Bandbreite.

Es ist nicht klar, ob Sie daran denken, von einem direkt abgebildeten N x 1-Wort-Cache zu einem (zum Beispiel) N/2 x 2-Wort-DM oder zu einem N x 2-Wort-DM-Cache zu wechseln. Ersteres könnte den sequentiellen Zugriff ein wenig verbessern, da das zweite Wort in einer Zeile als Prefetch-Puffer fungiert. Die zweite Alternative wird die Trefferquote deutlich verbessern, aber hauptsächlich, weil die Cache-Größe verdoppelt wurde.

Der Leistungsvorteil einer größeren Cache-Blockgröße hängt von der Bandbreite und Latenz des Hauptspeichers und der Arbeitslast ab. Wenn Speicherlatenz und Bandbreite relativ hoch sind (z. B. das erste Wort ist in 8 Prozessorzyklen und ein zusätzliches Wort in jedem Zyklus verfügbar), dann, wenn die Arbeitslast sogar die Hälfte des Cache-Blocks verwendet, bevor er entfernt wird, dann ein Block mit vier Wörtern erhöht die Leistung (Abwürgen nur für 11 Zyklen statt 16). (Da viele Speichertechnologien Burst-Beschränkungen haben, könnte der Vorteil geringer sein, wenn der Speichercontroller über einen Puffer verfügt [daher könnten sequentielle Zugriffe im Puffer treffen, ohne die Strafe für den vollen Speicherzugriff zu erleiden] oder größer, wenn die Fehlschläge zu verschiedenen Speicherblöcken gehören und die Verwendung des vollen Bursts erhöht die effektive Speicherbandbreite].)

Wenn der Cache zurückgeschrieben wird, müssen die zusätzlichen Kosten für die Räumung berücksichtigt werden. Wenn beispielsweise 50 % der Wörter unsauber sind, dann würde sich der durchschnittliche Stillstand (für die zwei Zugriffe, die im Durchschnitt im 4-Wort-Block getroffen werden) von 16 Zyklen auf 20 Zyklen und von 11 Zyklen auf 19,25 Zyklen (75 % der Blöcke schmutzig wäre, da die Hälfte der verwendeten Wörter schmutzig sind und die Hälfte der Wörter in einer Cache-Zeile verwendet werden).

Ein Writeback-Cache mit Einzelwortblöcken müsste den Speicher auch nicht für Ganzwort-Schreibvorgänge bei einem Cache-Fehltreffer lesen.

(Writethrough No-Allocate hat einige Vorteile für direkt zugeordnete Caches, wenn ein Schreibpuffer vorhanden ist. Die Kombination eines Schreibpuffers und eines Opfer-Cache kann nützlich sein.)

In einem direkt zugeordneten Cache erhöht die Erhöhung der Blockgröße auch die Konfliktfehlerrate. Wie signifikant dies sein wird, hängt von der Arbeitslast (und sogar von der Datenzuordnung) ab.

Andere mögliche Cache-Verbesserungen umfassen die Bereitstellung eines Opfer-Cache (effektiv ein winziger L2-Cache), die Verwendung einer höheren Assoziativität (Wegvorhersage könnte verwendet werden, um eine direkt zugeordnete Geschwindigkeit bei korrekten Vorhersagen bereitzustellen) und die Bereitstellung eines Prefetch-Puffers. Wenn die Speicherlatenz signifikant ist, müssen nicht viele Treffer in einem Opfer-Cache oder Vorabrufpuffer vorhanden sein, um die Verzögerung des Speicherzugriffs zu kompensieren. (Das spekulative Zugreifen auf den Speicher bei einem Fehlschlag vor dem Prüfen des Opfer-Cache/Prefetch-Puffers würde die Latenz für Fehlschläge in diesen Hilfs-Caches verringern, aber es könnte die Latenz erhöhen, wenn auf einen Treffer im Opfer-Cache unmittelbar ein Opfer-Cache-Fehlschlag folgt, da der zweite Zugriff dies möglicherweise tun muss Warten Sie, bis der erste zu verwerfende Speicherzugriff abgeschlossen ist, bevor Sie einen eigenen starten.)

Eine weitere Möglichkeit sind spezialisierte Caches. Wenn zum Beispiel Stapelzugriffe aus dem Rest des Datencaches herausgefiltert werden können, würden Konfliktfehltreffer reduziert, während die Einfachheit von direkt abgebildeten Caches beibehalten wird.

Übrigens profitieren einige Formen der Wegvorhersage von Cache-Blöcken, die größer als das Wort sind, weil sie die Referenzlokalität ausnutzen können.

Der größte Vorteil einer größeren Cache-Zeilengröße besteht darin, dass die Komplexität eines Cache-Controllers häufig hauptsächlich mit der Größe des Tag-Puffers zusammenhängt, der wiederum von der Anzahl der Zeilen gesteuert wird. Das Verdoppeln der Größe jeder Zeile verdoppelt somit die Informationsmenge, die mit einem Tag-Puffer einer gegebenen Größe zwischengespeichert werden kann. Ohne die Kosten wäre eine Verdoppelung der Größe jeder Cache-Zeile oft schlechter als doppelt so viele Cache-Zeilen. Wenn jedoch das Vervierfachen der Größe jeder Cache-Zeile (bei gleicher Anzahl) genauso viel kosten würde wie das Verdoppeln der Anzahl (bei gleicher Größe), ist es möglich, dass ersteres mehr "Knall fürs Geld" bietet. .

Wenn man versucht, aus größeren Cache-Zeilen eine gute Leistung zu erzielen, sollte man im Allgemeinen ein paar Bits für jede adressierbare Einheit innerhalb eines Wortes haben, die angibt, ob diese Einheit leer, vorhanden und sauber ist (übereinstimmend mit dem, was sich im RAM befindet) oder vorhanden und dirty (gilt nur für Write-Back-Caches). Wenn irgendwelche Cache-Zeilen nicht vollständig gefüllt sind, kann es nützlich sein, ihre Inhalte aus dem RAM zu Zeiten zu holen, wenn der Speicherbus sonst im Leerlauf wäre, aber Abrufen, an denen die CPU interessiert ist, sollte Vorrang vor denen gegeben werden, die es nicht sind.

Ein Vorteil von Write-Through-Caches gegenüber Write-Back besteht übrigens darin, dass sich beliebig viele Geräte mit Write-Through-Caches den Bus teilen können, ohne dass irgendein Code etwas über die Caches von irgendjemandem wissen muss; Alles, was notwendig ist, um die Kohärenz aufrechtzuerhalten, ist Logik, um alle Zeilen ungültig zu machen, die von externen Zugriffen getroffen werden. Im Gegensatz dazu ist es bei der Verwendung eines Writeback-Cache erforderlich, dass Geräte nachverfolgen, dass Daten in den Caches anderer Geräte gespeichert sind, um sicherzustellen, dass jedes Gerät, das einen Block in seinem Cache hat, benachrichtigt wird, wenn jemand anderes ihn ändert .

Erhöhen der Cache-Line-Größe von einem Datenwort auf vier ... Verschieben der Verzögerung, die zum Zugriff auf den RAM erforderlich ist, auf den Moment, in dem irgendwelche Daten in derselben Cache-Line benötigt werden. ... dadurch wird der Prozessor nicht schneller ausgeführt (und wahrscheinlich nur langsamer, da mehr Daten zwischen Cache und RAM übertragen werden).

Wenn der Prozessor die abgerufenen "zusätzlichen" Daten nicht benötigt, haben Sie Recht; Die Zeit, die zum Abrufen dieser zusätzlichen Daten aufgewendet wird, wird verschwendet, wodurch der Prozessor langsamer wird.

Wenn der Prozessor jedoch die abgerufenen "zusätzlichen" Daten benötigt , gibt es mehrere Möglichkeiten, wie größere Cache-Zeilen den Prozessor schneller machen können (mit einer festen Datenmenge im Cache).

Jedes bestimmte Benchmark-Programm, das wiederholt mit einer Vielzahl von Cache-Zeilengrößen (und einer festen Datenmenge im Cache) getestet wird, gibt Ihnen eine bestimmte Cache-Zeilengröße, die das Optimum für dieses bestimmte Benchmark-Programm ist – aber leider anders Benchmark-Programme haben unterschiedliche optimale Cache-Zeilengrößen. Programme, die Bytes quasi zufällig lesen, wie ARC4, bevorzugen normalerweise kürzere Cache-Zeilen. Programme, die große Datenblöcke mehr oder weniger sequentiell lesen, bevorzugen normalerweise größere Cache-Zeilen. Es ist ein Kompromiss.

Lesen der gleichen Daten in kürzerer Zeit

  • Alle DRAMs und die meisten anderen Speicher lesen Daten sequentiell schneller als zufällige Lesevorgänge. Wenn die CPU jetzt Byte 1000 lesen muss, dann Byte 7007 und dann 1001, obwohl Sie immer noch die gleiche Anzahl von Lesespeicherzyklen haben, egal wie Sie die Lesevorgänge mischen, dauert es oft weniger Zeit, um (a ) die Bytes 1000 und 1001 hintereinander in einem sequentiellen Modus und dann 7007 lesen, als (b) zufällige Lesevorgänge durchzuführen.

  • Wenn Sie einen schmalen Speicherdatenbus haben, der mehrere Speicherzyklen benötigt, um eine Cache-Zeile zu füllen, kann ein intelligenter Cache das gewünschte Byte zuerst aus dem Speicher lesen, dieses an die CPU weiterleiten und dann den Rest der Cache-Zeile mit "extra " Daten. Der erste Lesevorgang dauert genauso lange wie ein Small-Cache-Line-System. In Fällen, in denen die CPU parallel zum Cache-Laden vollständig aus dem Cache laufen kann, ist ein späteres Lesen der vorab abgerufenen Daten schneller.

Mehr Daten in der gleichen Zeit

Wenn Sie einen breiten Speicherdatenbus haben oder zu einem solchen wechseln können (zum Beispiel haben alle Intel-Prozessoren, die in den LGA-2011-Sockel passen, 256 Datenpins, die mit 256 Datenleitungen auf dem Motherboard verbunden sind – LGA-2011-Sockel-Datenblatt, Abschnitt 6.1 )

  • Wenn Sie eine große Cache-Zeile auf einmal lesen können, dauert das Lesen dieser gesamten Cache-Zeile genauso lange wie das Lesen eines einzelnen Bytes. Sie können also genauso gut die gesamte Cache-Zeile zwischenspeichern, da sie selbst im schlimmsten Fall nicht langsamer läuft, da die CPU gelegentlich einige dieser "zusätzlichen" Daten später benötigt und dann nicht warten muss.
  • Wenn Sie eine große Cache-Zeile auf einmal schreiben können und einen Write-Back-Cache verwenden, dauert das Schreiben dieser breiten Cache-Zeile genauso lange wie das Schreiben eines einzelnen Bytes oder eines vollen Registers. Sie können also genauso gut eine breite Cache-Zeile verwenden, da sie im schlimmsten Fall nicht langsamer läuft, da der breite Cache gelegentlich "Schreibvorgänge kombinieren" und die gesamte Cache-Zeile auf einmal in einem Speicherzyklus ausschreiben kann, anstatt in Stücken über 2 oder mehr getrennte Speicherzyklen.

Weniger Daten lesen

  • Wie Wouter van Ooijen betonte, wenn Sie tatsächlich die Datenmenge in Ihrem Cache erhöhen, indem Sie dieselben Tag-Bits beibehalten, aber die Cache-Zeilengröße erhöhen, erhöht dies tendenziell die Trefferrate, wodurch das System in fast allen Fällen schneller wird.