Dies ist eine komplizierte Frage, die Sie stellen. Ohne mehr über die Natur Ihrer Fäden zu wissen, ist es schwer zu sagen. Einige Dinge, die bei der Diagnose der Systemleistung zu beachten sind:
Ist der Prozess / Thread
- CPU-gebunden (benötigt viele CPU-Ressourcen)
- Speicher gebunden (benötigt viele RAM-Ressourcen)
- E / A-gebunden (Netzwerk- und / oder Festplattenressourcen)
Alle diese drei Ressourcen sind endlich und jede kann die Leistung eines Systems einschränken. Sie müssen sich ansehen, welche (möglicherweise 2 oder 3 zusammen) Ihre spezielle Situation belastet.
Sie können ntop
und iostat
und verwenden, um vmstat
zu diagnostizieren, was gerade vor sich geht.
"Warum passiert das?" ist leicht zu beantworten. Stellen Sie sich vor, Sie haben einen Korridor, in dem Sie vier Personen nebeneinander unterbringen können. Sie möchten den gesamten Müll an einem Ende an das andere Ende verschieben. Die effizienteste Anzahl von Menschen ist 4.
Wenn Sie 1-3 Leute haben, dann verpassen Sie etwas Platz im Korridor. Wenn Sie 5 oder mehr Personen haben, bleibt mindestens eine dieser Personen die ganze Zeit hinter einer anderen Person in der Warteschlange stecken. Wenn immer mehr Menschen den Korridor verstopfen, wird die Aktivität nicht beschleunigt.
Sie möchten also so viele Leute haben, wie Sie hineinpassen können, ohne dass es zu Warteschlangen kommt. Warum Sie Warteschlangen (oder Engpässe) haben, hängt von den Fragen in der Antwort von slm ab.
quelle
4
ist dies die beste Zahl.Eine übliche Empfehlung ist n + 1 Threads, wobei n die Anzahl der verfügbaren CPU-Kerne ist. Auf diese Weise können n Threads die CPU bedienen, während 1 Thread auf Festplatten-E / A wartet. Wenn weniger Threads vorhanden sind, wird die CPU-Ressource nicht vollständig ausgelastet (irgendwann muss immer auf E / A gewartet werden). Wenn mehr Threads vorhanden sind, kommt es zu Konflikten um die CPU-Ressource.
Threads kommen nicht frei, sondern mit Overhead-ähnlichen Kontextwechseln und - wenn Daten zwischen Threads ausgetauscht werden müssen, was normalerweise der Fall ist - verschiedenen Sperrmechanismen. Dies ist nur dann die Kosten wert, wenn Sie tatsächlich über mehr dedizierte CPU-Kerne verfügen, auf denen Code ausgeführt werden kann. Auf einer Single-Core-CPU ist ein einzelner Prozess (keine separaten Threads) in der Regel schneller als ein Threading. Threads beschleunigen Ihre CPU nicht auf magische Weise, sondern bedeuten nur zusätzlichen Arbeitsaufwand.
quelle
Wie andere bereits betont haben ( slm answer , EightBitTony answer ), ist dies eine komplizierte Frage , zumal Sie nicht beschreiben, was Sie tun und wie sie es tun.
Aber definitiv mehr Threads zu werfen kann die Dinge noch schlimmer machen.
Auf dem Gebiet des parallelen Rechnens gibt es Amdahls Gesetz , das anwendbar sein kann (oder nicht, aber Sie beschreiben nicht die Details Ihres Problems, also ...) und allgemeine Einsichten über diese Klasse von Problemen geben kann.
Der Punkt der Amdahl Gesetz ist , dass in jedem Programm (in jedem Algorithmus) gibt es immer einen Prozentsatz, der nicht sein können parallel ausgeführt (der sequentiellen Abschnitt ) , und es ist ein weiterer Prozentsatz, werden parallel ausgeführt (der parallele Abschnitt ) [Offensichtlich diese beiden Anteile addieren sich zu 100%].
Diese Teile können als Prozentsatz der Ausführungszeit ausgedrückt werden. Beispielsweise können 25% der Zeit für streng sequentielle Vorgänge aufgewendet werden, und die verbleibenden 75% der Zeit werden für Vorgänge aufgewendet, die parallel ausgeführt werden können.
(Bild aus Wikipedia )
Das Amdahlsche Gesetz sagt voraus, dass Sie für jeden gegebenen parallelen Teil (z. B. 75%) eines Programms die Ausführung nur so weit beschleunigen können (z. B. höchstens viermal), selbst wenn Sie immer mehr Prozessoren für die Arbeit verwenden.
Als Faustregel gilt: Je mehr von Ihnen programmieren, die Sie nicht parallel ausführen können, desto weniger können Sie mit mehr Ausführungseinheiten (Prozessoren) erzielen.
Da Sie Threads (und keine physischen Prozessoren) verwenden, kann die Situation noch schlimmer sein. Denken Sie daran, dass Threads (abhängig von der Implementierung und der verfügbaren Hardware, z. B. CPUs / Kerne) mit demselben physischen Prozessor / Kern verarbeitet werden können (eine Form von Multitasking, wie in einer anderen Antwort angegeben).
Diese theoretische Vorhersage (über die CPU-Zeiten) berücksichtigt andere praktische Engpässe nicht als
das kann leicht der begrenzende Faktor in praktischen Anwendungen sein.
quelle
Der Schuldige sollte hier das "CONTEXT SWITCHING" sein. Hierbei wird der Status des aktuellen Threads gespeichert, um die Ausführung eines anderen Threads zu starten. Wenn mehrere Threads die gleiche Priorität erhalten, müssen sie vertauscht werden, bis die Ausführung abgeschlossen ist.
In Ihrem Fall findet bei 50 Threads eine große Menge an Kontextwechsel statt, im Vergleich dazu, dass nur 10 Threads ausgeführt werden.
Dieser Zeitaufwand, der durch das Wechseln des Kontexts entsteht, führt dazu, dass Ihr Programm langsam läuft
quelle
ps ax | wc -l
derzeit 225 Prozesse gemeldet, und sie ist keineswegs stark ausgelastet). Ich bin geneigt, mit der Vermutung von @ EightBitTony zu gehen; Die Ungültigmachung des Caches ist wahrscheinlich ein größeres Problem, da die CPU jedes Mal, wenn Sie den Cache leeren, auf Code und Daten aus dem RAM warten muss .So korrigieren Sie die Metapher von EightBitTony:
Eine Person hier ist ein Thread, und ein Bucket repräsentiert die Ausführungsressource, die der Engpass ist. Das Hinzufügen weiterer Threads hilft nicht, wenn sie nichts tun können. Darüber hinaus sollten wir betonen, dass das Weitergeben eines Eimers von einer Person zu einer anderen in der Regel langsamer ist, als wenn eine einzelne Person den Eimer nur über dieselbe Distanz trägt. Das heißt, dass zwei Threads, die sich auf einem Kern abwechseln, in der Regel weniger Arbeit verrichten als ein einzelner Thread, der doppelt so lang läuft.
Ob die begrenzende Ausführungsressource (Bucket) für Ihre Zwecke eine CPU oder ein Core oder eine Hyper-Thread-Anweisungs-Pipeline ist, hängt davon ab, welcher Teil der Architektur Ihr begrenzender Faktor ist. Beachten Sie auch, dass wir davon ausgehen, dass die Threads völlig unabhängig sind. Dies ist nur der Fall, wenn sie keine Daten gemeinsam nutzen (und Cache-Kollisionen vermeiden).
Wie einige Leute vorgeschlagen haben, ist die begrenzende Ressource für E / A möglicherweise die Anzahl der sinnvollen E / A-Vorgänge in der Warteschlange: Dies kann von einer ganzen Reihe von Hardware- und Kernelfaktoren abhängen, kann aber auch viel größer sein als die Anzahl Kerne. Hier ist der Kontextwechsel, der im Vergleich zu ausführungsgebundenem Code so kostspielig ist, im Vergleich zu E / A-gebundenem Code ziemlich billig. Leider denke ich, dass die Metapher völlig außer Kontrolle geraten wird, wenn ich versuche, dies mit Eimern zu rechtfertigen.
Beachten Sie, dass das optimale Verhalten mit E / A-gebundenem Code in der Regel immer noch höchstens einen Thread pro Pipeline / Core / CPU hat. Sie müssen jedoch asynchronen oder synchronen / nicht blockierenden E / A-Code schreiben, und die relativ geringe Leistungsverbesserung rechtfertigt nicht immer die zusätzliche Komplexität.
PS. Mein Problem mit der ursprünglichen Korridor-Metapher ist, dass dringend empfohlen wird, 4 Warteschlangen zu haben, wobei 2 Warteschlangen Müll transportieren und 2 zurückkehren, um mehr zu sammeln. Dann können Sie jede Warteschlange machen fast so lang wie der Flur und das Hinzufügen von Menschen haben beschleunigen den Algorithmus (Sie drehte sich im Grunde den ganzen Flur in ein Förderband).
Tatsächlich ist dieses Szenario der Standardbeschreibung der Beziehung zwischen Latenz und Fenstergröße im TCP-Netzwerk sehr ähnlich, weshalb es mir aufgefallen ist.
quelle
Es ist ziemlich unkompliziert und einfach zu verstehen. Wenn Sie mehr Threads haben, als Ihre CPU unterstützt, werden Sie tatsächlich serialisiert und nicht parallelisiert. Je mehr Threads Sie haben, desto langsamer wird Ihr System. Ihre Ergebnisse sind tatsächlich ein Beweis für dieses Phänomen.
quelle