Beste Methoden zum Verwalten eines Netzes bei der parallelen Finite-Elemente-Berechnung?

11

Ich entwickle derzeit eine Domänenzerlegungsmethode zur Lösung des Streuproblems. Grundsätzlich löse ich iterativ ein System von Helmholtz-BVPs. Ich diskretisiere die Gleichungen mit der Finite-Elemente-Methode über Dreiecks- oder Tetraedernetzen. Ich entwickle den Code für meine Doktorarbeit. Ich kenne einige der vorhandenen Finite-Elemente-Bibliotheken wie deal.ii oder DUNE und obwohl ich denke, dass sie mit inspirierendem Design und API für Lernzwecke großartig sind, wollte ich meine eigene kleine Anwendung von Grund auf neu entwickeln.

Ich bin an einem Punkt angelangt, an dem meine seriellen Versionen ausgeführt werden, und jetzt möchte ich sie parallelisieren. Schließlich ist es eine der Stärken des Domänenzerlegungs-Frameworks, Algorithmen zu formulieren, die zumindest im Prinzip leicht zu parallelisieren sind. In der Praxis gibt es jedoch viele Details, die berücksichtigt werden müssen. Mesh Management ist einer von ihnen. Wenn die Anwendungen eine hohe Auflösung erreichen und gleichzeitig auf viele CPUs skaliert werden sollen, ist die Replikation eines gesamten Netzes auf jeder CPU ineffizient.

Ich wollte die Entwickler, die an ähnlichen Anwendungen in Hochleistungsrechnerumgebungen arbeiten, fragen, wie sie mit diesem Problem umgehen.

Es gibt eine p4est-Bibliothek für die verteilte Netzverwaltung. Ich brauche AMR nicht, daher könnte es ein Overkill sein, da ich nur an der Verwendung einheitlicher Netze interessiert bin und nicht sicher bin, ob es Dreiecksnetze verfeinern kann. Ich könnte auch einfach ein einheitliches Netz erstellen und es dann in einen der Netzpartitionierer einspeisen und die Ausgabe nachbearbeiten.

Der einfachste Ansatz scheint darin zu bestehen, für jede Partition eine separate Datei zu erstellen, die Netzinformationen enthält, die nur für diese bestimmte Partition relevant sind. Diese Datei würde von einer einzelnen CPU gelesen, die für die Montage des diskreten Systems auf diesem Teil des Netzes verantwortlich wäre. Natürlich müssten einige globale Partitionskonnektivitäts- / Nachbarschaftsinformationen auch in einer Datei gespeichert werden, die von allen CPUs für die Kommunikation zwischen Prozessen gelesen wird.

Welche anderen Ansätze gibt es da draußen? Wenn einige von Ihnen dies mitteilen könnten, welche Methoden werden in der Branche oder bei staatlichen Forschungseinrichtungen im Zusammenhang mit der Behandlung dieses Problems häufig verwendet? Ich bin ziemlich neu in der Programmierung eines parallelen Finite-Elemente-Lösers und wollte ein Gefühl dafür bekommen, ob ich über dieses Problem richtig nachdenke oder nicht und wie andere es angehen. Jeder Rat oder Hinweis auf relevante Forschungsartikel wäre sehr dankbar!

Danke im Voraus!

Midurad
quelle
Wenn Sie nach einem Mesh-Partitionierer suchen, ist METIS eine gute Wahl. Überprüfen Sie auch ParMETIS. Das Verwalten von Netzen ist eine andere Geschichte. ITAPS iMesh kann eine Lösung für Sie sein. Bitte überprüfen Sie auch die Antworten auf meine Frage hier: scicomp.stackexchange.com/questions/4750/…
Krzysztof Bzowski
@KrzysztofBzowski: Hast du vielleicht auch die Scotch Library benutzt? Ich habe mich gefragt, was der Unterschied zwischen Scotch und Metis ist, wenn es um finite Elemente geht. Das iMesh-Projekt scheint sehr interessant zu sein. Ich werde in den nächsten Tagen mehr darüber lesen. Ich weiß über Deal.II und DUNE Bescheid. Ich erinnere mich, dass ich mich vor einiger Zeit mit openMesh befasst habe, aber ich dachte mir, dass es einfacher sein würde, die von mir benötigte Funktionalität von Grund auf neu zu implementieren. Für aufeinanderfolgende Maschen, im Grunde angepasst ich die halbe Kante / Gesichtsdatenstruktur in diesem Papier Link Dank!
Midurad

Antworten:

7

