2012-06-13 3 views
9

Und wie viel schneller/langsamer ist es im Vergleich zu einer unbestrittenen atomaren Variable (wie atomare <> von C++) Operation. Wie viel langsamer sind umstrittene atomare Variablen im Vergleich zur unangetasteten Sperre? Die Architektur, an der ich arbeite, ist x86-64.Wie schnell ist eine unangekündigte Sperre?

+0

mögliche Duplikate von [Overhead der Verwendung von Sperren anstelle von atomaren intrinsics] (http://stackoverflow.com/questions/4296876/overhead-of-using-locks-instead-of-atomic-intrinsics) –

+0

@KonradRudolph, I Sieh die Fragen sind ähnlich aber nicht genau gleich. Dieser konzentriert sich mehr auf die grundlegenden Betriebskosten, während der andere die Overhead-Kosten zweier Ansätze für einen Algorithmus darstellt. Ich würde sie tatsächlich etwas anders beantworten. –

+0

@ edA-qamort-ora-y Als Autor der anderen Frage kann ich sagen, dass sie gleich sind. Die andere Frage kann * anders ausgedrückt werden (in Bezug auf Overhead), aber was sie tatsächlich gefragt hat, ist "Wie viel schneller als eine Sperre eine atomare Operation ist?" –

Antwort

5

Es gibt eine project on GitHub mit dem Zweck, dies auf verschiedenen Plattformen zu messen. Leider hatte ich nach meiner Masterarbeit nie wirklich die Zeit, dies zu verfolgen, aber zumindest ist der rudimentäre Code vorhanden.

Es misst Pthreads und OpenMP-Schlösser, im Vergleich zu __sync_fetch_and_add intrinsisch.

Soweit ich mich erinnere, erwarteten wir einen ziemlich großen Unterschied zwischen Locks und atomaren Operationen (~ eine Größenordnung), aber der wirkliche Unterschied erwies sich als sehr klein.

Die Messung auf meinem System ergibt jedoch Ergebnisse, die meine ursprüngliche Vermutung widerspiegeln, nämlich dass (unabhängig davon, ob pthreads oder OpenMP verwendet werden) atomare Operationen ungefähr fünfmal schneller sind und eine einzelne verriegelte Inkrementoperation etwa 35 ns benötigt beinhaltet das Erfassen des Schlosses, das Ausführen des Inkrements und das Aufheben der Sperre).

3

hängt von der Schlossimplementierung ab, hängt auch vom System ab. Atomare Variablen können nicht wirklich wie eine Sperre umkämpft werden (nicht einmal wenn Sie acquire-release semantics verwenden), das ist der ganze Punkt der Atomarität, es sperrt den Bus, um den Speicher zu propagieren (abhängig vom Speicherbarrierenmodus) , aber das ist ein Implementierungsdetail.

Allerdings sind die meisten User-Mode-Schlösser Atom ops gerade eingewickelt, siehe this Artikel von Intel für einige Zahlen auf hohe Leistung, skalierbare Schlösser Atom ops unter x86 und x64 mit (im Vergleich gegen CriticalSection Sperren Fenster leider keine Statistiken sind für die SWR Schlösser zu finden, aber man sollte immer für das eigene System/Umgebung profilieren).

+2

"Atomare Variablen können nicht wirklich auf die gleiche Weise umstritten sein als eine Sperre "- Wenn zwei Threads (auf verschiedenen Kernen) die gleiche atomare Variable hämmern, dann bestreitet sie das sicherlich? Es liegt dann an der Architektur/Implementierung, ob der Wettbewerb tatsächlich die Dinge verlangsamt oder nicht. Man könnte es vielleicht mit zwei Threads auf verschiedenen Kernen vergleichen, die die gleiche nicht-atomare Variable hämmern, um ein Gefühl dafür zu bekommen, ob die atomare Synchronisation in irgendeiner Weise Zeit braucht. –

+1

@SteveJessop, definitiv. Zwei Kerne, die dieselbe Variable verwenden, verursachen eine übermäßige Synchronisierung dieser Variablen. Sie sind an diesem Punkt an die Latenz/Bandbreite des Cache-Busses gebunden. –

