Optimale Anzahl von Threads pro Kern

280

Angenommen, ich habe eine 4-Kern-CPU und möchte einen Prozess in kürzester Zeit ausführen. Der Prozess ist idealerweise parallelisierbar, sodass ich Teile davon auf einer unendlichen Anzahl von Threads ausführen kann und jeder Thread die gleiche Zeit benötigt.

Da ich 4 Kerne habe, erwarte ich keine Beschleunigung, indem mehr Threads als Kerne ausgeführt werden, da ein einzelner Kern nur zu einem bestimmten Zeitpunkt einen einzelnen Thread ausführen kann. Ich weiß nicht viel über Hardware, daher ist dies nur eine Vermutung.

Gibt es einen Vorteil, wenn ein parallelisierbarer Prozess auf mehr Threads als Kernen ausgeführt wird? Mit anderen Worten, wird mein Prozess schneller, langsamer oder in ungefähr der gleichen Zeit abgeschlossen, wenn ich ihn mit 4000 Threads anstatt mit 4 Threads ausführe?

Julia
quelle

Antworten:

253

Wenn Ihre Threads keine E / A, Synchronisierung usw. ausführen und nichts anderes ausgeführt wird, erzielen Sie mit 1 Thread pro Kern die beste Leistung. Dies ist jedoch sehr wahrscheinlich nicht der Fall. Das Hinzufügen weiterer Threads hilft normalerweise, führt jedoch nach einiger Zeit zu Leistungseinbußen.

Vor nicht allzu langer Zeit habe ich Leistungstests auf einem 2-Quad-Core-Computer durchgeführt, auf dem eine ASP.NET-Anwendung unter Mono unter einer recht anständigen Last ausgeführt wird. Wir haben mit der minimalen und maximalen Anzahl von Threads gespielt und am Ende festgestellt, dass für diese bestimmte Anwendung in dieser bestimmten Konfiguration der beste Durchsatz irgendwo zwischen 36 und 40 Threads lag. Alles außerhalb dieser Grenzen schnitt schlechter ab. Lektion gelernt? Wenn ich Sie wäre, würde ich mit einer unterschiedlichen Anzahl von Threads testen, bis Sie die richtige Anzahl für Ihre Anwendung gefunden haben.

Eines ist sicher: 4k-Threads dauern länger. Das sind viele Kontextwechsel.

Gonzalo
quelle
21
Ich denke, Gonzalos Antwort ist gut. Ich möchte nur hinzufügen, dass Sie experimentieren und messen sollten. Ihr Programm unterscheidet sich von seinem oder meinem oder einem anderen Programm, und nur Messungen des Verhaltens Ihres eigenen Programms beantworten Ihre Fragen richtig. Die Durchführung paralleler (oder gleichzeitiger) Programme ist kein Bereich, in dem allein aus ersten Grundsätzen gute Schlussfolgerungen gezogen werden können.
High Performance Mark
5
+1, + Antwort: Es überrascht mich, dass viel mehr Threads als Kerne zu einer besseren Leistung führen, obwohl es sinnvoll ist, wenn mehr Threads im Vergleich zu konkurrierenden Threads einen größeren Zeitanteil bedeuten. Es wäre schön, wenn meine Anwendung Leistungsunterschiede erkennen und sich automatisch auf die optimale Anzahl von Threads einstellen könnte.
Julia
12
Es sollte Sie in einem realen Szenario nicht überraschen. Threads blockieren das Warten auf E / A-Ressourcen wie Festplattenzugriff, Netzwerk usw. Und warten darauf, dass Nicht-E / A-Ressourcen wie andere Threads die Verwendung gemeinsam genutzter Variablen beenden. Was Sie wirklich erreichen möchten, ist die Mindestanzahl von Threads, sodass immer mindestens ein Thread pro Kern ausgeführt werden kann.
Patros
4
1 Faden pro Kern ist nicht das Optimum. Es muss etwas mehr sein, vorzugsweise doppelt so viel, da dadurch ein anderer Thread ausgeführt werden kann, wenn ein Thread vorübergehend blockiert wird. Auch wenn nur im Gedächtnis. Dies ist wichtiger, wenn Sie Systeme (P4, I7, Sun Rock usw.) mit SMT / HT haben
Marco van de Voort
1
Daher das "Das ist sehr wahrscheinlich nicht der Fall" in meiner Antwort. Das Finden der richtigen Nummer hängt von der Anwendung und der Architektur ab, auf der sie ausgeführt wird.
Gonzalo
129