Wenn Sie AMR nicht verwenden und nicht über 1K-4K-Kerne hinaus skalieren möchten, tun Sie dies einfach.

  1. Rang 0 liest das gesamte Netz und partitioniert es mit METIS / Scotch usw. (Hinweis: Dies ist eine serielle Operation).

  2. Rang 0 sendet die Element- / Knotenpartitionierungsinformationen an alle anderen Ränge und gibt den Speicher frei (der zum Speichern des Netzes verwendet wird).

  3. Alle Ränge lesen die Knoten / Elemente, die sie besitzen (einschließlich Geisterknoten), aus derselben Eingabedatei (Hinweis: 2000 Ränge, die auf dieselbe Eingabedatei zugreifen, klingen möglicherweise langsam, sind aber in der Praxis nicht sinnvoll, obwohl dies für das Dateisystem möglicherweise schlecht ist, aber dann für uns mache es nur einmal).

  4. Alle Ränge müssen die lokalen zu globalen Knoten- / Element- / Dof-Zuordnungen für die Anwendung von BCs und das Zusammenstellen von Matrizen erstellen und die Knoten neu nummerieren.

Nachdem alles gesagt und getan ist, sind alle Daten in einem Rang lokal, sodass Sie in der Lage sein sollten, gut zu skalieren (in Bezug auf den Speicher). Ich mache das alles in ungefähr 100 Zeilen (siehe Zeilen 35-132 hier ) in einem kleinen Code von mir.

Wenn Ihr Netz zu groß ist (z. B.> 100-250 Millionen Elemente), als dass Sie es nicht mit METIS auf einem einzelnen Knoten partitionieren können und ParMETIS / PT-Scotch benötigen, müssen Sie es zusätzlich vor allen Kernen parallel partitionieren. Reihen können es lesen. In einem solchen Szenario ist es aus logistischen Gründen möglicherweise einfacher, die Partitionierungsphase vom Hauptcode zu trennen.

Übrigens machen AMR-Bibliotheken normalerweise keine Tet. Auch PETSc ist eine gute Wahl für die Parallelisierung Ihres Codes.

Edit: Siehe auch hier und hier .

stali
quelle
Vielen Dank, dass Sie Ihren Code geteilt haben! Ich werde höchstwahrscheinlich den oben beschriebenen Weg einschlagen. Es scheint am wenigsten kompliziert zu sein und ich habe bereits eine Idee, wie ich es anstellen soll. Darüber hinaus wird es eine gute Übung in der MPI-Programmierung sein. Sie haben erwähnt, dass AMR-Bibliotheken normalerweise keine Tet verarbeiten. Wäre es, weil eine naive Verfeinerung beispielsweise eines Quad-Baums eines Dreiecksnetzes zu einem Netz von schlechter Qualität führen könnte? Das Verfeinern von Quads scheint einfach zu sein, aber das Aufteilen eines Tet in vier Teile scheint schwierig zu sein, wenn man die Qualität erhalten möchte. Gibt es vielleicht einen C ++ - Wrapper für PETSc? Ich kann C verwenden, aber C ++ wäre besser.
Midurad
@midurad Wenn Sie C ++ gegenüber C bevorzugen, sollten Sie Trilinos in Betracht ziehen, eine C ++ - Bibliothek, die mit PETSc vergleichbar ist. Darüber hinaus verfügt Trilinos über ein Paket (Zoltan), mit dem Sie die Netzpartitionierung durchführen können.
Dr_Sam
@midurad Sie benötigen nur sehr wenige MPI-Anrufe, wenn Sie PETSc verwenden. Das Verfeinern von Tets sollte einfach sein, aber der (effiziente) Umgang mit den zugehörigen dynamischen Datenstrukturen erfordert möglicherweise einige Überlegungen und Arbeiten. Sie sollten in der Lage sein, PETSc mit C ++ zu verwenden, aber angesichts Ihrer Anforderungen ist libmesh möglicherweise eine praktikable Option (ich denke, es unterstützt AMR und tets).
stali
Vielen Dank für die Informationen. Das war sehr hilfreich.
Midurad
2

Dies mag Sie nicht überraschen, da ich einen Deal entwickle. II, aber hier ist meine Perspektive: Wenn ich mit Studenten spreche, fordere ich sie normalerweise auf, am Anfang ihren eigenen Prototyp zu entwickeln, damit sie sehen können, wie es gemacht wird. Aber sobald sie etwas Kleines zum Laufen gebracht haben, lasse ich sie eine Bibliothek verwenden, die es ihnen ermöglicht, so viel weiter zu gehen, weil sie das Rad nicht bei jedem Schritt neu erfinden müssen.

