Warum gilt ein pthread-Mutex als “langsamer” als ein futex?

Lesezeit: 8 Minuten

Benutzeravatar von Jason
Jason

Warum gelten POSIX-Mutexe als schwerer oder langsamer als Futex? Woher kommt der Overhead im Mutex-Typ pthread? Ich habe gehört, dass pthread-Mutexe auf futexes basieren und, wenn unbestritten, keine Aufrufe in den Kernel tätigen. Es scheint also, dass ein Pthread-Mutex lediglich ein “Wrapper” um einen Futex ist.

Besteht der Overhead einfach im Funktions-Wrapper-Aufruf und in der Notwendigkeit, dass die Mutex-Funktion den Futex “einrichtet” (dh im Grunde die Einrichtung des Stapels für den pthread-Mutex-Funktionsaufruf)? Oder finden mit dem pthread-Mutex einige zusätzliche Schritte zur Speicherbarriere statt?

  • @Jörgen du hast damals nichts verpasst, die gab es nicht! Sie befinden sich in Linux 2.6.x (entwickelt während der 2.5.x-Entwicklungsserie)

    – Nektarios

    15. Juni 2011 um 21:40 Uhr

  • @Nektarios: Tatsächlich gab es ähnliche Arten von Sperren schon viel früher. Ich glaube, die ursprüngliche DRI-Sperre (um ’91, SGI) war den aktuellen Futexes ähnlich.

    – ninjalj

    15. Juni 2011 um 22:13 Uhr

  • Haben Sie eine Referenz für “POSIX-Mutexe gelten als schwerer oder langsamer als Futexe”? Denn soweit ich weiß, haben pthreads unter Linux in den letzten Jahren (seit NPTL) so funktioniert, wie Sie es beschreiben.

    – Nemo

    15. Juni 2011 um 22:19 Uhr

  • @Nemo: Nur neugierig, wenn sie so funktionieren, wie ich es in meiner Frage beschrieben habe (dh beide bleiben im Benutzerbereich, wenn sie unbestritten sind, und beide machen Kernel-Aufrufe, wenn sie bestritten werden), warum sollten Sie sich dann die Mühe machen, einen Futex zu verwenden? ein Mutex?

    – Jason

    15. Juni 2011 um 23:13 Uhr

  • @Nemo: Übrigens, es scheint, als ob die Leute in diesem Thread die Tatsache wirklich mögen, dass ich geantwortet habe, indem ich einen Futex über einen Mutex vorgeschlagen habe, da meine Annahme war, dass ein Mutex immer, selbst im unbestrittenen Fall, einen Aufruf in den Kernel machen muss. Ich habe jedoch bemerkt, dass einige Poster erwähnt haben, dass pthread Mutexe und Semaphore unter Linux Wrapper auf Futexes sind, was dann die Frage aufwirft, warum man sich mit der Mühe der Verwendung eines Futex auseinandersetzen muss, wenn Abstraktionen auf höherer Ebene leicht verfügbar sind?

    – Jason

    15. Juni 2011 um 23:21 Uhr


Benutzeravatar von ninjalj
ninjalj

Futexes wurden erstellt, um die Leistung von pthread-Mutexes zu verbessern. NPTL verwendet futexes, LinuxThreads vordatierte futexes, was meiner Meinung nach der Grund für die “langsamere” Überlegung ist. NPTL-Mutexe haben möglicherweise zusätzlichen Overhead, aber es sollte nicht viel sein.

Bearbeiten:
Der eigentliche Overhead besteht im Wesentlichen aus:

  • Auswählen des richtigen Algorithmus für den Mutex-Typ (normal, rekursiv, adaptiv, fehlerüberprüfend; normal, robust, prioritätsvererbt, prioritätsgeschützt), wobei der Code dem Compiler deutliche Hinweise darauf gibt, dass wir wahrscheinlich einen normalen Mutex verwenden (so es sollte dies der Verzweigungsvorhersagelogik der CPU übermitteln),
  • und ein Schreiben des aktuellen Eigentümers des Mutex, wenn wir es schaffen, ihn zu nehmen, was normalerweise schnell sein sollte, da er sich in derselben Cache-Zeile befindet wie die tatsächliche Sperre, die wir gerade genommen haben, es sei denn, die Sperre ist stark umkämpft und etwas anderes Die CPU hat auf die Sperre zwischen dem Zeitpunkt zugegriffen, an dem wir sie genommen haben, und als wir versuchten, den Besitzer zu schreiben (dieser Schreibvorgang ist für normale Mutexe nicht erforderlich, wird jedoch für die Fehlerprüfung und rekursive Mutexe benötigt).

