Wie unterscheidet sich Spinlock vom Polling?

41

Ist Spinlock und Polling dasselbe?

Wikipedia:

Ein Spinlock ist eine Sperre, die bewirkt, dass ein Thread, der versucht, es zu erfassen, einfach in einer Schleife wartet ("spin") und wiederholt prüft, ob die Sperre verfügbar ist

Das klingt furchtbar nach:

while(!ready);

Es wurde mir beigebracht, Abstimmungen möglichst zu vermeiden, da sie durchweg nicht optimal waren. Also, ist Spinlock ein ausgefallener Name für schlechtes altes Polling? Wie unterscheidet sich ein Spinlock vom Polling?

Lord Loh.
quelle

Antworten:

85

Beim Abrufen wird wiederholt geprüft, ob eine Ressource (eine beliebige Ressource) bereit ist.

Ein Spinlock ist, wenn die Ressource, die Sie abfragen, eine Sperre ist.

Beachten Sie, dass das Polling nicht schlecht ist. Das Abrufen ist insbesondere dann effizient, wenn zum Zeitpunkt des Abrufs in der Regel Daten verfügbar sind. Abfragen sind nur dann ineffizient, wenn Sie dies tun, ohne dass Daten zurückgegeben werden.

Interrupts hingegen sind ineffizient, wenn so viele Daten vorhanden sind, dass Sie ständig unterbrochen werden. Sie sind effizient, wenn Daten selten genug eingehen, dass Sie nützliche Arbeiten erledigen können, bevor Sie unterbrochen werden.

Ich kann Ihnen ein reales Beispiel aus eigener Erfahrung geben: Vor 15 Jahren hatte ich mein E-Mail-Programm so eingerichtet, dass es mich jedes Mal unterbrach, wenn eine neue E-Mail einging. Dies geschah ein- oder zweimal pro Woche. Das ständige Überprüfen meines Posteingangs wäre eine gewaltige Zeitverschwendung gewesen.

Heutzutage habe ich alle Benachrichtigungen deaktiviert. Ich weiß, dass es dort immer neue E-Mails geben wird, wenn ich in meinen Posteingang schaue. Polling ist jetzt viel effizienter.

Spinlocks sind effizient, wenn a) die Wahrscheinlichkeit, dass die Sperre ergriffen wird, gering ist, und b) wenn die Sperre ergriffen wird, wird sie nur für eine kurze Zeit gehalten. Mit anderen Worten: Es ist effizient für größtenteils unbearbeitete feinkörnige Schleusen, aber ineffizient für stark umkämpfte grobkörnige Schleusen.

(Und natürlich funktionieren Spinlocks nur, wenn es eine echte Parallelität gibt, sonst hat der andere Thread keine Chance, die Sperre aufzuheben. Ich denke, das liegt auf der Hand, aber ich wollte es trotzdem sagen.)

Jörg W. Mittag
quelle
5
Spinlocks können in einer kooperativen Multitasking-Umgebung durchaus sinnvoll sein. Sie müssen nur sicherstellen, dass Sie die Kontrolle in der Schleife geben.
Kevin
4
Tolles Beispiel für E-Mails. Erinnert mich daran, dass Sie immer eine E-Mail haben ...
Petr Pudlák
2
@ Kevin: Ich habe eine sehr puristische Vorstellung von einem Spinlock, buchstäblich einer Sperre, die sich nur in einer leeren Schleife dreht. ( atomically_do { while (lock.is_locked?); lock.acquire! }) Wenn es nachgibt, ist es in dieser puristischen Sichtweise keine leere Schleife und somit auch kein Spinlock :-D Aber natürlich ist eine gewisse Hybridisierung mit anderen Arten von Sperren oder Entspannungen / Ergänzungen des platonischen Ideals in der realen Welt durchaus sinnvoll.
Jörg W Mittag
3
@bubakazouba: Ein Spinlock funktioniert, indem es sich buchstäblich in einer leeren Schleife dreht und überprüft, ob die Sperre bereits freigegeben ist. Ist die Sperre bereits freigegeben? Ist die Sperre bereits freigegeben? Ist die Sperre bereits freigegeben? wieder und wieder. Wenn es keine Parallelität gibt, läuft gleichzeitig kein anderer Thread, der die Sperre aufheben könnte, sodass Sie effektiv eine Endlosschleife haben! Lesen Sie den Kommentar direkt über Ihrem.
Jörg W Mittag
1
@kasperd: Sie können kooperatives Multitasking immer noch in ereignisgesteuerter Serversoftware wie nginx sehen. In diesem Fall gibt es einen Thread und keine Sperre, was bedeutet, dass Sie nur einen Kern ausnutzen können. Nach meinem besten Wissen gibt es praktisch keine Beispiele für echtes kooperatives Multitasking mit mehreren Kernen. Ein solches System wäre dumm, da Sie alle Nachteile von kooperativem Multitasking erhalten würden, ohne die Vorteile von Sperren.
Kevin
10

Ein Spinlock ist eine Art Sperre, die speziell durch Abfragen erreicht wird.

Polling ist eine Methode, um den Status von etwas zu überprüfen (indem Sie nach dem Status fragen, anstatt darauf zu warten, den Status zu erfahren).

