Wie wähle ich die beste Anzahl von Threads für Hyperthreading / Multicore?

8

Ich habe etwas peinlich parallelisierbare Arbeit in einer .NET 3.5-Konsolen-App und möchte Hyperthreading und Multi-Core-Prozessoren nutzen. Wie wähle ich die beste Anzahl von Worker-Threads aus, um diese am besten für ein beliebiges System zu nutzen? Wenn es sich zum Beispiel um einen Dual-Core handelt, möchte ich 2 Threads; Quad Core Ich werde 4 Threads wollen. Was ich letztlich bin, ist die Prozessoreigenschaften zu bestimmen, damit ich wissen kann, wie viele Threads zu erstellen sind.

Ich frage nicht, wie man die Arbeit aufteilt oder wie man Threading durchführt. Ich frage, wie ich die "optimale" Anzahl der Threads auf einem beliebigen Rechner ermitteln kann, auf dem diese Konsolen-App läuft.

>     
Colin Burnett 10.06.2009, 12:43
quelle

13 Antworten

9

Sie können Environment.ProcessorCount verwenden, wenn das das einzige ist, was Sie danach. Aber normalerweise ist die Verwendung eines ThreadPools die bessere Option.

Der .NET-Thread-Pool bietet auch Vorkehrungen, um mehr -Threads zuzuweisen, als Sie Kerne haben, um den Durchsatz in bestimmten Szenarien zu maximieren, in denen viele Threads auf die Beendigung von I / O warten.

    
Joey 10.06.2009, 12:46
quelle
15

Ich würde vorschlagen, dass Sie nicht versuchen, es selbst zu bestimmen. Verwenden Sie den ThreadPool und lassen Sie .NET die Threads für Sie verwalten.

    
Mark 10.06.2009 12:46
quelle
4

Die richtige Zahl ist offensichtlich 42 .

Nun zu der ernsthaften Notiz. Benutze einfach immer den Thread-Pool.

1) Wenn Sie eine langwierige Verarbeitung Aufgabe haben (dh CPU-intensiv), die in mehrere Mahlzeiten aufgeteilt werden kann, dann sollten Sie Ihre Aufgabe aufteilen und dann alle einzelnen Arbeitsaufgaben an die < a href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool.queueuserworkitem.aspx"> ThreadPool . Der Thread-Pool nimmt Arbeitselemente auf und beginnt dynamisch mit ihnen zu arbeiten, da er über Selbstüberwachungsfunktionen verfügt, die das Starten neuer Threads nach Bedarf umfassen und bei der Bereitstellung durch Administratoren gemäß den Bereitstellungswebsiteanforderungen konfiguriert, im Gegensatz zur Vorberechnung der Nummern zur Entwicklungszeit. Es stimmt zwar, dass die richtige Partitionierungsgröße Ihrer Verarbeitungsaufgabe die Anzahl der verfügbaren CPUs berücksichtigt, aber die richtige Antwort hängt so sehr von der Art der Aufgabe und den Daten ab, über die in dieser Phase (und darüber hinaus noch nicht einmal gesprochen werden sollte) Die Hauptprobleme sollten Ihre NUMA-Knoten , die Speicherlokalität und die interlocked Cache-Contention und erst danach die Anzahl der Kerne sein ).

2) Wenn Sie E / A (einschließlich DB-Aufrufe) ausführen, sollten Sie asynchrone E / A verwenden und die Aufrufe in ThreadPool abschließen, die als Beendigungsroutinen bezeichnet werden.

Diese beiden sind die einzigen gültigen Gründe, warum Sie mehrere Threads haben sollten, und beide werden am besten mit dem ThreadPool behandelt. Alles andere, einschließlich das Starten eines Threads per 'Anfrage' oder 'Verbindung', sind in der Tat Anti-Muster in der Win32-API-Welt (fork ist ein gültiges Muster in * nix, aber definitiv nicht unter Windows).

Für eine speziellere und viel detailliertere Diskussion des Themas kann ich nur die Rick Vicik Papiere zu diesem Thema empfehlen:

Remus Rusanu 10.06.2009 13:53
quelle
3

Die optimale Anzahl wäre nur die Prozessoranzahl. Optimalerweise würde immer ein Thread auf einer CPU ausgeführt werden (logisch oder physisch), um Kontextwechsel und den damit verbundenen Overhead zu minimieren.

Ob das die richtige Zahl ist, hängt (wie alle gesagt haben) davon ab, was Sie tun. Der threadpool (wenn ich es richtig verstehe) versucht so gut wie möglich, so wenig Threads wie möglich zu verwenden, spinnt aber jedes Mal einen weiteren, wenn ein Thread blockiert.

