Wie bestimmen die C ++ - STL-Algorithmen (ExecutionPolicy), wie viele parallele Threads verwendet werden sollen?

11

C ++ 17 verbesserte 69 STL-Algorithmen zur Unterstützung der Parallelität durch Verwendung eines optionalen Parameters ExecutionPolicy (als erstes Argument). zB.

%Vor%

Ich vermute, dass der C ++ 17-Standard absichtlich nichts über wie sagt, um die Multi-Threaded-Algorithmen zu implementieren, und es den Autoren überlassen, zu entscheiden, was am besten ist Gedanken, später). Dennoch möchte ich auf hoher Ebene verstehen, welche Probleme bei der Implementierung der parallelen STL-Algorithmen berücksichtigt werden.

Einige Fragen in meinem Kopf beinhalten (sind aber nicht beschränkt auf!):

  • Wie ist die maximale Anzahl von Threads (von der C ++ - Anwendung) bezogen auf die Anzahl der CPU- und / oder GPU-Kerne auf der Maschine?
  • Welche Unterschiede gibt es in der Anzahl der Threads, die jeder Algorithmus verwendet? (Wird jeder Algorithmus immer die gleiche Anzahl von Threads verwenden?)
  • Werden andere parallele STL-Aufrufe in anderen Threads (innerhalb derselben App) berücksichtigt? (zB wenn ein Thread std :: for_each (par, ...) aufruft, wird er mehr / weniger / gleiche Threads verwenden, je nachdem ob ein std :: sort (par, ...) bereits auf einem anderen Thread läuft (s)? Gibt es vielleicht einen Thread-Pool?)
  • Wird berücksichtigt, wie ausgelastet die Kerne aufgrund externer Faktoren sind? (Wenn z. B. 1 Kern sehr beschäftigt ist, sagen wir SETI-Signale analysieren, wird die C ++ - Anwendung die Anzahl der verwendeten Threads reduzieren?)
  • Verwenden einige Algorithmen nur CPU-Kerne? oder nur GPU-Kerne?
  • Ich vermute, dass Implementierungen von Bibliothek zu Bibliothek variieren (Compiler zu Compiler?), selbst Details dazu wären interessant.

Ich verstehe, dass der Sinn dieser parallelen Algorithmen darin besteht, den Programmierer davor abzuschirmen, sich um diese Details kümmern zu müssen. Jedoch würde jede Information, die mir ein hohes geistiges Bild von dem gibt, was in den Bibliotheksaufrufen passiert, geschätzt werden.

    
Scott Smedley 31.10.2017, 05:35
quelle

1 Antwort

1

Disclaimer: Kein Experte, nur neugierig auf diese Dinge ... Korrekturen sind mehr als willkommen

Die meisten dieser Fragen können heute nicht mit dem Standard beantwortet werden (Sie kennen ihn). Die Frage, wie ich sie verstehe, mischt jedoch zwei Konzepte:

C1. Einschränkungen für parallele Algorithmen

C2. Ausführung von Algorithmen

Die ganze C ++ 17 parallele STL-Sache handelt von C1: sie setzt Einschränkungen dafür, wie Befehle und / oder Threads in einer parallelen Berechnung verschachtelt / transformiert werden könnten. Auf der anderen Seite wird C2 standardisiert, das Schlüsselwort ist executor (mehr dazu später).

Für C1 gibt es 3 Standardrichtlinien (in std::execution::seq , par und par_unseq ), die jeder Kombination aus Task- und Befehlsparallelität entsprechen. Wenn Sie beispielsweise eine Ganzzahlakkumulation durchführen, könnte par_unseq verwendet werden, da die Reihenfolge nicht wichtig ist. Für die Gleitpunktarithmetik, bei der die Addition nicht kommutativ ist, wäre eine bessere Anpassung jedoch seq , um zumindest ein deterministisches Ergebnis zu erhalten. Kurz gesagt: Richtlinien legen Einschränkungen für die parallele Berechnung fest, und diese Einschränkungen können möglicherweise von einem intelligenten Compiler ausgenutzt werden.

Wenn Sie andererseits einen parallelen Algorithmus und seine Nebenbedingungen (und möglicherweise nach einer gewissen Optimierung / Transformation) haben, wird executor einen Weg finden, ihn auszuführen. Es gibt Standard-Executoren (zum Beispiel für die CPU) oder Sie können Ihre eigenen erstellen, dann kann die gesamte Konfiguration in Bezug auf Anzahl der Threads, Auslastung, Verarbeitungseinheit usw. eingestellt werden.

Ab heute ist C1 im Standard, aber nicht in C2. Wenn Sie also C1 mit einem kompatiblen Compiler verwenden, können Sie nicht angeben, welches Ausführungsprofil Sie möchten und welche Bibliotheksimplementierung wird für dich entscheiden (vielleicht durch Erweiterungen).

Also, um Ihre Fragen zu beantworten:

(In Bezug auf Ihre ersten 5 Fragen) Per Definition definiert C ++ 17 parallele STL-Bibliothek keine Berechnung, nur Datenabhängigkeit, um mögliche Datenflusstransformationen zu ermöglichen. All diese Fragen werden (hoffentlich) von executor beantwortet, Sie können den aktuellen Vorschlag sehen hier . Es sieht ungefähr so ​​aus:

%Vor%

Auch wenn einige Ihrer Fragen in diesem Vorschlag bereits definiert sind, fühle ich mich nicht sicher, sie hier zu diskutieren (zu neu, zu flüchtig), aber ich ermutige Sie, es zu lesen und Ihre eigene Antwort zu finden;)

(Für den 6.) Es gibt eine Reihe von Bibliotheken, die bereits ähnliche Konzepte implementieren (C ++ executor wurde von einigen von ihnen inspiriert), AFAIK: hpx, Thrust oder Boost.Compute. Ich weiß nicht, wie die letzten beiden tatsächlich implementiert werden, aber für HPX verwenden sie Lightweight-Threads und Sie können das Ausführungsprofil konfigurieren. Außerdem ist die erwartete (noch nicht standardisierte) Syntax des obigen Codes für C ++ 17 im Wesentlichen die gleiche wie in (stark inspiriert von) hpx.

Referenzen:

  1. C ++ 17 Parallelalgorithmen und darüber hinaus von Bryce Adelstein lelbach
  2. Die Zukunft von ISO C ++ Heterogenes Computing von Michael Wong
  3. Keynote C ++ - Executoren, um heterogenes Computing in C ++ von morgen zu ermöglichen von Michael Wong
  4. Executors for C ++ - Eine lange Geschichte von Detlef Vollmann
oxuf 21.03.2018 17:57
quelle