Multithreading, volatile, Cache usw.
-
Wenn ich mehrer Threads und CPUs habe, die auf den gleichen Daten arbeiten und ich das z.B. mit Mutex absichere, müssen dann die Daten auch volatile sein? Oder werden Daten die im CPU Cache sind, auch automatisch aktualisiert, wenn ein anderer CUP die Daten im Hauptspeicher ändert? Hat volatile überhaupt Auswirkungen auf den CPU Cache oder heißt das nur, das die Variable nicht in einem Register sein darf?
-
C++03 kennt keine Threads und damit erübrigt sich die Frage wohl was den Standard betrifft. In C++11 müssen die Daten nicht volatile sein.
-
cooky451 schrieb:
In C++11 müssen die Daten nicht volatile sein.
Warum? Kannst du dazu meine anderen Fragen zum CPU Cache auch beantworten?
-
volatile heißt AFAIK zuallererst, dass der Compiler nicht annehmen darf, dass sich eine Variable nicht spontan ändert. Und falls du sie die ganze Zeit mit einem Mutex absicherst, ändert sie sich auch nicht. Wenn du den Mutex zwischenzeitlich freigibst und ein anderer Thread drauf zugreift, sieht das schon grundlegend anders aus. Und wenn du die Variable nie freigeben würdest, würde sich ja auch die Frage erübrigen...
EDIT: Korrektur nach hustbaer.
-
wxSkip schrieb:
volatile heißt AFAIK zuallererst, dass der Compiler annehmen darf, dass sich eine Variable nicht spontan ändert.
Da fehlt ein "nicht" in dem Satz: nicht annehmen darf.
Oder anders gesagt: davon ausgehen muss, dass sich die Variable spontan ändern kann.
Oder nochmal anders gesagt: volatile Variablen sind per Definition "beobachtbar", d.h. sämtliche Stores/Fetches auf volatile Variablen müssen auch wirklich durchgeführt werden (und auch in der richtigen Reihenfolge).
-
@multicache
Vereinfacht kannst du dir vorstellen, dass nach dem Locken einer Mutex alle Daten neu vom RAM in den Cache geladen werden, und vor dem Freigeben einer Mutex werden alle geänderten Daten vom Cache ins RAM zurückgeschrieben. Und das gilt für alle Daten, volatile spielt diesbezüglich keine Rolle.Wenn du also sowas hast
LockMutex(); int data = g_gemeinsameVariableX; data = BerechneNeuenWert(data); g_gemeinsameVariableX = data; UnlockMutex();
dann muss das funktionieren.
Für die "Kurzfassung"LockMutex(); g_gemeinsameVariableX = BerechneNeuenWert(g_gemeinsameVariableX); UnlockMutex();
gilt natürlich das selbe.
-
hustbaer schrieb:
@multicache
Vereinfacht kannst du dir vorstellen, dass nach dem Locken einer Mutex alle Daten neu vom RAM in den Cache geladen werden, und vor dem Freigeben einer Mutex werden alle geänderten Daten vom Cache ins RAM zurückgeschrieben.Ist deswegen ein Mutex Lock so langsam?
-
multicache schrieb:
Ist deswegen ein Mutex Lock so langsam?
exakt.
//edit 1 Wort-Antwort und ich vertippe mich. Brauche mehr Kaffee
-
Ja und nein, kommt drauf an wie du es siehst.
-
warum müssen die daten denn vom cache in den ram?
volatile bezieht sich doch auf register <-> speicher, oder nicht?
ist der cache etwa prozess/thread spezifisch?
jenz
-
In modernen MultiCore-CPUs haben beide Kerne mindestens einen eigenen L1-Cache. Manchmal ist auch schon der L2 getrennt. In dem Fall muss der korrekte Wert im Ram stehen, damit der Cache der anderen CPU sich aktualisieren kann.
-
tatsache. ist ja ein ding.
ich sehe leider gerade den vorteil nicht.muss das dann wirklich per befehl angestoßen werden?
oder sind caches irgendwie verbunden um einen zugriff auf die selbe stelle zu bemerken?jenz
-
@jenz
Ja, Tatsache.
Wenn du nochmal freundlicher fragst, nimmt sich vielleicht jmd. die Zeit es dir zu erklären.
-
huch, unfreundlich?
mag mir jemand den vorteil von getrennten caches erklären?
-
tatsache. ist ja ein ding.
ich sehe leider gerade den vorteil nicht.War das etwa nicht schnippisch/verarschend gemeint?
Ich kenne keinen der "tatsache. ist ja ein ding." im Ernst sagt (und erst recht nicht schreibt), das ist immer verarsche.Der Vorteil ist dass getrennte Caches schneller sind. Sollte irgendwie logisch sein dass es schneller ist wenn jeder Core "seinen" Cache ganz für sich alleine hat.
Was die automatische Synchronisierung angeht: x86/AMD64 synchronisieren die Caches auch brav automatisch. Andere CPUs tun das nicht - u.a. weil es überhaupt nicht trivial ist das so hinzubekommen, dass es a) zuverlässig funktioniert und dabei b) nicht fürchterlich bremst. Und "nicht trivial" schlägt sich nicht nur in den Entwicklungskosten nieder, sondern auch in der Transistorzahl.
Im Endeffekt ist aber für 99.99% der Programmierer egal warum gewisse Dinge nicht garantiert sind. Viel wichtiger ist das Wissen dass sie eben nicht garantiert sind.
-
hustbaer schrieb:
Ich kenne keinen der "tatsache. ist ja ein ding." im Ernst sagt (und erst recht nicht schreibt)
Doch, mich.
-
Dann hab ich es falsch verstanden, bitte um Verzeihung!
-
Aber warum ist das schneller?
Warum funktioniert es nicht mit einem Cache an den x-Prozessoren angeschlossen sind?
Klar, weil man die dann gegeneinander Synchronisieren muss, aber das kann doch nicht unmöglich sein, dass das nur dann passiert, wenn die auf die gleichen Speicherbereiche zugreifen."Tatsache. Ist ja ein Ding." sollte wirklich nicht schnippisch oder so gemeint sein. Ich wollte einfach nur ausdrücken, dass ich gegoogelt habe, das gefunden habe und es mich überrascht hat.
jenz
-
Weil der Cache der Grund ist, warum Prozessoren überhaupt noch so schnell sein können. Da RAM-Zugriffe so langsam sind, brauchen die Prozessoren einen kleinen Speicherbereich in dem sie Werte zwischenspeichern können, die bald wieder gebraucht werden.
Der Fall, dass zwei Prozessoren auf den selben Daten arbeiten ist nicht der Normalfall. Eher ist das so, dass einfach unterschiedliche Software auf unterschiedlichen Kernen mit unterschiedlichen Daten werkelt.
Wenn die sich jetzt aber den Cache teilen, überschreiben sie sich ständig gegenseitig den Cache-Inhalt (der L1-Cache ist ziemlich klein, also werden bereits durch eine Anwendung alleine permanent Daten rein geladen oder raus geworfen). Womit der Nutzen eines Cache ziemlich exakt 0 ist.
-
EDIT: Blödsinn.