Ich stimme der Antwort von @ Gonzalo zu. Ich habe einen Prozess, der keine E / A ausführt, und hier ist, was ich gefunden habe:

Geben Sie hier die Bildbeschreibung ein

Beachten Sie, dass alle Threads in einem Array arbeiten, jedoch in unterschiedlichen Bereichen (zwei Threads greifen nicht auf denselben Index zu). Daher können die Ergebnisse unterschiedlich sein, wenn sie in unterschiedlichen Arrays gearbeitet haben.

Die 1.86-Maschine ist ein MacBook Air mit einer SSD. Der andere Mac ist ein iMac mit einer normalen Festplatte (ich denke, es ist 7200 U / min). Die Windows-Maschine hat auch eine Festplatte mit 7200 U / min.

In diesem Test war die optimale Anzahl gleich der Anzahl der Kerne in der Maschine.

Motasim
quelle
14
+1 für die Grafik. Natürlich ist 1 Thread pro Kern am besten, aber es ist interessant, dass das Quad-Core-System nicht bei höheren Thread-Nummern (ohnehin <100) zu sein scheint, wie es die anderen tun.
Jim Garrison
46
-1 für die Grafik! Glatte Kurven durch ganzzahlige x-Koordinaten? Ein wilder Sprung von 1 2 3 auf 10 20 30 auf 50 100? Und y-Koordinaten, die für ein gutes Maß Vielfache von 10 plus 2 sind. Das macht Excel, nicht wahr?
Spacedman
5
@Spacedman Ja, das ist es. Die glatten Kurven sehen meiner Meinung nach viel schöner aus. : D
Motasim
22
@PascalvKooten, Das Problem ist nicht, dass es hübsch aussieht, es täuscht auf den ersten Blick. Zunächst beginnt die y-Achse bei 42 und übertreibt den offensichtlichen Unterschied zwischen den getesteten Maschinen. Zweitens deutet das seltsame Fortschreiten der x-Achsenwerte darauf hin, dass die "Zeitaufwand" nicht linear mit der "Anzahl der Threads" skaliert. Dies gilt insbesondere für die blaue Linie. Ich denke, das Problem, das andere (einschließlich ich) damit haben, ist, dass es die Daten falsch darstellt.
Pauluss86
13
@Spacedman Die Kritik in der Grafik ist das Lächerlichste, was mir in den letzten 24 Stunden begegnet ist. Die Grafik hilft. Viel. Zeitraum. Könnte es besser gemacht worden sein? Keinen interessiert es. Glatte Kurve statt diskret? Das ist dein Problem???? Ich gehe davon aus, dass Sie alle niemals ein solches Diagramm in ihre Antwort aufnehmen würden, weil Sie nicht die zusätzliche Zeit / Energie haben, um es gut aussehen zu lassen. Das ist mein Punkt.
Tyrex
49

Ich weiß, dass diese Frage ziemlich alt ist, aber die Dinge haben sich seit 2009 weiterentwickelt.

Es sind jetzt zwei Dinge zu berücksichtigen: die Anzahl der Kerne und die Anzahl der Threads, die in jedem Kern ausgeführt werden können.

