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?
Antworten:
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:
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.
quelle
if (mem != x) { mem = x; }
stattdessen Code generierenmem = 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.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.
quelle
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.
quelle