Also ein paar Zyklen (typischer Fall) bis ein paar Zyklen + eine Verzweigungsfehlvorhersage + ein zusätzlicher Cache-Fehltreffer (sehr schlimmster Fall).

  • Gibt es also einen Grund, einen Futex über einen Mutex zu verwenden (zumindest unter Linux)?

    – Jason

    15. Juni 2011 um 23:16 Uhr

  • @Jason: nicht wirklich, es sei denn, Sie schreiben Ihre eigene libc oder möchten ein anderes Synchronisationselement als einen Mutex erstellen.

    – ninjalj

    16. Juni 2011 um 0:09 Uhr

  • @Jason, nur als Ersatz für Mutex gesehen, bringt Futex keinen großen Unterschied in der Leistung. Im Gegensatz dazu hat es eine API, die viel schwieriger zu erfassen ist, also tun Sie das nicht. Wo Futex wirklich hilfreich sein kann, ist es, wenn es als Mutex betrachtet wird und Bedingungsvariable (auf einer int Zustand) auf einmal. Dort ist es zeit- und platzsparender und Sie vermeiden die Falle von POSIX, dass jemand auf eine Bedingung warten könnte, indem er einen anderen Mutex verwendet.

    – Jens Gustedt

    16. Juni 2011 um 6:53 Uhr


  • Also kurz gesagt, wann sollte man welche verwenden?

    – Erich

    22. Januar 2016 um 10:16 Uhr

Die kurze Antwort auf Ihre Frage lautet, dass Futexe bekanntermaßen so effizient wie möglich implementiert werden, während ein pthread-Mutex dies möglicherweise ist oder nicht. Zumindest hat ein pthread-Mutex Overhead, der mit der Bestimmung des Mutex-Typs verbunden ist, und Futexes nicht. Ein Futex ist also fast immer mindestens so effizient wie ein pthread-Mutex, bis jemand sich eine leichtere Struktur als ein futex ausdenkt und dann eine pthreads-Implementierung veröffentlicht, die diese für ihren Standard-Mutex verwendet.

Technisch gesehen sind pthread-Mutexe nicht langsamer oder schneller als futexes. pthread ist nur eine Standard-API, also hängt es davon ab, ob sie langsam oder schnell sind Implementierung dieser API.

Speziell unter Linux werden pthread Mutexe als Futex implementiert und sind daher schnell. Eigentlich möchten Sie die futex-API selbst nicht verwenden, da sie sehr schwer zu verwenden ist, nicht über die entsprechenden Wrapper-Funktionen in glibc verfügt und eine Codierung in Assembler erfordert, die nicht portierbar wäre. Zum Glück für uns haben die Glibc-Betreuer all dies bereits für uns unter der Haube der pthread-Mutex-API codiert.

Nun, weil die meisten Betriebssysteme hat keine Futexe implementiert dann meinen Programmierer normalerweise, dass pthread Mutex die Leistung ist, die Sie von der üblichen Implementierung von pthread Mutexes erhalten, was langsamer ist.

