Ich versuche, mich mit C ++ 11 Atomics vertraut zu machen, also habe ich versucht, eine Barriere-Klasse für Threads zu schreiben (bevor jemand sich darüber beschwert, dass er keine vorhandenen Klassen verwendet): Das ist mehr für das Lernen / Selbstverbessern als für irgendeinen wirklichen Bedarf ). Meine Klasse sieht grundsätzlich so aus:
%Vor%Alle Mitglieder werden auf null initialisiert, mit Ausnahme von thread_count, das die entsprechende Anzahl enthält. Ich habe die Wartefunktion als
implementiert %Vor% Wenn Sie jedoch versuchen, es mit zwei Threads zu verwenden ( thread_count
ist 2), w \ u00e4hlt der erste Thread in die Wait-Schleife, aber der zweite Thread entriegelt die Barriere nicht (es scheint, dass es nicht einmal dazu kommt) int val = counter[idx].fetch_add(1);
, aber ich bin mir nicht sicher, dass etwa Allerdings, wenn ich gcc Atom-Spezifika bin mit unter Verwendung volatile int
anstatt std::atomic<int>
und Schreiben wait
wie folgt:.
es funktioniert gut. Aus meiner Sicht sollte es zwischen den beiden Versionen keine grundsätzlichen Unterschiede geben (mehr zu dem Punkt, wenn die Sekunde weniger wahrscheinlich funktionieren sollte). Welches der folgenden Szenarien gilt also?
std::atomic
nicht vollständig verstanden und es gibt ein Problem mit der ersten Variante (aber nicht der zweiten) Für den Datensatz verwende ich 32bit mingw mit gcc 4.6.1
Der aufrufende Code sieht so aus:
%Vor% Da mingw nicht <thread>
headers jet verwendet, verwende ich eine selbstgeschriebene Version für das, was im Grunde die entsprechenden pthread-Funktionen umschließt (bevor jemand fragt: Ja, es funktioniert ohne die Barriere, also sollte es kein Problem sein mit die Verpackung)
Irgendwelche Einsichten würden geschätzt werden.
edit: Erklärung für den Algorithmus, um es klarer zu machen:
thread_count
ist die Anzahl der Threads, die auf die Barriere warten sollen (wenn also thread_count
Threads in der Barriere sind, können alle die Barriere verlassen). lock
wird auf eins gesetzt, wenn der erste (oder ein beliebiger) Thread die Barriere erreicht. counter
zählt, wie viele Threads innerhalb der Barriere liegen und wird für jeden Thread if counter>=thread_count
Alle Threads befinden sich innerhalb der Barriere, also werden Zähler und Sperre auf Null zurückgesetzt lock
zu null wird counter
, lock
) verwendet, noch keine Probleme sicherzustellen, dass es, wenn Gewinde auf dem ersten Einsatz der Barriere warten (zB sie verdrängt worden war, als die Barriere aufgehoben) edit2:
Ich habe jetzt getestet es gcc 4.5.1 unter Linux verwenden, in denen beide Versionen scheinen gut zu funktionieren, was zu einem Problem mit mingw des std::atomic
zu verweisen scheint, aber ich bin immer noch nicht ganz überzeugt, da ein Blick in das Verzeichnis <atomic>
Header revaled, dass die meisten Funktionen einfach die entsprechende gcc-atomare Bedeutung nennen, da es eigentlich keinen Unterschied zwischen den beiden Versionen geben sollte
Es sieht unnötig kompliziert aus. Probieren Sie diese einfachere Version aus (gut, ich habe es nicht getestet, ich habe nur darüber nachgedacht :))):
%Vor%BEARBEITEN: @Grizzy, ich kann keine Fehler in Ihrer ersten (C ++ 11) Version finden und ich habe es auch für hundert Millionen Syncs mit zwei Threads ausgeführt und es wird abgeschlossen. Ich habe es jedoch auf einem Dual-Socket / Quad-Core-GNU / Linux-Rechner laufen lassen, daher bin ich eher geneigt, Ihre Option 3 zu vermuten. - Die Bibliothek (oder vielmehr ihr Port zu win32) ist nicht ausgereift / p>
Ich habe keine Ahnung, ob dies hilfreich ist, aber der folgende Ausschnitt aus Herb Sutters Implementierung einer gleichzeitigen Queue verwendet einen Spinlock, der auf Atomics basiert:
%Vor% Tatsächlich bietet der Standard einen speziellen Typ für diese Konstruktion, für den blockierungsfreie Operationen erforderlich sind, std::atomic_flag
. Damit würde der kritische Abschnitt so aussehen:
(Sie können, wenn Sie möchten, die Speicherordnung dort akquirieren und freigeben.)
Hier ist eine elegante Lösung aus dem Buch C ++ Concurrency in Aktion:. Practical Multithreading
%Vor%Hier ist eine einfache Version von mir:
%Vor%Verwendung: (aus std :: lock_guard Beispiel)
%Vor% Ich weiß, dass der Thread ein bisschen alt ist, aber da es immer noch das erste Google-Ergebnis ist, wenn ich nur mit c ++ 11 nach einer Thread-Barriere suche, möchte ich eine Lösung vorstellen, die die ausgelasteten Wartezeiten mit der %Code%.
Grundsätzlich ist es die Lösung von chill, aber statt der std::condition_variable
-Schleife wird while
und std::conditional_variable.wait()
verwendet. In meinen Tests scheint es gut zu funktionieren.
Direkt aus der Dokumentation gestohlen
Tags und Links c++ multithreading gcc c++11