Ich benutze boost spsc_queue
um meine Sachen von einem Thread zum anderen zu bewegen. Es ist einer der kritischen Stellen in meiner Software, also möchte ich es so schnell wie möglich machen. Ich habe dieses Testprogramm geschrieben:
Kompiliere Flags:
%Vor%Auf meinem Rechner: RHEL 7.1, gcc 4.8.3, Xeon E5-2690 v3 empfange ich 290-300 Nanosekunden.
upd: Warteschlangenmechanismus ist erforderlich. wenn der erste Thread Daten alle 1000 Nanosekunden erzeugt, aber der zweite Thread 10 000 Nanosekunden, um einen einzelnen Gegenstand zu verarbeiten, muss ich mehrere Gegenstände für eine kurze Zeitspanne "anreihen". Aber meine "Warteschlange" ist nie "zu groß". Fixed-Size-Short-Ring-Puffer muss ausreichen.
upd2 Kurz gesagt lautet die Frage: Was ist die schnellste einzelne Producer-Single-Consumer-Queue (am wahrscheinlichsten auf Ringbuffer mit fester Größe)? Ich benutze Boost spsc_queue und erreiche ~ 300 ns Latenz, können Sie etwas schneller vorschlagen?
upd3 In Java gibt es einen Disruptor, der 50 ns Latenz Ссылка Haben wir etwas in C ++ mit der gleichen 50 ns Latenz?
Da Sie int
s haben, messen Sie (im Idealfall) die Gesamtlatenz zwischen einem Aufruf von push()
an die Zeit pop()
gibt true
zurück.
Das macht keinen Sinn : Der Consumer-Thread ist eifrig polling die Warteschlange, das heißt, er loopt und prüft eifrig, ob pop
einen Wert abgerufen hat.
Wenn (IFF) die Latenz (für ein einzelnes Element) minimiert werden soll, würde meine Schätzung die Verwendung eines Synchronisierungsmechanismus für die Signalisierung sein, spsc_queue
, soweit ich das beurteilen kann, sieht dies nicht vor. (Sie benötigen einen Container oder eine benutzerdefinierte Lösung, in der Sie eine Art Zustandsvariable / Event, ...)
Wenn Sie (IFF) jedoch den Durchsatz maximieren möchten (Elemente pro Zeit), ist es weniger sinnvoll, die Latenz für ein "Aufwachen" eines (einzelnen) Elements zu messen. In diesem Fall möchten Sie die Parallelität, die Sie haben, bestmöglich nutzen, da wird in einem Kommentar erwähnt :
Der schnellste Weg zur Datenübermittlung besteht oft darin, für jeden Datenblock einen einzelnen Thread zu verwenden. Das heißt, verwenden Sie nur die in den Daten vorhandene Parallelität.
Adressierung Ihrer Aufzählungspunkte:
Wie gut ist die Test App: Ich denke nicht, dass es viel Sinn macht.
scheduledAt
in einer atomaren Datei erforderlich, da Sie sie aus einem Thread schreiben und von einem anderen lesen. Sonst hast du UB. struct {int val; int64_t time; };
in die Warteschlange zu setzen und dadurch den atomaren Zaun zu vermeiden. Aktuelle beste Zeit der Branche : keine Ahnung. Nicht sicher, ob sich jemand darum kümmert. (Vielleicht in etwas Kernel-Zeug?)
Wahl von spsc_queue : Ich denke nicht, dass es eine gute Wahl ist, weil es Abfragen erfordert.
schneller als spsc_queue? : Siehe oben. Verwenden Sie Benachrichtigungen ohne Abfrage.
schreibe einen Code, der gleich viel schneller funktioniert? : Nein. Oder besser gesagt, ich werde es nicht tun. = & gt;
Um die Antwort des Mannes zu zitieren:
- Sie definieren das Problem und wählen einen geeigneten Synchronisationsmechanismus
Das Problem mit Ihrer Frage ist, dass keine Problemdefinition vorliegt.
Soweit es mich betrifft, scheint die Cross-Thread-Benachrichtigungslatenz im Kontext eines User-Land-Prozesses auf einem normalen Betriebssystem völlig irrelevant zu sein. Was ist Ihr Anwendungsfall?
Erstens ist das Schreiben eines solchen Testprogramms völlig nutzlos. Sie arbeiten nicht mit den Daten, daher sind die Ergebnisse verzerrt. Zweitens verwendet Ihr Test usleep () zwischen Pushs - bei dieser Rate können Sie jede Art von Synchronisationsgrundelement verwenden. Es scheint auch, dass Ihre Consumer () nie beendet wird ...
Die Art, wie Sie so etwas implementieren, ist die folgende:
Sie benötigen bereits erste Erfahrungen oder Sie können versuchen, verschiedene Ansätze zu implementieren und zu sehen, was am besten funktioniert.
Es hängt von der Semantik der Anwendung ab und davon, wie viele Threads beteiligt sind. Bis jetzt betrachten Sie rohe Latenz. Mit mehr Threads könnte auch die Skalierung eine interessante Metrik sein.
Für den Fall mit zwei Threads könnten atomare Aktualisierungen an einem einzelnen Speicherort, vorzugsweise in einer Cache-Zeile, die von keinen anderen Operationen berührt wird, schneller sein, wenn das, was Sie mit den abgerufenen Daten tun, dies erlaubt.
Tags und Links c++ multithreading performance boost lock-free