Gibt es CPUs, die diese mögliche L1-Cache-Schreiboptimierung durchführen?

9

Wenn die CPU mit einem L1-Cache einen Schreibvorgang ausführt, wird normalerweise (vorausgesetzt, die Cache-Zeile, in die geschrieben wird, befindet sich bereits im L1-Cache) der Cache (zusätzlich zum Aktualisieren der Daten) diese Cache-Zeile als fehlerhaft markiert und wird die Zeile mit den aktualisierten Daten zu einem späteren Zeitpunkt ausschreiben.

Eine mögliche Optimierung wäre, den Cache den Inhalt des Schreibvorgangs mit dem vorherigen Inhalt des Caches vergleichen zu lassen. Wenn sie identisch sind, markieren Sie die Zeile nicht als verschmutzt. Da der Cache dadurch gelegentlich Rückschreibungen vermeiden kann, kann ich sehen, wie der CPU-Hersteller dies für die für diese Logik erforderlichen Gates als wertvoll erachtet.

Meine Frage: Gibt es CPUs, die diese Optimierung durchführen?

Hintergrund, warum ich frage: Ich schreibe Code, der konstanten Speicherzugriff benötigt; Das heißt, jemand, der das Verhalten des Caches abhören kann, sollte nicht ableiten können, was ich tue. Einige meiner Zugriffe sind Schreibvorgänge, und auf die offensichtliche Weise, diesen Code zu implementieren, schreiben viele Schreibvorgänge dieselben Daten, die bereits vorhanden sind. Ich muss die Schreibvorgänge ausführen, da die Daten, die ich schreibe, abhängig von den Daten möglicherweise dieselben sind oder nicht, und es wichtig ist, unabhängig davon dieselbe Aktion auszuführen. Wenn die CPU optimiert, indem sie kein "No-Change-Write" schreibt, würde dies bedeuten, dass das Verhalten des Caches abhängig von meiner Tätigkeit variiert, was mein Ziel untergraben würde.

Gibt es also eine CPU, die versucht, Schreibvorgänge auf diese Weise zu optimieren?

Poncho
quelle
11
Es wird gesagt, dass es in der Informatik zwei wirklich schwierige Probleme gibt: die Ungültigmachung des Caches, die Benennung der Dinge und Fehler nacheinander. Dies ist ein Beispiel dafür, warum die erste davon schwierig ist.
Mason Wheeler
@poncho Sie sagen, dass "jemand, der in der Lage ist, das Verhalten des Caches zu hören, nicht in der Lage sein sollte, abzuleiten, was ich tue." Wenn nun einige CPUs diese "Smart Write-Back" -Funktion implementieren, die den Cache nur dann ungültig macht, wenn die Daten wirklich aktualisiert werden, kann man den Verkehr / das Timing beobachten, wenn man in der Speicherhierarchie eine Ebene weiter von der CPU entfernt ist Unterschiede zwischen echten Schreibvorgängen und Dummy-Schreibvorgängen. Ist es das, worüber Sie sich Sorgen machen?
TheCodeArtist
@poncho Auch Ihre eigentliche Frage scheint die Implementierung eines besser privilegierten / sicheren Modus zu sein, bei dem keine Nutzungsinformationen verloren gehen. Vielleicht sollten Sie das fragen? ...
TheCodeArtist
1
@TheCodeArtist: Nun, es wurden kryptografische Sidechannel-Angriffe veröffentlicht, bei denen eine Verschlüsselungsroutine von einem anderen Programm angegriffen werden könnte, das auf einem anderen Kern derselben CPU ausgeführt wird, indem das Angriffsprogramm den gemeinsam genutzten Cache überwacht. Ich glaube, ein solches Programm könnte möglicherweise erkennen, ob L1-Cache-Zeilen geleert wurden, und daher Informationen über das Programm ableiten, an dem ich interessiert bin, wenn die CPU die zur Diskussion stehende Optimierung durchführt. Ich spreche nicht von einem "sicheren Modus", da ich nicht davon ausgehe, dass die CPU oder das Betriebssystem geändert werden können.
Poncho
4
Selbst wenn dies heute zutrifft, ist es morgen nicht garantiert.
pjc50

Antworten:

4

Nach stundenlangem Suchen konnte ich keine CPU finden, die diese spezielle Optimierung verwendet. Die meisten der genannten Optimierungen beziehen sich normalerweise auf Treffer / Fehler bei Lese- / Schreibvorgängen und Datenzugriff:

(Seiten 7 und) https://cseweb.ucsd.edu/classes/fa14/cse240A-a/pdf/08/CSE240A-MBT-L15-Cache.ppt.pdf