Nicht alle Abfragen sind Spinlocks, z. B. das Abfragen des Status von Tastaturtasten.


Polling ist auch nicht von Natur aus schlecht. Sehr kurze Abfrageperioden können teure Kontextverschiebungen vermeiden, die für die Verwendung von Interrupts erforderlich wären. Außerdem kann die Abfrage manchmal einfacher zu implementieren und damit einfacher zu warten sein, insbesondere auf niedrigeren Ebenen. Wie üblich sind Absoluten eine schreckliche Sache, und Sie sollten die Methode verwenden , die die entsprechende Leistung / Komplexität Trade - off für Ihre Bedürfnisse gibt , wie Sie sie gemessen haben , anstatt blind verwenden oder verwerfen Optionen.

8bittree
quelle
5

Spinlock unterscheidet sich von Polling, da es nur für einen sehr kurzen Zeitraum in der Größenordnung von wenigen Millisekunden oder weniger auftritt . Die Abstimmung kann auf unbestimmte Zeit fortgesetzt werden.

Bei der parallelen Programmierung ist eine kurze Folge des Spinnens oft der Blockierung vorzuziehen, da die Kosten für Kontextwechsel und Kernelübergänge vermieden werden.

Weiterführende
Literatur SpinLock und SpinWait in C #
Spinlocks und Read-Write-Locks in C

Robert Harvey
quelle
Ich denke, Sie wollten Mikrosekunden sagen. Für eine Sperre, die eine ganze Millisekunde dauert, sollten wir eine Sperrenimplementierung verwenden, die einen Kernelaufruf bei Konflikten ausführt.
Peter
@ Peter Vielleicht hat Albahari das gemeint. Das sagt sein Text.
Robert Harvey
4

Der Unterschied besteht darin, dass ein Spinlock (hoffentlich) nur in Situationen verwendet wird, in denen es angemessen ist, und in diesen Situationen ist es sehr effizient.

Sie verwenden ein Spinlock, wenn Sie erwarten, dass eine Ressource nur für eine sehr kurze Zeit gesperrt wird - zum Beispiel, wenn eine Sperre nur zum Aktualisieren einer Variablen verwendet wird. Das Spinlock fragt die Sperre mit maximaler Geschwindigkeit ab, aber hoffentlich für weniger als Mikrosekunden. Ein normaler Mutex würde einen OS-Aufruf erfordern. WENN die Sperre nur für eine winzige Zeitspanne gehalten wird, verbraucht die Spinlock-Funktion nur eine winzige Menge an CPU-Zeit, während der OS-Aufruf länger dauert. Wenn diese Erwartung jedoch falsch ist, ist der Spinlock sehr ineffizient - er beansprucht 100% der CPU-Zeit auf einer CPU, während der normale Mutex nur die Zeit benötigt, um das Betriebssystem aufzurufen und zurückzukehren.

Manchmal werden beide kombiniert; Sie führen die Drehsperre für eine kurze Zeit aus und wechseln zu einer anderen Strategie, wenn die Drehsperre nicht funktioniert.

gnasher729
quelle
2

Übermäßiges Abfragen ist etwas, das Sie nicht tun sollten, da es Systemressourcen verschwendet. Daraus folgt, dass das Abrufen in Ordnung ist, wenn keine Systemressourcen verschwendet werden .

Beispielsweise wird durch übermäßiges Abfragen die CPU-Auslastung auf 100% erhöht, wenn die tatsächliche Arbeit nur zu einer Auslastung von 2% führen würde.

Polling kann für andere Zwecke als verwendet werden while(!ready). Zum Beispiel bedeutet dies, regelmäßig zu überprüfen, ob der Benutzer eine Taste gedrückt hat. Eine vernünftige Implementierung prüft höchstens einmal alle 15 Millisekunden, es ist also eine Prüfung alle ~ 20 Millionen Taktzyklen. Diese Art der Abfrage ist großartig, da keine Systemressourcen verschwendet werden.

Ein SpinLock ist kein Sonderfall. Wenn wir einen SpinLock haben und ein Thread in die Sperre eintritt und ein anderer warten muss, ist der SpinLock genau dann die falsche Wahl, wenn der wartende Thread Systemressourcen verschwendet. Der wartende Thread verschwendet Systemressourcen genau dann, wenn er eine erhebliche Zeitspanne warten muss, bevor er die Sperre erwerben kann.

Daher ist die Verwendung eines SpinLocks zum Schutz von Objekten, die einige tausend oder mehr Taktzyklen benötigen, bevor sie wieder entsperrt werden (z. B. das Kompilieren und Ausführen eines JavaScript-Elements im laufenden Betrieb), genau aus dem von Ihnen angegebenen Grund schlecht. Die Verwendung von SpinLock zum Schutz von Elementen, die schnell ausgeführt werden, wie beispielsweise der Zugriff auf eine ordnungsgemäß implementierte Hash-Map, ist jedoch in Ordnung, da der wartende Thread nur zwei- oder dreimal ausgeführt wird und daher keine Systemressourcen verschwendet.

Peter
quelle