Gleichzeitigkeits- und Speichermodelle

8

Ich schaue mir dieses Video an Herb Sutter auf GPGPU und die neue C ++ AMP-Bibliothek. Er spricht über Speichermodelle und erwähnt Weak Memory Models und dann Strong Memory Models und ich denke, er bezieht sich auf Lesen / Schreiben usw., bin mir aber nicht sicher.

Google stellt einige interessante Ergebnisse (hauptsächlich wissenschaftliche Arbeiten) zu Speichermodellen auf, aber kann jemand erklären, was ein schwaches Speichermodell ist und was ein starkes Speichermodell und ihre Beziehung zur Nebenläufigkeit ist?

    
Tony The Lion 27.08.2011, 13:42
quelle

4 Antworten

13

Hinsichtlich der Parallelität gibt ein Speichermodell die Einschränkungen für Datenzugriffe und die Bedingungen an, unter denen Daten, die von einem Thread / Core / Prozessor geschrieben wurden, für einen anderen sichtbar werden.

Die Begriffe schwach und strong sind etwas mehrdeutig, aber die grundlegende Prämisse ist, dass ein starkes Speichermodell der Hardware viele Einschränkungen auferlegt, um sicherzustellen, dass sie nur einmal schreibt Thread / Core / Prozessor sind für andere Threads / Cores / Prozessoren in klar definierten Ordnungen sichtbar, während dem Programmierer maximale Freiheit des Datenzugriffs ermöglicht wird.

Auf der anderen Seite legt ein schwaches Modell der Hardware sehr wenig Beschränkungen auf, sondern legt vielmehr die Verantwortung fest, die Sichtbarkeit in den Händen des Programmierers zu gewährleisten.

Das stärkste Speichermodell ist Sequenzielle Konsistenz : Alle Operationen für alle Daten durch alle Prozessoren bilden eine einzige Gesamtbestellung, die von allen Prozessoren vereinbart wird, was mit der Reihenfolge der Operationen auf jedem Prozessor individuell übereinstimmt. Dies ist im Wesentlichen eine Verschachtelung der Operationen jedes Prozessors.

Das schwächste Speichermodell wird der Reihenfolge, in der Prozessoren die Schreibvorgänge des jeweils anderen Systems sehen, keine Einschränkungen auferlegen. Unterschiedliche Prozessoren im selben System können Schreibvorgänge in unterschiedlichen Reihenfolgen sehen, und einige Prozessoren können "veraltete" Daten aus ihrem eigenen Cache für eine lange Zeit nach einem Schreiben derselben Speicheradresse durch einen anderen Prozessor verwenden. Manchmal werden ganze Cache-Zeilen als eine einzige Einheit behandelt, so dass ein Schreiben auf eine Variable in einer Cache-Zeile bewirkt, dass Schreibvorgänge von anderen Prozessoren auf andere Cache-Zeilen, die für den ersten Prozessor noch nicht sichtbar sind, effektiv verworfen werden Die veralteten Werte werden über die Oberseite geschrieben, wenn sie schließlich die Cache-Zeile in den Speicher schreibt. Bei einem solchen Schema muss äußerst vorsichtig vorgegangen werden, um sicherzustellen, dass Daten unter Verwendung expliziter Synchronisationsanweisungen in der richtigen Reihenfolge an andere Prozessoren übertragen werden.

Zum Beispiel wird das Intel x86-Speichermodell allgemein als stärker betrachtet, da es strikte Regeln für die Reihenfolge gibt, in der Schreibvorgänge für andere Prozessoren sichtbar werden, während die DEC-Alpha- und ARM-Prozessoren allgemein als solche gelten schwache Speichermodelle, da Schreibvorgänge von einem Prozessor nur für andere Prozessoren in einer bestimmten Reihenfolge sichtbar sein müssen, wenn Sie in Ihrem Code explizit Bestellanweisungen (Speicherzäune oder Barrieren) eingeben.

Einige Systeme haben Speicher, auf den nur bestimmte Prozessoren zugreifen können. Das Übertragen von Daten zwischen diesen Prozessoren erfordert daher explizite Datenübertragungsanweisungen. Dies ist bei den Cell-Prozessoren der Fall und ist auch bei GPUs häufig der Fall. Dies kann als Extremfall eines schwachen Speichermodells angesehen werden - Daten sind nur für andere Prozessoren sichtbar, wenn Sie die Datenübertragung explizit aufrufen.

Programmiersprachen setzen normalerweise ihre eigenen Speichermodelle auf, was auch immer von den zugrunde liegenden Prozessoren bereitgestellt wird. Zum Beispiel gibt C ++ 0x einen vollständigen Satz von Ordnungseinschränkungen an, die von vollständig entspannter bis zu vollständiger sequenzieller Konsistenz reichen, sodass Sie im Code angeben können, was Sie benötigen. Auf der anderen Seite hat Java einen sehr spezifischen Satz von Ordnungsbeschränkungen, die eingehalten werden müssen und nicht variiert werden können. In beiden Fällen muss der Compiler die gewünschten Constraints in die entsprechenden Anweisungen für den zugrunde liegenden Prozessor übersetzen, was ziemlich aufwendig sein kann, wenn Sie auf einem schwach geordneten Rechner sequentielle Konsistenz anfordern.

    
Anthony Williams 31.08.2011 21:20
quelle
6

Die beiden Begriffe sind nicht klar definiert, und es ist kein Schwarz / Weiß-Ding.

Speichermodelle können extrem schwach, extrem stark oder irgendwo dazwischen sein.

Es bezieht sich im Grunde genommen auf die Garantien über gleichzeitige Speicherzugriffe.

