2015-04-26 4 views
8

Was ist der Zweck des x86 LOCK-Präfixes, wenn das MESI-Protokoll verhindert, dass andere Kerne auf "exklusiv" -eigene Daten schreiben?LOCK-Präfix vs MESI-Protokoll?

Ich bin ein wenig verwirrt zwischen dem, was LOCK bietet und was MESI bietet?

Ich verstehe, das MESI-Protokoll ist über die Gewährleistung der Kerne alle sehen einen konsistenten Zustand des Speichers, aber wie ich verstehe, verhindert es auch Kerne aus dem Speicher zu schreiben, die anderen Kern bereits schreibt?

+2

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. –

+0

@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

+7

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). –

Antwort

-1

Ja, du verwirrst zwei verschiedene Dinge. Das MESI-Protokoll ist ein Cache-Kohärenz-Protokoll, das sicherstellt, dass jeder Kern/Prozessor bei Anforderung die aktuellsten Daten aus dem Cache (oder Speicher) anderer Prozessoren erhält. Wenn eine Cacheline im "E" -Zustand ist, teilt dies dem anfordernden Prozessor mit, dass ein (und nur ein) anderer Prozessor eine Kopie dieser Zeile hat. Das ist alles, was es tut; der Status 'E' verhindert auf keinen Fall den Zugriff des anfordernden Prozessors auf die Daten; es gibt nur die Tatsache an, dass nur ein Prozessor eine Kopie der Daten hat (und diese Kopie ist auch konsistent mit dieser im Speicher). Wenn also ein Kern die Daten anfordert, die sich im 'E'-Zustand befinden, erhält der Kern eine Kopie davon. Die andere Kopie, die in 'E' war, wird geändert, je nachdem, ob der Kern die Kopie zum 'Schreiben' oder 'Lesen' anfordert. Wenn es zum Schreiben angefordert wird, wird die alte Kopie ungültig ('I' Zustand) und wenn es zum Lesen ist, wird die alte Kopie in den freigegebenen 'S' Zustand versetzt.

+0

Sie haben die Funktionalität des LOCK-Präfixes falsch erhalten. Zwei simultanen Schreibvorgängen schadet nichts - mit oder ohne LOCK, du wirst einen von ihnen sehen und es ist willkürlich was. –

+0

@DavidSchwartz Danke David für den Kommentar, ich entfernte diesen Teil der Antwort. Übrigens war mein Kommentar zu dem LOCK-Präfix, das beim Implementieren des gegenseitigen Ausschlusses verwendet wurde, korrekt. Was noch wichtiger ist, die Reihenfolge der Schreibvorgänge kann NICHT beliebig sein, wie Sie erwähnt haben, und muss dem Speicher konsistent Modell der Architektur folgen; andernfalls ist der Speicher nicht konsistent (aus Sicht des Programms und des Programmierers). – waleed

3

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:

  1. Acquire Cache-Zeile, gemeinsam nutzbarer ist in Ordnung. Lesen Sie den Wert.
  2. Fügen Sie einen Wert zum Lesen hinzu.
  3. Erwerben Cache-Zeile exklusive (wenn nicht schon E oder M) und sperren Sie es.
  4. Schreiben Sie den neuen Wert in die Cachezeile.
  5. Ändern Sie die Cache-Zeile, um sie zu ändern und zu entsperren.

Locked Schritt:

  1. Acquire Cache-Zeile exklusiv (falls nicht bereits E oder M) und sperren.
  2. Wert lesen.
  3. Fügen Sie einen hinzu.
  4. Schreiben Sie den neuen Wert in die Cachezeile.
  5. Ä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.

+0

"Das MESI-Protokoll wird nicht zwei Kerne davon abhalten, den gleichen Speicherblock zu lesen ... und zwei Inkremente in eins umzuwandeln." Ich bin verwirrt von dieser Aussage, da sie im Widerspruch zu dem steht, was Paul McKenney [in diesem Artikel] schreibt (http://www.puppetmastertrading.com/images/hwViewForSwHackers.pdf). Zum Beispiel werden die MESI-Übergänge (e) und (f) auf Seite 5 des Artikels durch RMW-Operationen verursacht. Wenn zwei CPUs gleichzeitig versuchen, die gleiche Cache-Zeile ungültig zu machen, wird es nach dem Artikel gelingen, die Cache-Zeile in den M-Zustand vor dem anderen zu setzen. –

+0

@ void-pointer Ich bin mir nicht sicher, was ich dir sagen soll, außer meine Antwort noch einmal zu lesen. Nehmen wir an, zwei CPUs machen ein Inkrement. Beide lesen, beide erhöhen sich, dann versuchen beide zu schreiben. Wie verhindert die Tatsache, dass ein Schreibvorgang vor dem anderen auftritt, ein verlorenes Inkrement? Natürlich nicht. Sie müssen die Cache-Zeile während des Inkrements sperren, und das ist, was das LOCK-Präfix tut. Transition (e) ist eine atomare Read-Modify-Write-Operation, und genau darum stellte sich die Frage, warum wir brauchen. Und die Antwort ist, dass die Reihenfolge der Schreibvorgänge nicht ausreicht. –

+0

Ich entschuldige mich für die dummen Fragen - ich versuche, mehr über Cache-Kohärenz zu lernen. Nach meinem Verständnis muss eine CPU eine Cache-Zeile im M-Zustand haben, um sie zu modifizieren, und genau eine CPU kann eine bestimmte Cache-Zeile gleichzeitig im M-Zustand haben. Ich sehe also nicht, wie beide CPUs gleichzeitig die gleiche Cachezeile inkrementieren könnten. Wenn zwei CPUs den RMW gleichzeitig versuchen, dann wird (nach meinem Verständnis) man "gewinnen" und den anderen zwingen, seine Kopie der Cache-Zeile ungültig zu machen. Der Verlierer müsste dann einen Lese-Ungültigmachen ausgeben, um Exklusivität zu erlangen, bevor sein RMW ausgeführt wird. –