2012-04-11 9 views
19

Ich habe gelesen, dass INC-Anweisung von x86 nicht atomar ist. Meine Frage ist, wie kommt es? Angenommen, wir inkrementieren eine 64-Bit-Ganzzahl auf x86-64, können wir dies mit einer Anweisung tun, da die INC-Anweisung sowohl mit Speichervariablen als auch mit Register arbeitet. Wie kommt es, dass es nicht atomar ist?Wie kommt es, INC-Anweisung von x86 ist nicht atomar?

+3

Nun, es ist _ atomic_, wenn Sie es mit LOCK voranstellen. Normalerweise ist das aber nicht das, was man will, weil es ziemlich teuer ist. Daher müssen Sie explizit angeben, was Sie wollen. – Damon

+0

ein Wort: Pipelines –

+4

Atomic bedeutet nicht, dass es eine Anweisung ist, es bedeutet, es ist eine unteilbare Aktion. Und 'inc' mit einem Speicheroperanden ist das nicht, jedenfalls nicht standardmäßig. – harold

Antwort

18

Warum sollte es sein? Der Prozessorkern muss immer noch den am Speicherort gespeicherten Wert lesen, dessen Inkrement berechnen und dann zurückspeichern. Es gibt eine Latenz zwischen dem Lesen und dem Speichern, und in der Zwischenzeit könnte eine andere Operation diesen Speicherort beeinflusst haben.

Auch bei Out-of-Order-Ausführung sind Prozessorkerne "intelligent" genug, um nicht über ihre eigenen Anweisungen zu stolpern und sind nicht dafür verantwortlich, diesen Speicher in der Zeitlücke zu modifizieren. Ein anderer Kern könnte jedoch einen Befehl ausgegeben haben, der diesen Ort ändert, eine DMA-Übertragung könnte diesen Ort beeinflusst haben, oder andere Hardware hat diesen Speicherort irgendwie berührt.

+2

Sie sollten ein wenig klarer darüber sein, was "eine andere Operation" bedeutet. Sicherlich kann keine andere Operation auf demselben CPU-Kern stattfinden, nur auf anderen Kernen/CPUs oder anderer Hardware, die auf dem Speicherbus herumfummelt. –

+1

Die Post wurde aktualisiert. – Kaganar

1

Sie wirklich keine garantierte atomare Operation wollen, wenn Sie es brauchen, von Agner Fog ‚s Software optimization resources: instruction_tables.pdf (1996-2017):

Anleitung mit einem LOCK-Präfix eine lange Latenzzeit haben, die hängt von der Cache-Organisation und möglicherweise von der RAM-Geschwindigkeit ab. Wenn mehrere Prozessoren oder Kerne oder Geräte mit direktem Speicherzugriff (DMA) vorhanden sind, sperren alle gesperrten Befehle eine Cache-Zeile für exklusiven Zugriff, was RAM-Zugriff beinhalten kann. Ein LOCK-Präfix kostet in der Regel mehr als einhundert Taktzyklen, selbst bei Einprozessor-Systemen . Dies gilt auch für den XCHG-Befehl mit einem Speicheroperanden.

+1

Diese Information ist sicherlich veraltet; Ein gesamter Mutex-Sperr-/Entsperrzyklus dauert weniger als 90 Zyklen auf einer Maschine, die ich getestet habe, und umfasst mehrere Sperren-Präfix-Operationen und den rdtsc-Overhead. Testen mit einem einzigen Lock-Inc-Befehl zwischen Rdtsc, war ich nicht in der Lage, es zu messen, die Zeit (Zeit nop) nimmend. Bei modernen CPUs scheint das Sperrpräfix die Zeit überhaupt nicht zu erhöhen, es sei denn, der Speicher wird gegenwärtig mit anderen Kernen geteilt. –

+0

@R .. - x86-64 ist seit 2003 verfügbar, also ist es wahrscheinlich eine pauschale Aussage. Ich frage mich, wie es sich auf einen ausstehenden Unterbrechungs-/ctx-Schalter auswirken würde. –