Dies bedeutet jedoch nicht, dass diese Optimierung nicht durchgeführt werden kann. Im Allgemeinen ist es möglich, programmgesteuert auf die Größe einer CPU-Cache-Zeile zuzugreifen. Es ist auch möglich, auf aktuelle Werte in Cache-Registern zuzugreifen - dies ist jedoch etwas gefährlich. Wenn Sie zu einem schlechten Zeitpunkt auf die falschen Register zugreifen, können Sie diejenigen manipulieren, die sich auf ein laufendes Programm beziehen. Oder Sie können versehentlich den Inhalt der Zeilen ändern, die Sie lesen möchten.

Abrufen des aktuellen Werts im Cache des Registers

Darüber hinaus erfordern alle theoretischen Lösungen irgendeine Form der Software-Implementierung (Assembler). Das nächste, was ich gefunden habe, bezieht sich auf die ARM-Architektur, die anscheinend eine Cache-Manipulation ermöglicht. Darüber hinaus müssten Sie auch die Größe einer Cache-Zeile für Ihre gewünschte CPU kennen. Sie können den Cache-Inhalt sorgfältig in zeilengroßen Schritten an einer sekundären Stelle im Speicher lesen und ihn mit Daten vergleichen, die in die Register (oder in diesem Fall L1-Cache-Zeilen) geschrieben werden sollen.

Lesen Sie den Inhalt des CPU-Cache

Von dort aus könnten Sie ein softwarebasiertes System entwickeln, das identische Umschreibungen verhindert. Dies ist zwar etwas vereinfacht, aber so, weil die Lösung für jede vorhandene CPU anwendbar sein muss.

Eine andere Möglichkeit, die ich im Zusammenhang mit der Cache-Kohärenz gefunden habe:

Relevante Passage aus einem Wikipedia-Artikel über Acche-Kohärenz

Der Hauptpunkt, der meine Aufmerksamkeit in Bezug auf dieses Problem auf sich zog, war die Beschreibung von Snarfing:

Dies ist ein Mechanismus, bei dem ein Cache-Controller sowohl Adresse als auch Daten überwacht, um zu versuchen, seine eigene Kopie eines Speicherorts zu aktualisieren, wenn ein zweiter Master einen Speicherort im Hauptspeicher ändert. Wenn ein Schreibvorgang an einem Speicherort beobachtet wird, von dem ein Cache eine Kopie hat, aktualisiert der Cache-Controller seine eigene Kopie des Speicherorts mit den neuen Daten.

Mit anderen Worten, es gibt möglicherweise bereits Mechanismen. Es ist nur so, dass sie möglicherweise nicht für die von Ihnen vorgeschlagene Optimierung verwendet werden. Sie müssten eine Software implementieren, die den Lese- / Schreibvergleich durchführt.

Gemeinschaft
quelle
Es ist auch möglich, auf aktuelle Werte in Cache-Registern zuzugreifen - dies ist jedoch etwas gefährlich. Huh, das macht keinen Sinn. Meinen Sie CPU-Register? Vom Compiler generierter oder handgeschriebener ASM-Code verwendet Register, um Werte zu speichern, mit denen er arbeitet ...
Peter Cordes
Wenn Sie versuchen, dies in Software zu implementieren, muss der Compiler if (mem != x) { mem = x; }stattdessen Code generieren mem = x;. Dies ist nur manchmal eine Optimierung für gemeinsam genutzte Cache-Zeilen in einem Multithread-Programm, da das Schreiben das Lesen anderer Threads beeinträchtigt.
Peter Cordes
1
"snarfing" hat damit nichts zu tun. Es ist nur passives Schnüffeln. CPU-Caches verwenden MESI, damit sie kohärente Rückschreib-Caches haben können.
Peter Cordes
@ PeterCordes Wenn Sie meine Antwort als unangenehm empfinden, entschuldige ich mich. Es scheint jedoch, dass Sie in dieser Angelegenheit mehr Einsicht haben als ich. Warum also nicht die Frage selbst beantworten? Meine Antwort war offensichtlich unzureichend für Ihre Standards ...
3

Das Schreiben in den L1-Cache ist eine sehr, sehr zeitkritische Operation.

Das Zurückschreiben genau derselben Daten scheint eher selten zu sein. Eine Optimierung, die die Dinge in diesem speziellen Fall beschleunigt, wird insgesamt nicht viel Geschwindigkeit bringen.

Andererseits erfordert diese Optimierung einen Vergleich von alten und neuen Daten bei jedem einzelnen Schreibvorgang in den Cache-Speicher. Was das noch schlimmer macht, ist, dass es erforderlich ist, dass die zu schreibenden Daten zum Zeitpunkt des Schreibens tatsächlich verfügbar sind!

