Ich denke, dass beide die gleiche Aufgabe erfüllen. Wie entscheiden Sie, welches Programm Sie für die Synchronisierung verwenden?
Antworten
Zu viele Anzeigen?Die Regel für die Verwendung von Spinlocks ist einfach: Verwenden Sie ein Spinlock nur dann, wenn die tatsächliche Zeit, in der die Sperre gehalten wird, begrenzt und ausreichend klein ist.
Beachten Sie, dass normalerweise vom Benutzer implementierte Spinlocks diese Anforderung NICHT erfüllen, da sie keine Interrupts deaktivieren. Sofern Vorabunterbrechungen nicht deaktiviert sind, verletzt eine Vorabunterbrechung, während ein Spinlock gehalten wird, die Anforderung der begrenzten Zeit.
Ob sie ausreichend klein sind, ist eine Ermessensfrage und hängt vom jeweiligen Kontext ab.
Ausnahme: Einige Kernel-Programmierungen müssen ein Spinlock verwenden, auch wenn die Zeit nicht begrenzt ist. Insbesondere, wenn eine CPU keine Arbeit zu erledigen hat, hat sie keine andere Wahl, als so lange zu spinnen, bis mehr Arbeit auftaucht.
Besondere Gefahr: Bei der Programmierung auf niedriger Ebene ist große Vorsicht geboten, wenn mehrere Unterbrechungsprioritäten bestehen (normalerweise gibt es mindestens eine nicht maskierbare Unterbrechung). In diesem Fall können Präemptionen mit höherer Priorität ausgeführt werden, selbst wenn Interrupts mit Thread-Priorität deaktiviert sind (z. B. vorrangige Hardware-Dienste, die oft mit der virtuellen Speicherverwaltung zusammenhängen). Sofern eine strikte Trennung der Prioritäten beibehalten wird, muss die Bedingung für eine begrenzte Echtzeit gelockert und durch eine begrenzte Systemzeit auf dieser Prioritätsebene ersetzt werden. Beachten Sie, dass in diesem Fall nicht nur der Sperrenhalter vorzeitig beendet werden kann, sondern auch der Spinner unterbrochen werden kann; dies ist im Allgemeinen kein Problem, da Sie nichts dagegen tun können.
Spinlocks können tatsächlich Folgendes leisten sehr schlecht auf NUMA-Maschinen. Das Problem ist leicht zu verstehen und sehr schwer zu beheben (ohne zu einem Mutex zu wechseln, das heißt). Stellen Sie sich einen Spinlock vor, der sich im DRAM "in der Nähe" von Kern A befindet, und Threads auf A und B, die sich um diesen Lock streiten. Nehmen Sie an, dass B von diesem DRAM entfernt ist. Wie wir alle wissen, bedeutet dies, dass die Speicherzugriffe von A etwa fünfmal schneller sind als die von B, weil die Zugriffe von B den Bus des NUMA-Chips durchqueren müssen, während die Zugriffe von A lokal sind und daher diese Busüberquerung vermeiden.
Tatsächlich läuft die Spin-Logik von A 5x oder mehr schneller als die von B. Ja, sie konkurrieren, und B stört A, aber die Auswirkungen sind asymmetrisch: Wenn A das Rennen um den nächsten Zugriff auf die Sperre gewinnt, erhält er lokale Lade- und Speicheroperationen und wird daher mit einer viel höheren Befehlsrate arbeiten. Wenn B sich dreht, sind diese entfernten Ladungen und Speicher langsam, also dreht sich B in Zeitlupe.
Das Ergebnis, und das haben wir bei unserer Arbeit über Derecho ist, dass wir ein sehr unfaires Spinlock erhalten. A ist gegenüber B stark begünstigt, und die Sperrung durch B wird sehr lange dauern.
Wie würden Sie dies beobachten? In unserem Fall verwenden wir LibFabrics und diese Bibliothek hat ein paar Threads, die auf mehrere Kerne verteilt werden. Innerhalb der LibFabric-Logik spinnen A und B, um eine mit der RDMA-Hardware verknüpfte Abschlusswarteschlange zu sperren und dann zu überprüfen. Dies hat zur Folge, dass A diese Warteschlange 5x häufiger überprüft als B. In Fällen, in denen eine Aktion von B erforderlich ist (die abgeschlossene Operation am Kopf der Warteschlange gehört B), lässt A B effektiv für den Zugriff verhungern - und verlangsamt LibFabrics auf extreme Weise, was unseren Derecho-Code stark beeinträchtigt. Wir haben Fälle gesehen, in denen der Zugriff von A so stark begünstigt wurde, dass B bis zu 10 ms auf die Sperre warten musste, obwohl B diese Sperre unter unbeabsichtigten Umständen in 0,2 s erhalten hätte. Der Effekt kann also ziemlich extrem sein.
Schlussfolgerung? Ziehen Sie die Verwendung eines Spinlocks auf einem NUMA-System nicht einmal in Erwägung, wenn sich Ihre Threads (1) auf verschiedenen NUMA-Kernen befinden könnten, (2) mit unterschiedlicher Lokalität zum DRAM, wo der Spinlock zugewiesen wurde. Sie werden massive Leistungsprobleme feststellen! (3) Wenn Sie eine Bibliothek eines Drittanbieters verwenden, die über mehrere Threads verfügt, denken Sie daran, dass sie diese Diskussion möglicherweise nicht gelesen haben und sich irren könnten!
Die Verwendung von Spinlocks auf einem Single-Core-/Single-CPU-System macht in der Regel keinen Sinn, denn solange die Spinlock-Abfrage den einzigen verfügbaren CPU-Kern blockiert, kann kein anderer Thread ausgeführt werden, und da kein anderer Thread ausgeführt werden kann, wird der Lock auch nicht entsperrt. D.h., ein Spinlock verschwendet auf diesen Systemen nur CPU-Zeit ohne wirklichen Nutzen.
Das ist falsch. Es gibt keine Verschwendung von CPU-Zyklen bei der Verwendung von Spinlocks auf Uniprozessorsystemen, denn sobald ein Prozess einen Spinlock einnimmt, ist die Vorkaufsrecht deaktiviert, so dass es keinen anderen Prozess geben kann, der sich dreht! Es macht einfach keinen Sinn, sie zu benutzen! Daher werden Spinlocks auf Uni-Systemen durch preempt_disable zur Kompilierzeit durch den Kernel ersetzt!
- See previous answers
- Weitere Antworten anzeigen