Das MESI-Protokoll macht die Speichercaches effektiv unsichtbar. Dies bedeutet, dass Multithread-Programme sich keine Gedanken darüber machen müssen, ob sie die alten Daten lesen oder zwei Kerne in verschiedene Teile einer Cache-Zeile schreiben und die Hälfte der einen und die andere Hälfte zum Hauptspeicher senden.
Dies hilft jedoch nicht bei Lese-Modify-Write-Operationen wie Inkrementieren, Vergleichen und Tauschen und so weiter. Das MESI-Protokoll wird nicht zwei Kerne davon abhalten, den gleichen Speicherblock zu lesen, jeder fügt einen hinzu, und dann schreibt jeder den gleichen Wert zurück und wandelt zwei Inkremente in eins um.
Auf modernen CPUs sperrt das LOCK-Präfix die Cache-Zeile, so dass die Lese-Modifiziere-Schreib-Operation logisch atomar ist. Diese sind zu stark vereinfacht, aber hoffentlich werden sie Ihnen die Idee geben.
entriegelte Schritt:
- Acquire Cache-Zeile, gemeinsam nutzbarer ist in Ordnung. Lesen Sie den Wert.
- Fügen Sie einen Wert zum Lesen hinzu.
- Erwerben Cache-Zeile exklusive (wenn nicht schon E oder M) und sperren Sie es.
- Schreiben Sie den neuen Wert in die Cachezeile.
- Ändern Sie die Cache-Zeile, um sie zu ändern und zu entsperren.
Locked Schritt:
- Acquire Cache-Zeile exklusiv (falls nicht bereits E oder M) und sperren.
- Wert lesen.
- Fügen Sie einen hinzu.
- Schreiben Sie den neuen Wert in die Cachezeile.
- Ändern Sie die Cache-Zeile, um sie zu ändern und zu entsperren.
Beachten Sie den Unterschied? Im entsperrten Inkrement wird die Cache-Zeile wie alle Schreibvorgänge nur während der Schreibspeicheroperation gesperrt. In dem gesperrten Inkrement wird die Cache-Zeile über den gesamten Befehl gehalten, und zwar von der Leseoperation bis zur Schreiboperation und einschließlich während der Inkrementierung selbst.
Außerdem haben einige CPUs andere Dinge als Speichercaches, die Speichersichtbarkeit beeinträchtigen können. Zum Beispiel haben einige CPUs einen Lese-Prefetcher oder einen Posted-Write-Puffer, die dazu führen können, dass Speicheroperationen außerhalb der Reihenfolge ausgeführt werden. Wo es erforderlich ist, wird ein LOCK-Präfix (oder eine äquivalente Funktionalität auf anderen CPUs) auch alles tun, was zu tun ist, um Speicherbetriebsordnungsprobleme zu behandeln.
Betrachten Sie den Unterschied zwischen einem gesperrten und einem entsperrten Inkrement: Wenn zwei Kerne gleichzeitig einen Wert 0 im Speicher inkrementieren, beschließen beide, 1 in den Speicher zu schreiben. Die Cache-Kohärenz verhindert nicht den Verlust eines der Updates. –
@KerrekSB Entschuldigung, ich habe nicht ganz verstanden was du meintest. Würden Sie die Kohärenz nicht zwischenspeichern, um sicherzustellen, dass nur einer der Kerne die Cachezeile besitzt, in die geschrieben wird? Wenn also der zweite Kern die Cacheline verändern würde, während die erste inkrementiert würde, würde MESI das Schreiben verhindern, bis der erste Kern das Inkrement abgeschlossen hatte. – user997112
Inkrementieren ist keine atomare Operation. Zuerst lesen beide Kerne den gleichen Wert (0) von einer sauberen Cache-Zeile. Dann entscheiden beide, den neuen Wert zu berechnen (1). Dann schreiben beide den Wert zurück. Bei dieser Schreibphase hilft die Cache-Kohärenz nicht, da das Schreiben in den Speicher nicht unmittelbar von der Kohärenz beeinflusst wird (nur * Lesen * von verschmutzten Seiten). –