Bei Intel-Prozessoren wird die Anzahl der Threads durch das Hyperthreading definiert, das nur 2 beträgt (sofern verfügbar). Aber Hyperthreading verkürzt Ihre Ausführungszeit um zwei, selbst wenn Sie nicht zwei Threads verwenden! (dh 1 Pipeline, die von zwei Prozessen gemeinsam genutzt wird - dies ist gut, wenn Sie mehr Prozesse haben, sonst nicht so gut. Mehr Kerne sind definitiv besser!)

Auf anderen Prozessoren haben Sie möglicherweise 2, 4 oder sogar 8 Threads. Wenn Sie also 8 Kerne haben, von denen jeder 8 Threads unterstützt, können 64 Prozesse ohne Kontextwechsel parallel ausgeführt werden.

"Keine Kontextumschaltung" ist offensichtlich nicht der Fall, wenn Sie mit einem Standardbetriebssystem arbeiten, das die Kontextumschaltung für alle möglichen anderen Dinge außerhalb Ihrer Kontrolle ausführt. Aber das ist die Hauptidee. Bei einigen Betriebssystemen können Sie Prozessoren zuweisen, sodass nur Ihre Anwendung Zugriff auf diesen Prozessor hat.

Nach meiner eigenen Erfahrung sind mehrere Threads gut, wenn Sie viele E / A haben. Wenn Sie sehr viel speicherintensive Arbeit haben (Quelle 1 lesen, Quelle 2 lesen, schnelle Berechnung, Schreiben), hilft es nicht, mehr Threads zu haben. Dies hängt wiederum davon ab, wie viele Daten Sie gleichzeitig lesen / schreiben (dh wenn Sie SSE 4.2 verwenden und 256-Bit-Werte lesen, werden alle Threads in ihrem Schritt gestoppt ... mit anderen Worten, 1 Thread ist wahrscheinlich viel einfacher zu implementieren und Wahrscheinlich fast genauso schnell, wenn nicht sogar schneller. Dies hängt von Ihrer Prozess- und Speicherarchitektur ab. Einige erweiterte Server verwalten separate Speicherbereiche für separate Kerne, sodass separate Threads schneller sind, vorausgesetzt, Ihre Daten werden ordnungsgemäß abgelegt Architekturen, 4 Prozesse laufen schneller als 1 Prozess mit 4 Threads.)

Alexis Wilke
quelle
4
Es gibt wahrscheinlich andere, aber der mir bekannte ist der POWER-Prozessor von IBM. Sie hatten Systeme mit 4 oder 8 Threads pro Prozessor. Jetzt können sie mehr Kerne einschalten, sodass sie stattdessen 2 Threads pro Kern anbieten ...
Alexis Wilke
Dies ist alt, aber die meisten Intel i5, i7 haben Multi-Thread-CPUs wie zum Beispiel i7-CPUs haben normalerweise 4 Kerne, aber 8 Threads.
Edgar.A
4
Prozessoren haben keine Threads. Sie haben physische und logische Kerne. Beim Hyperthreading fungiert ein einzelner physischer Kern als zwei logische Kerne. Ich hatte einen Techniker, der darauf bestand, dass Prozessoren mit Threads eine echte Sache waren, also zeichnete ich ein Bild auf das Whiteboard eines Prozessors, aus dem eine Thread-Spindel herausragt.
@TechnikEmpire Schauen Sie sich diese intel.com/content/www/us/en/processors/core/… an . Vielleicht können Sie dann auch Intel kontaktieren und ihnen Threads zeichnen.
G7K
24

Die tatsächliche Leistung hängt davon ab, wie viel freiwilliges Nachgeben jedes Threads bewirkt. Wenn die Threads beispielsweise überhaupt KEINE E / A ausführen und keine Systemdienste verwenden (dh sie sind zu 100% an die CPU gebunden), ist 1 Thread pro Kern optimal. Wenn die Threads etwas tun, das ein Warten erfordert, müssen Sie experimentieren, um die optimale Anzahl von Threads zu ermitteln. 4000 Threads würden einen erheblichen Planungsaufwand verursachen, daher ist dies wahrscheinlich auch nicht optimal.