Es ist also eine statistische Tatsache, dass in den meisten Betriebssystemen, die POSIX-konform sind, der pthread-Mutex im Kernel-Space implementiert ist und langsamer als ein Futex ist. Unter Linux haben sie die gleiche Leistung. Es könnte sein, dass es andere Betriebssysteme gibt, bei denen pthread-Mutexe im Benutzerbereich implementiert sind (im unbestrittenen Fall) und daher eine bessere Leistung aufweisen, aber mir ist an dieser Stelle nur Linux bekannt.

  • Ist es “eine statistische Tatsache, dass in den meisten POSIX-kompatiblen Betriebssystemen der pthread-Mutex im Kernel-Space implementiert ist”? Wirklich? Weil ich gedacht hätte, dass wahrscheinlich genau das Gegenteil der Fall ist – es ist offensichtlich, dass Sie Kernel-Übergänge möglichst vermeiden möchten, also würde ich erwarten, dass die Autoren typischer pthreads-Implementierungen versuchen, so weit wie möglich im Benutzerland zu bleiben möglich.

    – al45tair

    16. Juli 2018 um 17:17 Uhr

  • Es ist unmöglich, beim Implementieren eines Mutex immer im Benutzerbereich zu bleiben, weil: – ein Thread, der auf den Mutex warten muss, sich selbst in den Ruhezustand versetzen muss (echter Schlaf, nicht beschäftigtes Warten) und dies ohne das Betriebssystem nicht möglich ist. – Ein Thread, der einen Mutex enthält, muss prüfen, ob andere Threads auf den Mutex warten, den er freigibt, und sie daher aufwecken. Dies ist auch ohne das Betriebssystem nicht möglich.

    – Markus Veltzer

    2. August 2018 um 14:45 Uhr


  • Dies bedeutet, dass Sie nur im “unbestrittenen” Fall im Benutzerbereich bleiben können, wenn: – Sie einen Mutex erreichen und dieser offen ist, sodass Sie nicht schlafen gehen müssen. – Sie geben einen Mutex frei und stellen fest, dass niemand darauf wartet, und müssen daher niemanden aufwecken.

    – Markus Veltzer

    2. August 2018 um 14:49 Uhr

  • Und jetzt zum Kernpunkt: Sicher, die meisten Pthread-Implementierer möchten so weit wie möglich im Benutzerbereich bleiben, aber die Implementierungsdetails sind sehr schwierig und erfordern spezielle APIs vom Betriebssystem. Dies fehlte in den meisten Standard-UNIX-Systemen.

    – Markus Veltzer

    2. August 2018 um 14:49 Uhr

  • Mir ist bewusst, dass es im Allgemeinen unmöglich ist, einen Kernel-Übergang zu vermeiden, um den Thread tatsächlich in den Ruhezustand zu versetzen, aber ich denke, dass die Ansicht, dass “spezielle” APIs erforderlich sind, übertrieben ist. Ich denke, es kommt daher, weil ältere Kernel (nicht nur Linux, sondern im Allgemeinen) Threads überhaupt nicht unterstützten, und daher wurden viele der Probleme, die mit dem Versuch verbunden sind, ein Threading-Paket auf einem Kernel ohne Thread-Unterstützung zu schreiben, als inhärent missverstanden Probleme mit Threads.

    – al45tair

    3. August 2018 um 10:55 Uhr

Weil sie so viel wie möglich im Userspace bleiben, was bedeutet, dass sie weniger Systemaufrufe benötigen, was von Natur aus schneller ist, weil der Kontextwechsel zwischen Benutzer- und Kernelmodus teuer ist.

Ich nehme an, du redest von Kernel Threads, wenn Sie über POSIX-Threads sprechen. Es ist durchaus möglich, eine vollständige Userspace-Implementierung von POSIX-Threads zu haben, die keine Systemaufrufe erfordern, aber andere eigene Probleme haben.

Mein Verständnis ist, dass ein Futex auf halbem Weg zwischen einem Kernel-POSIX-Thread und einem Userspace-POSIX-Thread liegt.

Auf AMD64 ist ein futex 4 Bytes, während ein NPTL pthread_mutex_t 56 Bytes ist! Ja, es gibt einen erheblichen Overhead.

  • Ich denke, die Frage betraf die Laufzeitleistung und nicht die Strukturgröße. Außerdem benötigen Sie mehr Daten im Benutzerbereich und es gibt mehr Daten im Kernelbereich für einen Futex, sodass ein Futex keine 4 Bytes hat, noch lange nicht ….

    – Markus Veltzer

    29. November 2016 um 19:55 Uhr

  • Ich denke, die Frage betraf die Laufzeitleistung und nicht die Strukturgröße. Außerdem benötigen Sie mehr Daten im Benutzerbereich und es gibt mehr Daten im Kernelbereich für einen Futex, sodass ein Futex keine 4 Bytes hat, noch lange nicht ….

    – Markus Veltzer

    29. November 2016 um 19:55 Uhr

1409960cookie-checkWarum gilt ein pthread-Mutex als “langsamer” als ein futex?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy