Eine Umfrage unter den Top500 zeigt, dass die Branche einen exponentiellen Anstieg der Prozessorkerne verzeichnet . Die größten Supercomputer verwenden alle MPI für die Kommunikation zwischen Knoten, obwohl es keinen eindeutigen Trend für die Parallelität zwischen Knoten zu geben scheint, mit dem einfachsten (aber nicht unbedingt effizientesten) Ansatz, einen einzelnen MPI-Prozess automatisch auf jeden Kern abzubilden Parallelisierung vom Compiler, OpenMP, pthreads, CUDA, Cilk und OpenCL.
Ich gehöre zu einer Gruppe von Wissenschaftlern, die einen Code pflegen und entwickeln, der auf einigen der größten Supercomputer der Welt verwendet werden kann. Wie kann ich mich bei begrenzter Entwicklerzeit zukunftssicher machen, um von der Leistung der leistungsstärksten Maschine der Welt zu profitieren? Welche Annahmen sollte ich zur Architektur der Prozesskopplung treffen? Welche Paradigmen werden leiden, wenn wir in die Kernära eintreten? Werden partitionierte Sprachen für den globalen Adressraum "in Produktion" auf petascale-Computern verfügbar sein?
quelle
Antworten:
Historische Perspektive
Es ist wirklich unmöglich zu sagen, wie die neuen Paradigmen in der Zukunft aussehen werden, zum Beispiel eine gute historische Perspektive. Ich schlage vor, Ken Kennedys Aufstieg und Fall von HPF zu lesen . Kennedy gibt einen Überblick über zwei aufkommende Muster, MPI im Vergleich zu einem intelligenten Compiler, und erläutert, wie MPI die richtige Anzahl von Early Adopters und Flexibilität hatte, um zu dominieren. HPF hat schließlich seine Probleme behoben, aber es war zu spät.
In vielerlei Hinsicht folgen mehrere Paradigmen wie PGAS und OpenMP demselben HPF-Trend. Die frühen Codes waren nicht flexibel genug, um gut verwendet zu werden, und ließen viel Leistung auf dem Tisch. Das Versprechen, nicht jedes Jota des Parallelalgorithmus schreiben zu müssen, ist jedoch ein attraktives Ziel. Das Streben nach neuen Modellen wird also immer fortgesetzt.
Klare Trends bei der Hardware
Nun wurde der Erfolg von MPI häufig als eng mit der Modellierung der Hardware, auf der es ausgeführt wird, verbunden angeführt. Ungefähr jeder Knoten verfügt über einige wenige Prozesse, und das Weiterleiten der Nachrichten an lokale Punkt-zu-Punkt-Operationen oder durch koordinierte kollektive Operationen ist im Clusterbereich leicht möglich. Aus diesem Grund vertraue ich keinem, der ein Paradigma vorstellt , das neuen Hardwaretrends nicht genau folgt, und tatsächlich war ich von dieser Meinung durch die Arbeit von Vivak Sarakar überzeugt .
In diesem Sinne gibt es drei Trends, die in neuen Architekturen deutlich Fortschritte machen. Lassen Sie mich klarstellen, dass in HPC mittlerweile zwölf verschiedene Architekturen vermarktet werden. Dies war vor weniger als 5 Jahren nur mit x86 möglich. In den kommenden Tagen bieten sich viele Möglichkeiten, Hardware auf unterschiedliche und interessante Weise einzusetzen
Aktuelle Modelle
Das aktuelle Modell ist tatsächlich 3 Ebenen tief. Während es viele Codes gibt, die gut zwei dieser Ebenen verwenden, sind nicht viele aufgetaucht, die alle drei verwenden. Ich glaube, dass man, um erst einmal ins Exascale zu kommen, in die Bestimmung investieren muss, ob Code auf allen drei Ebenen ausgeführt werden kann. Dies ist wahrscheinlich der sicherste Weg, um die aktuellen Trends zu wiederholen.
Lassen Sie mich die Modelle durchlaufen und erläutern, wie sie sich basierend auf den vorhergesagten neuen Hardwareansichten ändern müssen.
Verteilt
Die Player auf der verteilten Ebene fallen größtenteils in MPI- und PGAS-Sprachen. MPI ist derzeit ein klarer Gewinner, aber PGAS-Sprachen wie UPC und Chapel machen Fortschritte im Weltraum. Ein guter Hinweis ist die HPC Benchmark Challenge. PGAS-Sprachen setzen die Benchmarks sehr elegant um.
Der interessanteste Punkt hierbei ist, dass dieses Modell derzeit nur auf Knotenebene funktioniert, es jedoch ein wichtiges Modell innerhalb eines Knotens für gekachelte Architekturen sein wird. Ein Indiz dafür ist der Intel SCC-Chip, der sich grundsätzlich wie ein verteiltes System verhält. Das SCC-Team erstellte eine eigene MPI-Implementierung, und viele Teams konnten Community-Bibliotheken erfolgreich auf diese Architektur portieren.
Um ehrlich zu sein, hat PGAS wirklich eine gute Geschichte, um in diesen Bereich einzutreten. Wollen Sie wirklich MPI Internode programmieren und müssen dann den gleichen Trick Intranode machen? Eine große Sache bei diesen gekachelten Architekturen ist, dass sie unterschiedliche Taktraten auf den Chips und große Unterschiede in der Bandbreite zum Speicher haben, so dass leistungsfähige Codes dies berücksichtigen müssen.
Shared Memory auf dem Knoten
Hier sehen wir, dass MPI oft "gut genug" ist, aber PThreads (und Bibliotheken, die von PThreads wie Intel Parallel Building Blocks abgeleitet sind) und OpenMP werden immer noch häufig verwendet. Die gängige Ansicht ist, dass es eine Zeit geben wird, in der es genügend gemeinsam genutzte Speicher-Threads gibt, die das MPI-Socket-Modell für RPC ausfallen lassen, oder Sie benötigen einen Prozess mit geringerem Gewicht, der auf dem Core ausgeführt wird. Bereits jetzt können Sie die Anzeichen von IBM Bluegene-Systemen erkennen, die Probleme mit Shared Memory MPI haben.
Laut Matt ist die Vektorisierung des seriellen Codes die größte Leistungssteigerung für rechenintensive Codes. Während viele Leute davon ausgehen, dass dies bei Beschleunigern zutrifft, ist dies auch für Maschinen auf Knoten kritisch. Ich glaube, Westmere hat eine 4-fache FPU, daher kann man nur ein Viertel der Flops ohne Vektorisierung erhalten.
Während ich nicht sehe, dass der aktuelle OpenMP gut in diesen Bereich eintritt, gibt es einen Platz für Chips mit geringer Leistung oder Kacheln, um mehr Lichtfäden zu verwenden. OpenMP hat Schwierigkeiten zu beschreiben, wie der Datenfluss funktioniert, und da mehr Threads verwendet werden, sehe ich nur, dass dieser Trend übertrieben wird. Schauen Sie sich nur Beispiele an, was zu tun ist, um ein ordnungsgemäßes Prefetching mit OpenMP zu erzielen.
Sowohl OpenMP als auch PThreads können auf einer ausreichenden Kursstufe die Vektorisierung nutzen, die erforderlich ist, um einen guten Prozentsatz der Peaks zu erhalten. Dazu müssen Sie Ihre Algorithmen jedoch so aufschlüsseln, dass die Vektorisierung auf natürliche Weise erfolgt.
Co-Prozessor
Schließlich hat das Aufkommen des Co-Prozessors (GPU, MIC, Cell Acclerators) Einzug gehalten. Es wird klar, dass kein Weg zum Exascale ohne sie vollständig sein wird. Bei SC11 nutzte jeder Bell-Wettbewerb sie sehr effektiv, um zu den niedrigen Petaflops zu gelangen. Während CUDA und OpenCL den aktuellen Markt dominiert haben, hoffe ich, dass OpenACC- und PGAS-Compiler den Raum betreten.
Nun, um es genauer zu betrachten, besteht ein Vorschlag darin, die Chips mit geringer Leistung mit vielen Co-Prozessoren zu verbinden. Dies wird die mittlere Schicht des aktuellen Stapels ziemlich gut abtöten und Codes verwenden, die Entscheidungsprobleme auf dem Hauptchip handhaben und die Arbeit an die Co-Prozessoren abschieben. Dies bedeutet, dass eine Person, damit Code recht effektiv funktioniert, die Algorithmen in Bezug auf Kernel (oder Codelets) überdenken muss, d. Soweit ich weiß, ist eine Lösung für diese Entwicklung ziemlich offen.
Wie sich dies auf den App-Entwickler auswirkt
Nun zu Ihrer Frage. Wenn Sie sich vor der zunehmenden Komplexität von Exascale-Maschinen schützen möchten, sollten Sie einige Dinge tun:
Wenn Sie heute performant sein möchten, ist MPI + CUDA / OpenCL gut genug, aber UPC ist auf dem Weg dorthin. Es ist also keine schlechte Idee, sich ein paar Tage Zeit zu nehmen und es zu lernen. OpenMP unterstützt Sie beim Einstieg, führt jedoch zu Problemen, sobald der Code überarbeitet werden muss. PThreads erfordert das vollständige Umschreiben Ihres Codes in seinen Stil. Damit ist MPI + CUDA / OpenCL das aktuell beste Modell.
Was hier nicht besprochen wird
Während all dieses Gerede von Exascale nett ist, ist etwas, das hier nicht wirklich diskutiert wird, das Ein- und Ausschalten von Daten auf den Maschinen. Obwohl es viele Fortschritte bei Speichersystemen gegeben hat, sehen wir sie nicht in Commodity-Clustern (einfach zu teuer). Da datenintensives Computing immer mehr in den Fokus aller Super-Computing-Konferenzen gerückt ist, ist mit einer größeren Bewegung in den Bereich mit hoher Speicherbandbreite zu rechnen.
Dies führt zu dem anderen Trend, der eintreten könnte (wenn die richtigen Finanzierungsagenturen einbezogen werden). Die Maschinen werden sich immer mehr auf die erforderliche Art der Datenverarbeitung spezialisieren. Wir sehen bereits, dass "datenintensive" Maschinen von der NSF finanziert werden, aber diese Maschinen befinden sich auf einer anderen Strecke als die Exascale Grand Challenge 2019.
Dies wurde länger als erwartet. Fragen Sie nach Referenzen, wo Sie sie in den Kommentaren benötigen
quelle
Beginnen wir mit der Erörterung einer Strategie für Intranode-Code (Computing, bei dem die Verbindung nicht berührt wird), da MPI meiner Meinung nach eine gute Wahl für Internode-Code ist. Ich halte es für sinnlos, über Knoten mit weniger als 100 Kernen zu sprechen, also zumindest über eine aktuelle GPU oder MIC.
Es ist eine Tatsache, dass Pthreads alleine keine maximale Leistung auf einem modernen Chip erzielen können, da Sie die Vektoreinheit nutzen müssen (wahr seit dem ersten Cray). Auf Intel und AMD kann man Intrinsics verwenden, aber diese sind nicht portabel und meiner Meinung nach klobig. CUDA und OpenCL verfügen über eine in die Bibliothek integrierte Vektorisierung, die es einfach macht, maximale Leistung zu erzielen. Die gesamte neue Hardware, die mir bekannt ist, hat diese Vektoranforderung, daher sollte jede Lösung dies berücksichtigen. Für mich ist CUDA / OpenCL der aktuelle Weg.
Als nächstes werden alle diese Maschinen NUMA sein, was schwieriger zu programmieren ist, aber ich denke, die Kernel-Strategie funktioniert. Sie teilen Arbeit und Daten in kleine Einheiten auf. Diese werden wahrscheinlich automatisch geplant, wie dies derzeit in CUDA und OpenCL der Fall ist, aber Sie können Abhängigkeiten angeben. Bei Problemen, die zum Streaming-Paradigma passen, kann dieses Chunking auch automatisch durchgeführt werden. Intel TBB tut dies, aber ich bevorzuge den Ansatz einer höheren Bibliothek, beispielhaft dargestellt durch Thrust und Cusp , die auf CUDA oder (bald) TBB abzielen können.
quelle
Ich werde eine kürzere Antwort als einige meiner geschätzten Kollegen in diesem Thread versuchen ;-)
Meine Botschaft an alle meine Schüler ist immer, dass Entwicklerzeit wertvoller ist als CPU-Zeit. Das heißt, wenn Sie Zeit haben, 100% des Codes bei 80% Effizienz für die Ausführung auf großen Maschinen zu konvertieren - mit einem High-Level-Ansatz -, sind Sie besser dran als mit einem zeitaufwendigen Low-Level Ansatz, der Ihnen 100% Effizienz auf 20% Ihres Codes gibt. Infolgedessen bin ich ein großer Fan von hochrangigen Bibliotheken. Mein Favorit in diesem Bereich sind die Threading-Bausteine (TBB), da ich damit Algorithmen an den äußersten Schleifen und auf hoher Ebene betrachten kann. Es kann auch all die Dinge tun, die Sie mit pthreads tun möchten, ohne sich mit OS-Funktionen usw. herumschlagen zu müssen. - also kein OpenMP,
Ich kann nicht mit Autorität über OpenCL, CUDA usw. sprechen.
quelle
Die zuvor veröffentlichten Antworten sind ausgezeichnet, haben sich jedoch hauptsächlich auf die Knotenarchitektur konzentriert. Dies spiegelt meines Erachtens die Tatsache wider, dass MPI in den meisten Fällen als ausreichend für die Internode-Programmiermodelle angesehen wird und dass es sich um eine Intranode-Parallelität handelt, mit der wir zu kämpfen haben.
Hier sind meine Versuche, zwei Fragen zu beantworten, die noch nicht oder nur begrenzt beantwortet wurden:
Welche Annahmen sollte ich zur Architektur der Prozessverbindung treffen?
Ich werde drei Eigenschaften von Netzwerken betrachten:
Die Latenz ist umgekehrt proportional zur Frequenz. Wir wissen, dass die Frequenzskalierung stagniert hat. Man kann daher den Schluss ziehen, dass die Latenz in Zukunft wahrscheinlich nicht signifikant abnehmen wird. Die MPI-Send-Recv-Latenz auf Blue Gene / Q beträgt ungefähr 2 us, was 3200 Zyklen entspricht. Mehr als die Hälfte dieser Latenz ist Software, aber ein Großteil davon wird vom MPI-Standard benötigt. Durch eine umfassende Optimierung kann die Latenz auf nahezu 1 us verringert werden, insbesondere wenn behauptet werden kann, dass keine MPI-Platzhalter verwendet werden.
In jedem Fall beträgt die Hardware-Latenz für die Paketinjektion auf Blue Gene- und Cray-Systemen etwa 1 us. Wenn überhaupt, macht es die Erhöhung der Parallelität auf Knotenebene schwierig, diese Zahl so niedrig zu halten, aber ich bin optimistisch, dass Hardwareentwickler auf absehbare Zeit Wege finden werden, die Latenz unter 5 zu halten.
Die Netzwerkbandbreite wird geringfügig erhöht, indem die Anzahl der Netzwerkverbindungen erhöht wird. Dies ist jedoch nur ein Teil der Geschichte. Man legt 1000 ausgehende Links auf einen Knoten und kann sie nicht verwenden, wenn die Prozessoren das Netzwerk nicht mit voller Bandbreite betreiben können. Beispielsweise haben einige Supercomputer einen Engpass im Bus (z. B. HyperTransport) und nicht im Netzwerk, was die Einspeisungsbandbreite betrifft.
Der Netzwerkbandbreite sind keine grundlegenden, sondern nur praktische Grenzen gesetzt. Bandbreite kostet Geld und Strom. Systementwickler müssen die Kompromisse zwischen der Netzwerkbandbreite und anderen Teilen der Maschine berücksichtigen, wenn sie zukünftige Systeme entwickeln. Viele Codes sind nicht auf die Netzwerkbandbreite beschränkt, sodass es unwahrscheinlich ist, dass wir in Zukunft Maschinen mit einer dramatisch höheren Bandbreite pro Verbindung sehen. Die Bandbreite pro Knoten sollte sich jedoch proportional zur Rechenleistung erhöhen, sodass mehrere Verbindungen pro Knoten erforderlich sind, um eine Skalierung durchzuführen.
Die dritte Eigenschaft von Netzwerken, die in formalen Modellen häufig übersehen wird, ist, wie viele Nachrichten gleichzeitig gesendet werden können. Ein Netzwerk mit einer Latenz von 1 ns und / oder einer Bandbreite von 1 TB / s, das jeweils nur eine Nachricht senden kann, wäre für die meisten Anwendungen völlig nutzlos. Es ist wichtig, in der Lage zu sein, viele Nachrichten von vielen Threads gleichzeitig zu senden, damit das Netzwerk bei Konflikten nicht zusammenbricht. Sowohl Cray- als auch Blue-Gene-Systeme erreichen jetzt mehr als 1 MMPS (Millionen Nachrichten pro Sekunde). Ich kann mich nicht an die genauen Zahlen erinnern, aber beide können mit kleinen Nachrichten einen signifikanten Bruchteil der Spitzenbandbreite erreichen. Ein ideales Netzwerk ist möglicherweise in der Lage, die maximale Bandbreite mit Nachrichten beliebiger Größe zu erreichen. In der Praxis ist dies jedoch aufgrund des Paketheaders und des damit verbundenen Buchhaltungsaufwands nicht möglich. Jedoch,
Dies ist eine unvollständige und unvollständige Antwort. Andere sind willkommen, zu versuchen, es zu verbessern oder Dinge vorzuschlagen, die ich verbessern sollte.
Werden partitionierte Sprachen für den globalen Adressraum "in Produktion" auf petascale-Computern verfügbar sein?
Cray XE-, XK- und XC-Systeme verfügen über einen UPC- und CAF-Compiler in Produktionsqualität. Blue Gene-Systeme können mit XLUPC und XLCAF geliefert werden, aber niemand fragt danach, so dass es nicht geliefert wird. PERCS verfügt über produktionsfähige XLUPC- und XLCAF-Compiler, jedoch über keine großtechnischen Installationen, die für die Wissenschaft zugänglich sind.
Coarrays sind Teil von Fortran 2008, obwohl die Implementierungen in Intel und GNU Fortran noch nicht von hoher Qualität sind. Die Intel-Implementierung soll funktionieren, aber auch ziemlich langsam sein (es gibt ein Papier bei PGAS12 darüber).
Was das PGAS-Programmiermodell betrifft (da Programmiermodelle - keine Programmiersprachen - Gegenstand der ursprünglichen Frage sind), ist die Global Arrays-Bibliothek in vielen Fällen eine vernünftige Annäherung an die Produktionsqualität. Als Laufzeitumgebung ist es nicht so robust wie MPI, aber in Bezug auf die Qualität der Implementierungen ist MPI ziemlich einzigartig. Die ARMCI-MPI-Implementierung von ARMCI macht Global Arrays viel stabiler, wenn auch in einigen Fällen langsamer.
Mit MPI-3 RMA ist es relativ einfach, Konstrukte im PGAS-Stil in Produktionsqualität zu implementieren. Wenn jemand eine neue Frage dazu stellt, würde ich diese gerne beantworten.
quelle
Sehr große Mengen an Kernen eröffnen auch eine triviale, aber überraschend nützliche Perspektive - nur um damit viele Iterationen der gesamten Simulation durchzuführen.
Ein wesentlicher Teil der Computerforschung besteht heutzutage darin, einen Parameterraum zu scannen, einen großen Pool von Anfangsbedingungen zu screenen oder eine Verteilung einiger Ergebnisse in einer Resampling-Weise zu berechnen. all diese aufgaben sind peinlich parallel und somit amdahlsicher.
quelle
Ich vermute, dass selbst die durchdachtesten Antworten auf diese Frage in fünf bis zehn Jahren veraltet sein werden. Angesichts der Unsicherheit zukünftiger Programmierparadigmen lohnt es sich möglicherweise nicht, viel Zeit darauf zu verwenden, die Codebasis vorab zu optimieren.
quelle
Ich wollte gerade diese Antwort auf diese Frage posten , aber sie wurde als Duplikat dieser Frage geschlossen.
Das hört sich vielleicht ein bisschen salomonisch an, aber meiner Erfahrung nach gehört die Zukunft hybriden Ansätzen, bei denen mehrere Multicore-Knoten mit gemeinsam genutztem Speicher, auf denen Multithread-Kernel ausgeführt werden, über ein Paradigma mit verteiltem Speicher wie MPI verbunden sind.
Es gibt jedoch einige Probleme, und sie betreffen überhaupt nicht die Hardware. Erstens sind die meisten Parallelprogrammierer stark in MPI-Codes investiert und zögern sehr, Teile oder die gesamte Codebasis unter Verwendung eines neuen Paradigmas neu zu implementieren. Der Mangel an Menschen, die Shared-Memory-Ansätze verwenden, führt zu langsameren Fortschritten bei den Algorithmen für diesen Bereich, was jede Investition noch sinnloser erscheinen lässt.
Ein zweites Problem ist, dass jeder die Parallelität von gemeinsam genutztem Speicher mit OpenMP in Verbindung bringt . Während OpenMP eine nette schnelle und schmutzige Methode ist, um kleine, einfache Probleme auf einer kleinen Anzahl von Prozessoren zu lösen, ist es ein absolut schreckliches Programmiermodell für echte Parallelität von gemeinsam genutztem Speicher. Obwohl wir alle irgendwann eine Reihe einfacher und effizienter Paradigmen für die parallele Programmierung kennengelernt haben, z. B. Thread-Pools oder Scheduler , sind diese nicht einfach mit OpenMP zu implementieren, und ehrlich gesagt ist dies nicht die Art von Parallelität, die es gibt OpenMP verleitet Programmierer zur Verwendung.
Zusammenfassend ist die Barriere für den Übergang von einem rein verteilten Speicher zu einem rein / teilweise gemeinsam genutzten Speicherparadigma ziemlich hoch. Wenn Sie Threads effizient nutzen möchten, müssen Sie OpenMP vergessen und Threads und Nebenläufigkeiten selbst verwalten (hallo pthreads , auf Wiedersehen Fortran).
Aber warum überhaupt zu einem hybriden Ansatz übergehen? Nun, obwohl sich MPI auf Tausende von Kernen skalieren lässt, ist das zugrunde liegende Modell eines von Synchronität in Schritten und statischen Kommunikationsmustern. Dies ist gut für einige Probleme, z. B. Simulationen mit Milliardenpartikeln, aber nicht optimal für schwierigere oder feinkörnigere Probleme. Shared-Memory-Paradigmen erleichtern den dynamischen Lastausgleich und / oder die asynchrone Kommunikation erheblich, erfordern jedoch einen erheblichen Programmieraufwand.
quelle