Naiverweise würden Sie erwarten, dass ein Schreibvorgang in einem Thread sofort für alle anderen Threads sichtbar ist. Und Sie würden erwarten, dass Ereignisse in allen Threads in der gleichen Reihenfolge angezeigt werden.

Aber in einem schwächeren Speichermodell kann keiner von beiden halten.

Sequenzielle Konsistenz ist die Bezeichnung für ein Speichermodell, das garantiert, dass Ereignisse in allen Threads in der gleichen Reihenfolge angezeigt werden. Ein Speichermodell, das sequenzielle Konsistenz sicherstellt, ist ziemlich stark.

Eine schwächere Garantie ist kausale Konsistenz: die Garantie, dass Ereignisse nach den Ereignissen beobachtet werden, von denen sie abhängen.

Mit anderen Worten, wenn Sie zuerst einen Wert x auf eine Adresse A schreiben und dann einen zweiten Wert y auf dieselbe Adresse schreiben, dann wird kein Thread jemals lesen Der Wert y nach dem Lesen des Wertes x . Da die beiden Schreibvorgänge dieselbe Adresse haben, würde dies die kausale Konsistenz verletzen, wenn nicht alle Threads die gleiche Reihenfolge hätten. Aber das sagt nichts darüber aus, was mit nicht verwandten Ereignissen passieren soll. Das Ergebnis des Schreibens eines dritten Wertes in eine andere Speicheradresse könnte bei absolut any durch andere Threads beobachtet werden (so können verschiedene Threads Ereignisse in einer anderen Reihenfolge beobachten, anders als unter sequenzieller Konsistenz)

Es gibt viele andere Ebenen der "Konsistenz", einige stärker, einige schwächer und bieten alle Arten subtiler Garantien darüber, worauf Sie sich verlassen können.

Grundsätzlich bietet ein stärkeres Speichermodell mehr Garantien für die Reihenfolge, in der Ereignisse beobachtet werden, und garantiert normalerweise ein Verhalten, das näher an dem liegt, was Sie intuitiv erwarten würden.

Aber ein schwächeres Modell bietet mehr Platz für die Optimierung und insbesondere skaliert es besser mit mehr Kernen (weil weniger Synchronisation erforderlich ist)

Sequenzielle Konsistenz ist im Prinzip frei auf einer Single-Core-CPU, ist auf einem Quad-Core machbar, wäre aber auf einem 32-Core-System oder einem System mit 4 physischen CPUs unerschwinglich teuer. Oder ein Shared-Memory-System zwischen mehreren physischen Maschinen.

Je mehr Kerne Sie haben und je weiter sie voneinander entfernt sind, desto schwieriger ist es sicherzustellen, dass alle Ereignisse in der gleichen Reihenfolge beobachten. So werden Kompromisse gemacht, und Sie begnügen sich mit einem schwächeren Speichermodell, das lockerere Garantien bietet.

    
jalf 27.08.2011 15:17
quelle
4

Ja, Sie haben Recht - der Unterschied zwischen schwachen und starken Speichermodellen ist ein Unterschied in den verfügbaren Optimierungen (Reihenfolge der Lese- / Schreibvorgänge und verwandter Zäune).

  

Sie können ein Speichermodell angeben, indem Sie mit einem sequenziell konsistenten Modell (dem restriktivsten oder stärksten Modell) beginnen und dann angeben, wie Lese- und Schreibvorgänge von einem einzelnen Thread in Bezug aufeinander eingeführt, entfernt oder verschoben werden können

     

In diesem Modell (sequenziell konsistent) ist der Speicher unabhängig von einem der Prozessoren (Threads), die ihn verwenden. Der Speicher ist mit jedem der Threads durch einen Controller verbunden, der Lese- und Schreibanforderungen von jedem Thread zuführt. Die Lese- und Schreibvorgänge aus einem einzelnen Thread erreichen den Speicher in genau der vom Thread angegebenen Reihenfolge, aber sie können auf andere Weise mit Lese- und Schreibvorgängen von anderen Threads verschachtelt werden

Verstehen Sie die Auswirkungen von Low-Lock-Techniken in Multithread-Anwendungen

Es gibt jedoch keine genaue Bindung zwischen starken und schwachen Speichermodellen, es sei denn, Sie betrachten das sequentielle konsistente Modell im Vergleich zu anderen Modellen. Einige von ihnen sind nur stärker / schwächer und daher offener für Optimierungen durch Neuordnung als andere. Beispielsweise ermöglicht das Speichermodell in .NET 2.0 für x86 ein wenig mehr Optimierungen als die Version in .NET 1.1, sodass es als ein schwächeres Modell betrachtet werden kann.

    
Andrey Taptunov 27.08.2011 14:26
quelle
2
  

Google stellt einige interessante Ergebnisse (hauptsächlich wissenschaftliche Arbeiten) zu Speichermodellen auf, aber kann jemand erklären, was ein schwaches Speichermodell ist und was ein starkes Speichermodell und ihre Beziehung zur Nebenläufigkeit ist?

Ein starkes Speichermodell ist eines, bei dem aus der Sicht anderer Kerne Lese- und Schreibvorgänge auftreten, so wie sie im Programm erscheinen und insbesondere in der Reihenfolge, in der sie im Programm erscheinen. Dies wird als sequentielle Konsistenz bezeichnet.

Ein schwaches Speichermodell ist eines, bei dem Speicherausführungen von der CPU geändert werden können, z. nachbestellt. Alle praktischen CPU-Architekturen ermöglichen eine Neuordnung der Befehle.

Beachten Sie, dass Herb Sutter das "starke Speichermodell" verwendet, um atomare Intrinsik nicht neu zu ordnen. Dies ist nicht die allgemein akzeptierte Definition.

    
Jon Harrop 11.01.2015 18:17
quelle