Die Blockierung ist niemals optimal, aber wenn Sie irgendeine Art von Blockierung durchführen, würde sich die Antwort dramatisch ändern.

Der einfachste und einfachste Weg, gutes (nicht unbedingt optimales) Verhalten zu erzielen, ist der Threadpool. Meiner Meinung nach ist es wirklich schwierig, etwas Besseres zu tun als der Threadpool, also ist das einfach der beste Ort, um anzufangen und nur an etwas anderes zu denken, wenn man zeigen kann, warum das nicht gut genug ist.

    
Tollo 10.06.2009 13:12
quelle
2

Der einzige Weg ist eine Kombination aus Daten- und Codeanalyse basierend auf Leistungsdaten.

Unterschiedliche CPU-Familien und Geschwindigkeiten im Vergleich zur Speichergeschwindigkeit im Vergleich zu anderen Aktivitäten auf dem System werden die Abstimmung unterschiedlich machen.

Möglicherweise ist eine gewisse Selbstabstimmung möglich, aber das bedeutet, dass wir eine Art Live-Performance-Tuning und Selbsteinstellung haben.

    
Richard 10.06.2009 12:46
quelle
2

Eine gute Faustregel ist, da Sie vollständig CPU-gebunden sind, processorCount+1 .

Das ist +1 , weil Sie immer einige Aufgaben erhalten, die gestartet / gestoppt / unterbrochen werden, und n Aufgaben werden fast nie n Prozessoren vollständig ausfüllen.

    
Robert Munteanu 10.06.2009 13:01
quelle
2

Oder sogar besser als der ThreadPool, verwenden Sie .NET 4.0 Task-Instanzen von der TPL. Die Task Parallel Library basiert auf einer Grundlage im .NET 4.0-Framework, die tatsächlich die optimale Anzahl von Threads ermittelt, um die Aufgaben so effizient wie möglich für Sie auszuführen.

    
jerryjvl 10.06.2009 13:50
quelle
1

Ich habe kürzlich etwas dazu gelesen (siehe die akzeptierte Antwort auf diese Frage <) / a> zum Beispiel).

Die einfache Antwort ist, dass Sie das Betriebssystem entscheiden lassen. Es kann viel besser entscheiden, was optimal ist, als Sie können.

Es gibt eine Reihe von Fragen zu einem ähnlichen Thema - die Suche nach "optimalen Anzahl Threads" (ohne die Anführungszeichen) gibt Ihnen ein paar Seiten mit Ergebnissen.

    
ChrisF 10.06.2009 12:47
quelle
1

Ich würde sagen, es hängt auch davon ab, was Sie tun, wenn Sie eine Server-Anwendung machen und dann alles verwenden, was Sie über Environment.ProcessorCount oder ein Thread-Pool ist eine gute Idee. Wenn dies jedoch auf einem Desktop oder einem Computer ausgeführt wird, der nicht für diese Aufgabe vorgesehen ist, möchten Sie möglicherweise einige CPU im Leerlauf lassen, damit der Computer für den Benutzer "funktioniert".

    
EKS 10.06.2009 13:06
quelle
0

Es kann argumentiert werden, dass die beste Möglichkeit, die beste Anzahl von Threads auszuwählen, darin besteht, dass die Anwendung sich selbst profiliert und ihr Threading-Verhalten adaptiv ändert, je nachdem, was die beste Leistung bringt.

    
chaos 10.06.2009 12:47
quelle
0

Ich habe eine einfache App geschrieben, die mehrere Threads verwendet und festgestellt hat, dass sie auf meinem Quad-Core-System die meiste Arbeit in einem bestimmten Zeitraum mit 6 Threads erledigt hat.

Ich denke, der einzige wirkliche Weg, um festzustellen, ist durch Trialing oder Profiling.

    
cjk 10.06.2009 13:00
quelle
0

Zusätzlich zur Prozessoranzahl möchten Sie möglicherweise die Prozessoraffinität des Prozesses berücksichtigen, indem Sie Bits in der Affinitätsmaske zählen, die von der Funktion GetProcessAffinityMask zurückgegeben wird.

    
wkf 10.06.2009 14:03
quelle
0

Wenn beim Ausführen der Threads keine übermäßigen E / A-Verarbeitungs- oder Systemaufrufe auftreten, ist die Anzahl der Threads (mit Ausnahme des Hauptthreads) im Allgemeinen gleich der Anzahl der Prozessoren / Kerne in Ihrem System, andernfalls können Sie Versuchen Sie, die Anzahl der Threads durch Testen zu erhöhen.

    
bill 14.06.2009 19:17
quelle

Tags und Links