Dies ist bei einer modernen CPU normalerweise nicht der Fall. Die zu schreibenden Daten können beispielsweise noch berechnet werden. Der Cache kann weiterhin ausgeführt werden, die Cache-Zeile bei Bedarf laden, die Cache-Zeile als geändert markieren usw., noch bevor die Berechnung abgeschlossen ist. Die gesamte Buchhaltung kann bereits durchgeführt werden, mit Ausnahme der tatsächlichen Änderung der Cache-Zeile. Wenn Sie neu geschriebene Ergebnisse und alte Cache-Zeilendaten vergleichen möchten, ist dies nicht möglich.

Wenn Sie beispielsweise C-Code haben, ist a [i] = x / y; Die Ausführung der Division x / y dauert auf den meisten CPUs außerordentlich lange. Der größte Teil der Arbeit, die zum Speichern des Ergebnisses in einem [i] erforderlich ist, wurde jedoch lange vor dem Ende der Teilung ausgeführt. Das einzige, was fehlt, ist das Verschieben von acht Ergebnisbytes in die Cache-Zeile. Ein Vorgang, bei dem die Cache-Zeile geleert wird, wartet automatisch, bis die Teilung abgeschlossen ist. Eine Operation, die ein [i] liest, wird wahrscheinlich umgeleitet, um das Ergebnis direkt vom Teiler zu erhalten.

gnasher729
quelle
Ein Cache, der MESI für die Kohärenz verwendet, kann die RFO weiterhin ausführen. Wenn die Daten jedoch nach ihrer Fertigstellung mit denselben verglichen werden, belassen Sie die Zeile im Status "Exklusiv" anstelle von "Geändert". Der wahre Grund, warum es in der Hardware nicht gemacht wird, ist, dass es zusätzliche Cache-Lesevorgänge kostet, wenn die Daten in den Cache übertragen werden, und eine Art atomare Lese- / Vergleichs- / Schreibzyklen (mit optionaler Einstellung des Dirty-Bits) erfordern würde, die es für a saugen lassen Pipeline-Implementierung.
Peter Cordes
1

Eine mögliche Optimierung wäre, den Cache den Inhalt des Schreibvorgangs mit dem vorherigen Inhalt des Caches vergleichen zu lassen. Wenn sie identisch sind, markieren Sie die Zeile nicht als verschmutzt

Verdoppelt eine solche Optimierung nicht die Zeit, die die CPU benötigt, um etwas in den Cache zu schreiben? Denn jedes Schreiben in der Cache-Zeile wird jetzt von einer Vergleichsoperation begleitet, die nicht kostenlos ist.

Tatsächlich hängt die Optimierung jetzt von dem sehr vagen Faktor ab: Wie oft schreibt eine durchschnittliche Software ihren zwischenspeicherbaren Speicher mit denselben Daten neu.

Vladislav Rastrusny
quelle
Dieser Vergleich würde innerhalb der CPU-Logik implementiert. Es würde keine zusätzliche CPU-Operation erfordern, aber die Signalzeit könnte sich erhöhen, was ein Problem sein könnte oder nicht.
Ziggystar
@ziggystar Nun, ich bin kein Hardware-Meister, aber ich habe mich an den Gedanken gewöhnt, dass alles mit Kosten verbunden ist. Dies gilt auch für den Vergleich der Operation mit der Cache-Zeile. Es könnte schnell gehen. Das kostet aber immer noch. Und ich denke, die Implementierer haben beschlossen, es nicht zu bezahlen. Kann auch nach einigem Nachdenken und Messen sein.
Vladislav Rastrusny
1
Aber Sie sprechen von Zeit, in der die Kosten möglicherweise nur eine Erhöhung der Anzahl der Tore sind.
Ziggystar
1
@ziggystar: Das sind nicht nur mehr Tore. Wenn Daten an den Cache gesendet werden, kann der Prozess des Sendens der Daten normalerweise die Cache-Zeile als geändert markieren. Bei dieser "Optimierung" müssen sowohl die alten als auch die neuen Daten diese Gatter passieren, was zu einer gewissen Verzögerung führt, und nur dann kann der Cache ungültig gemacht werden. Sie müssen dies alles in einem Prozessorzyklus zusammenfassen, andernfalls dauert das Schreiben in eine Cache-Zeile plötzlich zwei Zyklen. Um die Sache noch komplizierter zu machen, überlegen Sie, was passiert, wenn ich acht aufeinanderfolgende Wörter in eine Cache-Zeile schreibe.
Gnasher729
1
Und jeder dieser Schreibvorgänge verzögert die Entscheidung, ob die Cache-Zeile geändert wird. Wenn also der zweite Schreibvorgang stattfindet, weiß die Cache-Zeile (noch) nicht, ob sie geändert wurde oder nicht. Das wird spaßig.
Gnasher729