Kann ich erzwingen, cache-Kohärenz, die auf einem multicore x86 CPU?
Die andere Woche, ich schrieb einen kleinen thread-Klasse und ein one-way-message-pipe für die Kommunikation zwischen threads (zwei Rohre pro thread, offensichtlich, für die bidirektionale Kommunikation). Alles hat gut funktioniert auf meinem Athlon 64 X2, aber ich Frage mich, ob ich auf Probleme stoßen, wenn beide threads die gleichen Variablen und die lokale zwischengespeicherte Wert für diese variable auf jedem Kern war out of sync.
Ich weiß, die flüchtigen Schlüsselwort zwingt eine variable zu aktualisieren, aus dem Speicher, aber gibt es eine Möglichkeit auf multicore-x86-Prozessoren zu zwingen, die caches aller Kerne zu synchronisieren? Ist das etwas, was ich brauchen, um über, oder wird flüchtigen und ordnungsgemäße Verwendung von leichten locking-Mechanismen (ich war mit _InterlockedExchange meinen flüchtigen Rohr-Variablen) alle Fälle behandeln, wo ich schreiben möchte "lock-free" code für multicore-x86-CPUs?
Ich bin mir schon bewusst und verwendet haben, Critical Sections, Mutexe, Events, und so weiter. Meistens bin ich Frage mich, ob es gibt x86-Interna, ich bin mir nicht bewusst, welche Kraft oder kann verwendet werden, um zu erzwingen, cache-Kohärenz.
InformationsquelleAutor der Frage Furious Coder | 2009-02-17
Du musst angemeldet sein, um einen Kommentar abzugeben.
volatile
nur Kräfte, Ihren code zu re-Lesen Sie den Wert ab, kann er nicht kontrollieren, wo der Wert ausgelesen. Wenn der Wert war vor kurzem zu Lesen von deinem code, dann wird es wohl in einem cache, in dem Fall flüchtige zwingen wird, es erneut zu Lesen aus dem cache, NICHT aus dem Gedächtnis.Gibt es nicht eine Menge von cache-Kohärenz-Instruktionen in x86. Es gibt prefetch-Anweisungen wie
prefetchnta
aber das hat keinen Einfluss auf die Speicher-Bestellung Semantik. Es implementiert werden, indem der Wert der L1-cache ohne umweltschädliche L2, aber die Dinge sind komplizierter für moderne Intel-designs mit einem großen gemeinsamen inclusive L3-cache.x86-CPUs verwenden eine variation des MESI-Protokoll (MESIF für Intel, MOESI für AMD), um Ihre caches kohärent mit jedem anderen (einschließlich der private L1-caches der anderen Kerne). Ein Kern, der will, schreiben Sie eine cache-Zeile hat, zu zwingen, andere Kerne zu entkräften Ihre Kopie, bevor Sie es ändern kann, seine eigene Kopie aus dem Gemeinsamen Modifizierten Zustand.
Brauchen Sie nicht alle Zaun-Anweisungen (wie MFENCE) zu erzeugen, um Daten in einem thread, und konsumieren Sie es in einem anderen auf x86, weil x86-loads/stores haben acquire/release-Semantik eingebaut. Sie brauchen MFENCE (full-Schranke), um sequentielle Konsistenz. (Eine frühere version dieser Antwort schlug vor, dass
clflush
gebraucht wurde, was nicht korrekt ist).Sie tun müssen, um zu verhindern, dass compile-Zeit der Neuordnungweil C++memory Modell ist schwach bestellt.
volatile
ist eine alte, schlechte Wege, dies zu tun; C++11 std::atomic ist ein viel besserer Weg, um zu schreiben-lock-freien code.InformationsquelleAutor der Antwort SoapBox
Cache-Kohärenz garantiert wird zwischen den Kernen durch das MESI-Protokoll eingesetzt, die von x86-Prozessoren. Sie müssen nur sorgen über die Speicher-Kohärenz beim Umgang mit externer hardware, die möglicherweise Zugriff auf den Speicher, während Daten weiterhin Standortwahl auf cores' - caches. Nicht so Aussehen, wie es Ihrem Fall hier, obwohl, da der text suggeriert, du bist Programmierung im userland.
InformationsquelleAutor der Antwort
Müssen Sie nicht sorgen zu machen über die cache-Kohärenz. Die hardware wird sich darum kümmern. Was Sie brauchen können, um sorgen über performance-Probleme aufgrund von zu dass die cache-Kohärenz.
Wenn core#1 schreibt auf eine variable und core#2 liest, die mit derselben variable, der Prozessor stellen Sie sicher, dass der cache für core#2 aktualisiert. Da eine ganze cache-line (64 Byte) Lesen aus dem Speicher, es wird einige performance Kosten. In diesem Fall ist es unvermeidlich. Dies ist das gewünschte Verhalten.
Das problem ist, dass, wenn Sie mehrere Variablen in der gleichen cache-Zeile, der Prozessor könnte verbringen mehr Zeit, halten die caches synchronisieren, auch wenn die Kerne beim Lesen/schreiben von verschiedenen Variablen innerhalb der gleichen cache-Zeile. Diese Kosten können vermieden werden, indem sichergestellt wird, die Variablen sind nicht in der gleichen cache-Zeile. Dieser Effekt ist bekannt als False-Sharingda Sie zwingt die Prozessoren synchronisieren die Werte von Objekten, die eigentlich nicht zwischen threads gemeinsam genutzt werden.
InformationsquelleAutor der Antwort Ferruccio
Volatil wird es nicht tun. In C++, flüchtige wirkt sich nur auf das, was der compiler-Optimierungen wie das speichern einer Variablen in ein register statt Speicher oder entfernen Sie es ganz.
InformationsquelleAutor der Antwort dsimcha
Du nicht angeben, welchen compiler Sie verwenden, aber wenn du auf windows, werfen Sie einen Blick auf dieser Artikel hier. Werfen Sie auch einen Blick auf die verfügbaren synchronization Funktionen hier. Möchten Sie vielleicht zu beachten, dass im Allgemeinen
volatile
ist nicht genug, zu tun, was Sie wollen, es zu tun, aber unter VC 2005 und 2008, es gibt nicht-standard-Semantik Hinzugefügt werden, fügen Sie stillschweigend Speicher Barrieren rund um lese-und Schreibvorgänge.Wenn Sie wollen, dass die Dinge tragbar sein, wirst du eine viel härtere Straße.
InformationsquelleAutor der Antwort Eclipse
Gibt es eine Reihe von Artikeln, die erklären, moderne Speicher-Architekturen hiereinschließlich Intel Core2 caches und viele weitere moderne Architektur-Themen.
Artikel sind sehr gut lesbar und gut illustriert. Genießen Sie !
InformationsquelleAutor der Antwort davidnr
Gibt es mehrere sub-Fragen in deiner Frage, so werde ich Ihnen Antworten nach meinem besten wissen.
InformationsquelleAutor der Antwort Bartosz Milewski
Folgenden ist ein guter Artikel in Bezug auf die Verwendung
volatile
w/threaded Programme.Flüchtig Fast Nutzlos für Multi-Threaded-Programmierung.
InformationsquelleAutor der Antwort cmcginty
Herb Sutter schien einfach vorschlagendass zwei Variablen sollten sich in separaten cache-Zeilen. Er tut dies in seiner gleichzeitigen Warteschlange mit Polsterung zwischen seine Schlösser und Knoten Zeiger.
Edit: Wenn du mit dem Intel compiler oder GCC verwenden, können Sie die atomic geliefertendie scheinen Ihr bestes zu tun, um die Sitzung des cache, wenn möglich.
InformationsquelleAutor der Antwort greyfade