Jim Garrison
quelle
21

Die Antwort hängt von der Komplexität der im Programm verwendeten Algorithmen ab. Ich habe eine Methode entwickelt, um die optimale Anzahl von Threads zu berechnen, indem zwei Messungen der Verarbeitungszeiten Tn und Tm für zwei beliebige Anzahl von Threads 'n' und 'm' durchgeführt wurden. Für lineare Algorithmen ist die optimale Anzahl von Threads N = sqrt ((m n (Tm * (n-1) - Tn * (m-1))) / (n Tn-m Tm)).

Bitte lesen Sie meinen Artikel über die Berechnung der optimalen Anzahl für verschiedene Algorithmen: pavelkazenin.wordpress.com

pkazen
quelle
4
Warum wird es herabgestimmt? Es tut mir leid, aber dies ist die beste Antwort auf diese Frage. gonzalo spricht den kühnen Teil der Frage an, und pkazen spricht den Titel an. Beide Antworten sind sehr nützlich, aber die pkazen-Antwort ist relevant, da wir eine systematische Methode haben, um die Anzahl der Threads zu approximieren. Er gibt sogar die Formel für Linea-Algorithmen an.
tobiak777
1
Ich habe nicht abgelehnt, aber wenn ich es getan hätte, wäre es auf der Grundlage, dass es keine wirkliche Erklärung dafür gibt, warum oder wie die optimale Anzahl von Threads mit der Komplexität des Algorithmus zusammenhängt, außer durch Lesen des gesamten verlinkten Artikels, der ist eine lange Lektüre (wegen der Komplexität des Artikels). Darüber hinaus sind mir einige Aspekte des Artikels nicht klar, vor allem, wie die experimentellen Ergebnisse die Theorie bestätigen.
Codebling
Ich glaube auch, dass diese Berechnung davon ausgeht, dass Sie eine unendliche Anzahl von CPU-Kernen haben. Während dies definitiv wertvolle Informationen sind, bezieht sich die Frage auf reale Maschinen mit einer kleinen Anzahl von Kernen.
Navneeth
9

Ich dachte, ich würde hier eine andere Perspektive hinzufügen. Die Antwort hängt davon ab, ob die Frage eine schwache oder eine starke Skalierung voraussetzt.

Aus Wikipedia :

Schwache Skalierung: Wie sich die Lösungszeit mit der Anzahl der Prozessoren für eine feste Problemgröße pro Prozessor ändert.

Starke Skalierung: Wie sich die Lösungszeit mit der Anzahl der Prozessoren für eine feste Gesamtproblemgröße ändert.

Wenn die Frage eine schwache Skalierung voraussetzt, reicht die Antwort von @ Gonzalo aus. Wenn die Frage jedoch eine starke Skalierung voraussetzt, gibt es noch etwas hinzuzufügen. Bei einer starken Skalierung wird von einer festen Workload-Größe ausgegangen. Wenn Sie also die Anzahl der Threads erhöhen, verringert sich die Größe der Daten, an denen jeder Thread arbeiten muss. Auf modernen CPUs sind Speicherzugriffe teuer und es wäre vorzuziehen, die Lokalität beizubehalten, indem die Daten in Caches gehalten werden. Daher kann die wahrscheinlich optimale Anzahl von Threads gefunden werden, wenn der Datensatz jedes Threads in den Cache jedes Kerns passt (ich gehe nicht auf die Details der Diskussion ein, ob es sich um L1 / L2 / L3-Cache (s) des Systems handelt).

Dies gilt auch dann, wenn die Anzahl der Threads die Anzahl der Kerne überschreitet. Angenommen, das Programm enthält 8 beliebige Arbeitseinheiten (oder AU), die auf einem 4-Kern-Computer ausgeführt werden.