In Ihrem Fall haben Sie bereits gesehen, wie Sie einen einfachen Helmholtz-Löser implementieren. Aber Sie werden die nächsten 6 Monate damit verbringen, den dafür erforderlichen Code parallel zu schreiben. Sie werden weitere 3 Monate damit verbringen, kompliziertere Geometrien zu verwenden. Sie verbringen dann weitere 6 Monate, wenn Sie einen effizienten Löser wünschen. Und die ganze Zeit schreiben Sie Code, der bereits von jemand anderem geschrieben wurde und der Sie in gewisser Weise nicht näher an das bringt, was Sie tatsächlich für Ihre Promotion tun müssen: etwas Neues entwickeln, das es noch nicht gab vorher gemacht. Wenn Sie diesen Weg gehen, verbringen Sie 2-3 Jahre Ihrer Doktorarbeit damit, das zu wiederholen, was andere getan haben, und vielleicht 1 Jahr damit, etwas Neues zu tun.

Die Alternative ist, dass Sie jetzt 6 Monate damit verbringen, eine der vorhandenen Bibliotheken zu lernen, aber danach haben Sie 2-3 Jahre Zeit, in denen Sie wirklich neue Dinge tun, Dinge, in denen Sie jede zweite Woche in das Büro Ihres Beraters gehen und ihn / sie zeigen können Sie ist etwas wirklich Neues, das in großem Maßstab läuft oder in anderer Hinsicht einfach sehr cool ist. Ich denke, Sie sehen wahrscheinlich, wohin ich jetzt damit gehe.

Wolfgang Bangerth
quelle
3
Ehrliche Frage, da Sie eindeutig eine Autorität in diesem Bereich sind: Wer wird die nächste Generation von Frameworks wie deal.ii schreiben, wenn niemand in der aktuellen Gruppe von Doktoranden solche Probleme angeht? Wir sehen bereits einen problematischen Trend bei Doktoranden, die noch nie ein Programm zusammengestellt haben. Es ist ein wenig beunruhigend für mich, dass die durchschnittlichen Fähigkeiten von Codeentwicklern bei Computerwissenschaftlern kontinuierlich zu sinken scheinen.
Aurelius
1
Das ist eine faire Frage. Sie brauchen Studenten, die so knochenköpfig und stur sind wie ich :-) Aber meine Antwort lautet: Nur weil wir wahrscheinlich ein paar Leute brauchen, die das tun, heißt das nicht, dass wir alle dazu ermutigen sollten , Jahre ihres Lebens damit zu verbringen, sich zu wiederholen was andere schon umgesetzt haben.
Wolfgang Bangerth
2
Ja, fair genug. IMO, das größte Problem, das die CFD-Forschungswelt in den letzten 20 Jahren zurückgehalten hat, war ein Mangel an Software-Engineering-Talenten und die Ablehnung moderner Software-Praktiken durch die Graubärte. Abgesehen von den Frameworks werden so viele Doktoranden durch schlechten Legacy-Code und die Unfähigkeit, die komplexen Softwareteile, die für moderne numerische Methoden auf moderner Hardware benötigt werden, schnell zu konstruieren, zurückgehalten.
Aurelius
Ich bin mit der Aussage über die Graubärte nicht einverstanden (obwohl meine heutzutage auch grau wird ...). Sie sehen aber auch, dass Sie sich zwischen mürrischen Legacy-Codes oder einer Neuerfindung des Rads entscheiden müssen, wenn Sie einen neuen Studenten haben. Nur sehr wenige Menschen haben Spaß daran, mit der von ihnen geschriebenen Software Erfolg zu haben (der derzeitige Autor hält dies nicht aus), und Sie möchten keinen vielversprechenden Studenten auf diesen Weg schicken, wenn Sie nicht wissen, dass sie daraus eine Karriere machen können.
Wolfgang Bangerth
0

Dies ist keine vollständige Antwort.

Bei der Implementierung paralleler Domänenzerlegungsmethoden sind einige Komplikationen aufgetreten. Erstens kann man viele Prozessoren für eine Subdomäne verwenden oder einen Prozessor mit vielen Subdomänen versorgen, und man möchte möglicherweise beide Paradigmen implementieren. Zweitens erfordert die substrukturierte Form von Domänenzerlegungsmethoden das Trennen der Flächen, Kanten und Scheitelpunkte von Unterdomänen (nicht von Elementen). Ich glaube nicht, dass diese Komplikationen leicht in das parallele Netzmanagement einbezogen werden können. Die Situation wird einfacher, wenn Sie einen Prozessor für eine Subdomain betrachten und die überlappende RAS / RASHO-Methode verwenden. Selbst in diesem Fall sollten Sie Ihr paralleles Layout besser selbst verwalten.

Hui Zhang
quelle