+0

@SteveJessop: Sie könnten es so nennen, aber, IMO, es ist auf eine andere Art und Weise alle zusammen, so dass Sie es nicht wirklich in die gleiche Kategorie wie Spin-Wait-Retry für eine bereits erworbene Sperre setzen können. – Necrolis

14

Ich habe zufällig viele Low-Level-Geschwindigkeitstests herumliegen. Was genau die Geschwindigkeit bedeutet, ist jedoch sehr unsicher, weil es sehr davon abhängt, was genau Sie tun (auch unabhängig von der Operation selbst).

Hier sind einige Zahlen von einem AMD 64-Bit Phenom II X6 3.2Ghz. Ich habe dies auch auf Intel-Chips ausgeführt und die Zeiten variieren sehr (je nachdem, was gerade gemacht wird).

Ein GCC __sync_fetch_and_add, der eine vollständig eingezäunte atomare Addition wäre, hat einen Durchschnitt von 16ns, mit einer Mindestzeit von 4ns. Die minimale Zeit ist wahrscheinlich näher an der Wahrheit (obwohl selbst dort habe ich ein bisschen Overhead).

Ein uncontreted Pthread Mutex (durch Boost) ist 14ns (was auch sein Minimum ist). Beachten Sie, dass dies auch ein bisschen zu niedrig ist, da die Zeit tatsächlich zunimmt, wenn etwas anderes den Mutex gesperrt hat, aber jetzt nicht mehr unbestätigt ist (da es eine Cache-Synchronisierung verursacht).

Ein fehlgeschlagener try_lock ist 9ns.

Ich habe keine einfache alte atomische inc, da dies auf x86_64 nur eine normale Austauschoperation ist. Wahrscheinlich nahe der minimal möglichen Zeit, also 1-2ns.

Notify benachrichtigen ohne einen Kellner auf eine Bedingung Variable ist 25ns (wenn etwas über 304ns wartet).

Da jedoch alle Sperren bestimmte CPU-Bestellgarantien verursachen, wird die Größe des Speichers, den Sie geändert haben (was auch immer in den Speicherpuffer passt), die Dauer dieser Vorgänge ändern. Und natürlich, wenn du jemals einen Mutex hast, der deine schlimmste Zeit ist. Jede Rückkehr zu dem Linux-Kernel kann Hunderte von Nanosekunden betragen, selbst wenn kein Threadwechsel tatsächlich auftritt. Dies ist normalerweise der Fall, wenn atomare Sperren übertreffen, da sie niemals irgendwelche Kernel-Aufrufe beinhalten: Ihre durchschnittliche Fallleistung ist auch Ihr schlimmster Fall. Mutex-Entriegelung verursacht auch einen Overhead, wenn Threads warten, während ein Atomic dies nicht tut.


HINWEIS: Solche Messungen sind mit Problemen behaftet, so dass die Ergebnisse immer fraglich sind. Meine Tests versuchen, Variationen zu minimieren, indem CPU-Geschwindigkeit fixiert wird, CPU-Affinität für Threads festgelegt wird, keine anderen Prozesse ausgeführt werden und über große Ergebnismengen gemittelt wird.

+0

Danke für die Zahlen! Welche Plattform hast du getestet? "Pthread Mutex" sagt nicht viel, denn was das bedeutet, hängt ganz von der Implementierung ab. Da die Zeit nahe an einem atomaren Add ist, gehe ich davon aus, dass es sich um GNU/Linux handelt. –

+0

Ja, auf Linux. Unbeglaubigt bedeutet, dass es keinen Systemaufruf berührt, daher ist der Futex in diesem Fall nicht tatsächlich involviert (nicht umstritten in der NPTL-Bibliothek wird vollständig im Benutzerbereich ohne Systemaufruf gelöst). –

+0

In meiner Meinung "das Futex" _ist_ die ganze Zahl, so ist es beteiligt, aber alles, was benötigt wird, ist ein atomares Inkrement von "der Futex" (d. H. Die ganze Zahl) –