Was ist ein Erinnerungszaun?

Antworten:

115

Um die Leistung zu verbessern, führen moderne CPUs häufig Befehle in der falschen Reihenfolge aus, um das verfügbare Silizium (einschließlich Lese- / Schreibvorgänge im Speicher) maximal zu nutzen. Da die Hardware die Integrität von Anweisungen erzwingt, bemerken Sie dies nie in einem einzelnen Ausführungsthread. Für mehrere Threads oder Umgebungen mit flüchtigem Speicher (z. B. speicherabgebildete E / A) kann dies jedoch zu unvorhersehbarem Verhalten führen.

Ein Speicherzaun / eine Speicherbarriere ist eine Klasse von Anweisungen, die bedeuten, dass Speicherlesevorgänge in der von Ihnen erwarteten Reihenfolge erfolgen. Zum Beispiel bedeutet ein "vollständiger Zaun", dass alle Lese- / Schreibvorgänge vor dem Zaun vor denen nach dem Zaun ausgeführt werden.

Beachten Sie, dass Speicherzäune ein Hardwarekonzept sind. In höheren Sprachen sind wir es gewohnt, mit Mutexen und Semaphoren umzugehen - diese können durchaus mithilfe von Speicherzäunen auf niedriger Ebene implementiert werden, und die explizite Verwendung von Speicherbarrieren ist nicht erforderlich. Die Verwendung von Speicherbarrieren erfordert ein sorgfältiges Studium der Hardwarearchitektur und ist in Gerätetreibern häufiger anzutreffen als Anwendungscode.

Die CPU-Neuordnung unterscheidet sich von Compiler-Optimierungen - obwohl die Artefakte ähnlich sein können. Sie müssen separate Maßnahmen ergreifen, um zu verhindern, dass der Compiler Ihre Anweisungen neu anordnet, wenn dies zu unerwünschtem Verhalten führen kann (z. B. Verwendung des flüchtigen Schlüsselworts in C).

Gwaredd
quelle
26
Ich denke nicht, dass flüchtig genug ist, um die Neuordnung des Compilers zu stoppen. AFAIK stellt nur sicher, dass der Compiler den Variablenwert nicht zwischenspeichern kann. Der Linux-Kernel verwendet eine gcc-Erweiterung ( asm __volatile __ ("" ::: "memory")), um eine vollständige Barriere für die Compileroptimierung zu erstellen.
CesarB
5
wahr, flüchtig ist nicht thread-fähig, aber Sie können es verwenden, um den Compiler daran zu hindern, bestimmte Optimierungen anzuwenden - dies hat nichts mit Zäunen zu
tun
3
(.NET CLR) Flüchtige Lesevorgänge sind Erfassungszäune, Schreibvorgänge sind Freigabezäune. Interlocked Ops sind voll, ebenso wie die MemoryBarrier-Methode.
Luke Puplett
3
Interessante Informationen zum flüchtigen Schlüsselwort in .net finden Sie hier albahari.com/threading/part4.aspx#_NonBlockingSynch Die Website enthält viele nützliche Informationen zum Threading in c #
Bas Smit
developerWorks hat einen guten [Artikel] [1] über das PowerPC-Speichermodell. [1]: ibm.com/developerworks/systems/articles/powerpc.html
Iouri Goussev
17

Kopieren meiner Antwort auf eine andere Frage: Welche Tricks macht ein Prozessor, um Code zu optimieren? ::

Das wichtigste wäre die Neuordnung des Speicherzugriffs.

Ohne Speicherzäune oder Serialisierungsanweisungen kann der Prozessor Speicherzugriffe neu anordnen. Einige Prozessorarchitekturen haben Einschränkungen hinsichtlich der Anzahl der Nachbestellungen. Alpha ist dafür bekannt, das schwächste zu sein (dh dasjenige, das am meisten nachbestellen kann).

Eine sehr gute Behandlung des Themas finden Sie in der Linux-Kernel-Quelldokumentation unter Documentation / memory-barriers.txt .

In den meisten Fällen ist es am besten, Sperrprimitive aus Ihrem Compiler oder Ihrer Standardbibliothek zu verwenden. Diese sind gut getestet, sollten über alle erforderlichen Speicherbarrieren verfügen und sind wahrscheinlich recht optimiert (die Optimierung von Sperrprimitiven ist schwierig; selbst die Experten können sie manchmal falsch verstehen).

CesarB
quelle
Wie beeinflusst es den Ablauf der Nachbestellung? Als Sie sagten Alpha is known for being the weakest, warum weakest? Ist es nicht besser, dass es mehr nachbestellt, so dass es viel schneller ausgeführt wird? (Ich bin kein Alpha-Benutzer, sondern frage nach dem Effekt von very reorderingvs restricted reordering). Was sind die Nachteile der Neuordnung von Chargen (mit Ausnahme des Risikos eines undefinierten Verhaltens, aber ich denke, die meisten modernen CPUs hätten eine gute Neuordnung auflösen und nur eine definierte Neuordnung implementieren müssen, da dies sonst keinen Sinn für die von ihnen getroffene Entscheidung ergibt).
Hirte
8

Nach meiner Erfahrung bezieht es sich auf eine Speicherbarriere , bei der es sich um eine (explizite oder implizite) Anweisung handelt, den Speicherzugriff zwischen mehreren Threads zu synchronisieren.

Das Problem tritt in der Kombination von modernen aggressiven Compilern (sie haben erstaunliche Freiheit, Anweisungen neu zu ordnen, wissen aber normalerweise nichts über Ihre Threads) und modernen Multicore-CPUs auf.

Eine gute Einführung in das Problem ist die Erklärung " Die doppelt überprüfte Sperre ist defekt ". Für viele war es der Weckruf, dass es Drachen gibt.

Implizite vollständige Speicherbarrieren sind normalerweise in Routinen zur Synchronisierung von Plattformthreads enthalten, die den Kern davon abdecken. Für die sperrenfreie Programmierung und Implementierung benutzerdefinierter, leichter Synchronisationsmuster benötigen Sie jedoch häufig nur die Barriere oder sogar nur eine Einwegbarriere.

peterchen
quelle
2

Wikipedia weiß alles ...

Die Speicherbarriere, auch als Membar oder Speicherzaun bekannt, ist eine Klasse von Anweisungen, die eine Zentraleinheit (CPU) veranlassen, eine Ordnungsbeschränkung für Speicheroperationen zu erzwingen, die vor und nach der Barriereanweisung ausgegeben werden.

CPUs verwenden Leistungsoptimierungen, die zu einer Ausführung außerhalb der Reihenfolge führen können, einschließlich Speicherlade- und Speicheroperationen. Die Neuordnung von Speicheroperationen bleibt normalerweise innerhalb eines einzelnen Ausführungsthreads unbemerkt, führt jedoch bei gleichzeitigen Programmen und Gerätetreibern zu unvorhersehbarem Verhalten, sofern sie nicht sorgfältig gesteuert werden. Die genaue Art einer Ordnungsbeschränkung ist hardwareabhängig und wird durch das Speichermodell der Architektur definiert. Einige Architekturen bieten mehrere Hindernisse für die Durchsetzung unterschiedlicher Ordnungsbeschränkungen.

Speicherbarrieren werden normalerweise verwendet, wenn Maschinencode auf niedriger Ebene implementiert wird, der auf Speicher arbeitet, der von mehreren Geräten gemeinsam genutzt wird. Dieser Code umfasst Synchronisationsprimitive und sperrenfreie Datenstrukturen auf Multiprozessorsystemen sowie Gerätetreiber, die mit Computerhardware kommunizieren.

Omar Kooheji
quelle