Wie programmiere ich einen Supercomputer?

in #program7 years ago

Wie programmiere ich einen Supercomputer?

Wir hielten es für notwendig, ein Buch zu schreiben, das Programmiertechniken wieder einführt, die von Anwendungsentwicklern verwendet werden sollten, die auf die aktuellen und zukünftigen Supercomputer der Generation abzielen. Während die Techniken schon lange existieren, sind sich viele der heutigen Entwickler ihrer nicht bewusst. Lass uns das erklären.

Der Supercomputer ist seit seiner Einführung in Form von Seymour Crays CDC 6600 in den frühen 1970er Jahren ein sich wandelndes Ziel für Anwendungsprogrammierer geworden und zwang Entwickler, sich an neue Ansätze anzupassen, zusammen mit den sich ständig ändernden Hardware- und Softwaresystemen. Diese Notwendigkeit der Entwickleranpassung ist besonders auf dem Gebiet des Hochleistungsrechnens (high-performance computing, HPC) auffällig, wo Entwickler typischerweise für die Zielknotenarchitektur optimieren, um die letzte Unze verfügbarer Leistung auszuquetschen. Dies wurde durch den CDC7600 und die Vektor-reichen Systeme fortgesetzt: Cray 1, Cray XMP, YMP und C90.

Dann hat der "Angriff der Killermikros" in den 1990er Jahren alles in den Wahnsinn getrieben. Mit zunehmender Anzahl von Knoten mussten Anwendungsentwickler PVM und dann MPI in Betracht ziehen, um ihre Anwendungen über die Vielzahl von Knoten, die aus serienmäßigen Standard-Chips (COTS-Chips) ohne jegliche Vektorinstruktionen bestehen, parallelisieren zu können. Wie in Abbildung 1 zu sehen ist, wurden die COTS-Chips schneller, als ihre Taktzykluszeit zwischen 1995 und 2010 sank. Anwendungsentwickler mussten sich nicht mehr um die Knotenarchitektur kümmern.

Mit dem Aufkommen von AVX256, AVX512, SVE und GPUs in den letzten fünf Jahren haben Vektoren begonnen, zurück zu kommen. In letzter Zeit erforderten viele Kernsysteme wie Intels Knight's Landing (KNL) sowie angeschlossene Beschleuniger wie die GPU-Reihe von Nvidia eine erneute Überprüfung der Anwendung, um eine bessere Leistung der neuen, leistungsstärkeren Knoten zu erzielen. Da die Anwendung vom Compiler nicht immer vektorisiert und / oder parallelisiert werden konnte, musste der Anwendungsentwickler etwas unternehmen.

Das reichte vom Schreiben wichtiger Kernel in spezialisierten Programmiermodellen wie CUDA für die Nvidia-GPUs bis hin zur Verwendung von Compiler-Direktiven, um dem Compiler zu helfen, den eingegebenen Code auf Benutzerebene in vektorisierten Low-Level-Code für die Prozessoren zu übersetzen. Dann gab es das Problem, all diese Kerne auf dem Knoten zu verwenden / Tausende von Threads für die GPU zu erzeugen. Da das Ausführen von MPI über alle Kerne auf und von den Knoten ziemlich gut funktionierte, mussten die Entwickler für die anfänglichen Multicore-Systeme nicht wirklich mit Threads für gemeinsam genutzten Speicher parallelisieren. Das Einfädeln von Nvidia-Beschleunigern war jedoch unbedingt erforderlich. OpenACC und dann OpenMP 4.5 wurden für eine Performance-portable Lösung für Threading und Vektorisierung für die GPU entwickelt.

Eine weitere Offenbarung in neuen Architekturen ist, dass Speicherhierarchien immer komplexer werden, insbesondere wenn eine Anwendung einen großen Speicherbedarf hat. Knight's Landing sowie Knoten mit angeschlossenen GPU-Beschleunigern haben zwei Speicherebenen, was neue Herausforderungen mit sich bringt, die von Programmierern angegangen werden müssen. Abbildung 2 zeigt die Unterschiede zwischen den Speicherhierarchien von KNL und der gehosteten GPU. Wenn eine Anwendung in den Hochgeschwindigkeitsspeicher passt, wird sie eine hervorragende Speicherleistung genießen. Wenn die Anwendung jedoch mehr Arbeitsspeicher benötigt, muss der Datensatz so verwaltet werden, dass er effizient und zeitnah zwischen den beiden fließt.

Die letzten vier bis fünf Jahre waren ein Kulturschock für diejenigen Entwickler, die auf Produktivität statt Leistung bestanden. Sie stehen nun vor der großen Herausforderung, diese neuen leistungsstarken Knoten effektiv zu nutzen. Wenn sie mit All-MPI-Codes fortfahren und nicht die notwendige Umwandlung in mehrstufigen parallelen Code durchführen (durch Vektorisierung und Threading), hängt ihre Leistung nur von der Anzahl der Kerne auf dem Knoten und dem Taktzyklus ab. Während die Anzahl der Kerne auf dem Knoten langsam steigt, sinkt die Taktrate dieser Kerne, was zu einer geringen Rendite bei neuen Hardware-Investitionen ohne Software-Optimierung führt.

Unser Buch Programmierung für hybride Multi- / Manycore-MPP-Systeme diskutiert die Architektur der neuen Knoten und Programmiertechniken, die Anwendungsentwickler verwenden können, um mehr Leistung zu erhalten. Es wird extrem nützlich für diejenigen Entwickler sein, die jetzt vor der großen Herausforderung stehen, eine erhöhte Leistung von der Vektorfähigkeit des Knotens zu erhalten, sowie eine verbesserte Skalierung über die erhöhte Anzahl von Kernen oder Threading für die GPU. Das Buch betrachtet auch die Speicherhierarchie des KNL und diskutiert verschiedene Ansätze zur Verwaltung der Daten. Schließlich blickt das Buch in die Zukunft, die in vielerlei Hinsicht gleich ist: mehr Kerne mit breiteren Vektoren sowie komplexere Speicherhierarchien.

SOLUTIONS SUPPORT

Sort:  

Hey, just wanted to let you know I gave you an upvote because I appreciate your content! =D See you around

@greentomorrow did not give you an upvote and has made this exact same comment hundreds of times.

Click the flag to downvote this @greentomorrow comment!

greentomorrow.png

Here are a few ways to support @duplibot and help reduce spam and superfluous comments.