+3

@R .. Nun, weniger als 90 und mehr als 100 sind nicht so weit auseinander :-) – hirschhornsalz

18

Moderne x86-Prozessoren als Teil ihrer Ausführungspipeline "kompilieren" x86-Befehle in eine untergeordnete Reihe von Operationen; Intel nennt diese uOps, AMD rOps, aber was es läuft darauf ist, dass bestimmte Art von einzelnen x86 Anweisungen von den eigentlichen Funktionseinheiten in der CPU als mehrere Schritte ausgeführt werden.
Das bedeutet zum Beispiel, dass:

INC EAX 

als ein einzigen „Mini-op“ wie uOp.inc eax ausgeführt wird (lassen Sie mich es so nennen - sie sind nicht ausgesetzt).
Für andere Operanden die Dinge anders aussehen, wie:

uOp.load tmp_reg, [ EAX ] 
uOp.inc tmp_reg 
uOp.store [ EAX ], tmp_reg 

und deshalb nicht ausgeführt atomar:

INC DWORD PTR [ EAX ] 

die Low-Level-Zersetzung obwohl aussehen würde mehr. Wenn Sie andererseits Präfix sagen, LOCK INC [ EAX ], das wird sagen, die "Kompilieren" Stufe der Pipeline auf eine andere Weise zu zerlegen, um sicherzustellen, dass die Atomarität Anforderung erfüllt ist.

Der Grund dafür ist natürlich, wie von anderen erwähnt - Geschwindigkeit; Warum etwas atomar und notwendigerweise langsamer machen, wenn nicht immer erforderlich?

+2

Die Zerlegung "Mini-Op" ist für die Atomarität irrelevant, da ein einzelner CPU-Kern während der Instruktion nicht unterbrochen werden kann. Tatsächlich ist inc ohne Lock-Präfix auf Single-Core-Rechnern vollkommen atomar. Nur wenn andere Kerne (oder dunkler, andere Hardware auf dem Bus) auf den Speicher zugreifen können, spielt das Sperrpräfix eine Rolle. –

+1

@R ..: Argumentiert so, _any_ modify-mem cpu op auf einzelne Kerne waren Atom, egal wie getan. Aber auch Single-Core-Maschinen sind heute nicht "single", weil Busmaster-DMA/Speicherbusse, die mit Peripheriegeräten gemeinsam genutzt werden, das Vorhandensein von Cache-Kohärenz- und Atomizitätsproblemen sicherstellen. Es gibt immer mehr als einen Speicherbus-Client. Daher werden Lade-/Speichervorgänge auf Speicherbus-Ebene _always_ zerlegt, selbst wenn sie als Teil einer "einzelnen" CPU-Anweisung auftreten. Atomarität muss behauptet werden (exklusiver Speicherbuszugriff); Die CPU kann keine Modify-mem als Load/Change/Store ausführen, sondern muss mit Bus Lock/Unlock versehen werden. –

+0

@R ..: ARM-CPUs, zum Beispiel, offenbaren die Bus-Lock-Notwendigkeit für Atomixity auf Befehlssatz-Ebene über 'LDREX' /' STREX'. Nur aus der Tatsache, dass x86 mem-modify-Anweisungen hat, kann man nicht schlussfolgern, dass das Bedürfnis nach Explizitheit nicht vorhanden ist. Außerdem geht es nicht darum, die Mitte der Anweisung zu unterbrechen - das ist nicht dasselbe wie die Atomarität. Die Dekomposition ist in diesem Sinne sehr wichtig, da die Speicherzugriffe der _single_-Anweisung mit denen anderer CPUs übereinstimmen können. Der Befehl wird abgeschlossen (es gibt keinen Trap, der einen Neustart erfordert), aber das Ergebnis (ohne 'lock') ist nicht eindeutig/bestimmt. –

Verwandte Themen