Fall 1: Führen Sie vier Threads aus, wobei jeder Thread 2AU ausführen muss. Jeder Thread dauert 10 Sekunden ( mit vielen Cache-Fehlern ). Bei vier Kernen beträgt die Gesamtzeit 10 Sekunden (10 Sekunden * 4 Threads / 4 Kerne).

Fall 2: Führen Sie acht Threads aus, wobei jeder Thread 1AU ausführen muss. Jeder Thread benötigt nur 2 Sekunden (anstelle von 5 Sekunden, da weniger Cache-Fehler auftreten ). Bei vier Kernen beträgt die Gesamtzeit 4 Sekunden (2 Sekunden * 8 Threads / 4 Kerne).

Ich habe das Problem vereinfacht und die in anderen Antworten erwähnten Overheads (z. B. Kontextwechsel) ignoriert, hoffe jedoch, dass Sie den Punkt erreichen, dass es je nach Datengröße von Vorteil sein kann, mehr Threads als die verfügbare Anzahl von Kernen zu haben. Ich beschäftige mich mit.

someneat
quelle
7

4000 Threads auf einmal sind ziemlich hoch.

Die Antwort lautet ja und nein. Wenn Sie in jedem Thread viel E / A blockieren, können Sie erhebliche Beschleunigungen von bis zu 3 oder 4 Threads pro logischem Kern feststellen.

Wenn Sie jedoch nicht viel blockieren, wird der zusätzliche Overhead beim Threading nur langsamer. Verwenden Sie also einen Profiler und sehen Sie, wo sich die Engpässe in jedem möglicherweise parallelen Teil befinden. Wenn Sie umfangreiche Berechnungen durchführen, hilft mehr als 1 Thread pro CPU nicht weiter. Wenn Sie viel Speicher übertragen, hilft dies auch nicht. Wenn Sie jedoch viel E / A ausführen, z. B. für den Festplatten- oder Internetzugang, helfen ja mehrere Threads bis zu einem gewissen Grad oder machen die Anwendung zumindest reaktionsfähiger.

Earlz
quelle
7

Benchmark.

Ich würde anfangen, die Anzahl der Threads für eine Anwendung zu erhöhen, beginnend bei 1, und dann zu etwa 100 wechseln, drei bis fünf Versuche für jede Anzahl von Threads ausführen und selbst ein Diagramm der Betriebsgeschwindigkeit im Verhältnis zur Anzahl der Threads erstellen .

Sie sollten sicherstellen, dass der Fall mit vier Threads optimal ist und die Laufzeit danach leicht ansteigt, aber möglicherweise nicht. Es kann sein, dass Ihre Anwendung bandbreitenbeschränkt ist, dh der Datensatz, den Sie in den Speicher laden, ist riesig, es treten viele Cache-Fehler usw. auf, sodass 2 Threads optimal sind.

Sie können nicht wissen, bis Sie testen.

mmr
quelle
3

Sie finden heraus, wie viele Threads Sie auf Ihrem Computer ausführen können, indem Sie den Befehl htop oder ps ausführen, der die Anzahl der Prozesse auf Ihrem Computer zurückgibt.

Sie können die Manpage zum Befehl 'ps' verwenden.

man ps

Wenn Sie die Anzahl aller Benutzerprozesse berechnen möchten, können Sie einen der folgenden Befehle verwenden:

  1. ps -aux| wc -l
  2. ps -eLf | wc -l

Berechnung der Anzahl eines Benutzerprozesses:

  1. ps --User root | wc -l

Sie können auch "htop" verwenden [Referenz] verwenden. :

Installation unter Ubuntu oder Debian:

sudo apt-get install htop

Installation unter Redhat oder CentOS:

yum install htop
dnf install htop      [On Fedora 22+ releases]

Wenn Sie htop aus dem Quellcode kompilieren möchten, finden Sie es hier .

Saeed Zahedian Abroodi
quelle
2

Das Ideal ist 1 Thread pro Kern, solange keiner der Threads blockiert.

Ein Fall, in dem dies möglicherweise nicht zutrifft: Auf dem Kern werden andere Threads ausgeführt. In diesem Fall können mehr Threads Ihrem Programm einen größeren Teil der Ausführungszeit einräumen.

Patros
quelle
Es hängt davon ab, ob die Hintergrundprozesse des Benutzers wie Mist ausgeführt werden sollen, während Ihre Anwendung ausgeführt wird. In diesem Fall können Sie einfach eine Echtzeitpriorität für jeden Thread festlegen und die maximale Leistung erhalten. Aber Benutzer mögen Multitasking.
Earlz
2
Nun, wir haben es mit einer magischen, ideal parallelisierbaren Anwendung zu tun. Wenn ich jemals so etwas erschaffen würde, würde ich mich berechtigt fühlen, die CPU so viel zu belasten, wie ich will.
Patros
2

Ein Beispiel für viele Threads ("Thread-Pool") gegenüber einem pro Kern ist die Implementierung eines Webservers unter Linux oder Windows.

Da Sockets unter Linux abgefragt werden, können viele Threads die Wahrscheinlichkeit erhöhen, dass einer von ihnen den richtigen Socket zur richtigen Zeit abfragt - aber die Gesamtverarbeitungskosten sind sehr hoch.

Unter Windows wird der Server mithilfe von E / A-Abschlussports (IOCPs) implementiert, die das Anwendungsereignis steuern: Wenn eine E / A abgeschlossen ist, startet das Betriebssystem einen Standby-Thread, um es zu verarbeiten. Wenn die Verarbeitung abgeschlossen ist (normalerweise mit einer anderen E / A-Operation wie in einem Anforderungs-Antwort-Paar), kehrt der Thread zum IOCP-Port (Warteschlange) zurück, um auf den nächsten Abschluss zu warten.

Wenn keine E / A abgeschlossen ist, muss keine Verarbeitung durchgeführt werden und es wird kein Thread gestartet.

In der Tat empfiehlt Microsoft in IOCP-Implementierungen nicht mehr als einen Thread pro Kern. Alle E / A können an den IOCP-Mechanismus angeschlossen werden. IOCs können bei Bedarf auch von der Anwendung veröffentlicht werden.

Olof Forshell
quelle
Ich weiß nicht, von welchem ​​Linux Sie sprechen, aber meine Blöcke, bis eine Verbindung eintrifft. Ich schlage vor, Sie lesen ein paar Dinge über select () und FD_SET () und ähnliche Funktionen / Makros.
Alexis Wilke
Ok, es gibt also keine asynchrone Form, die sofort zurückkehrt?
Olof Forshell
Von der select () Manpage:timeout is an upper bound on the amount of time elapsed before select() returns. If both fields of the timeval structure are zero, then select() returns immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.
Alexis Wilke
0

Aus rechnerischer und speichergebundener Sicht (wissenschaftliches Rechnen) führen 4000 Threads dazu, dass die Anwendung sehr langsam ausgeführt wird. Ein Teil des Problems ist ein sehr hoher Aufwand für die Kontextumschaltung und höchstwahrscheinlich eine sehr schlechte Speicherlokalität.

Es hängt aber auch von Ihrer Architektur ab. Von dort, wo ich gehört habe, sollen Niagara-Prozessoren in der Lage sein, mehrere Threads auf einem einzigen Kern mit einer fortschrittlichen Pipelining-Technik zu verarbeiten. Ich habe jedoch keine Erfahrung mit diesen Prozessoren.

Anycorn
quelle
0

Hoffe das macht Sinn, überprüfe die CPU und Speicherauslastung und lege einen Schwellenwert fest. Wenn der Schwellenwert überschritten wird, darf kein neuer Thread erstellt werden, da sonst ...

M. Gopal
quelle