Ich arbeite zur Zeit an einer C++ - Bibliothek für spärliche Matrix/Mathe/iterative Solver für ein Simulationswerkzeug, das ich verwalte. Ich hätte es vorgezogen, ein existierendes Paket zu verwenden, jedoch wurde nach umfangreichen Untersuchungen keine gefunden, die für unseren Simulator geeignet wäre (wir haben uns flens, it ++, PetSC, eigen und einige andere angesehen). Die gute Nachricht ist, dass meine Solver und spärlichen Matrixstrukturen jetzt sehr effizient und robust sind. Die schlechte Nachricht ist, dass ich jetzt die Parallelisierung mit OpenMP untersuche und die Lernkurve ein wenig steil ist.Mehrere Ebenen der Parallelität mit OpenMP - Möglich? Clever? Praktisch?
Die von uns gelöste Domäne kann in Subdomänen aufgeteilt werden, die in einem Blockdiagonalformat zusammenkommen. Unser Speicherschema sieht also aus wie ein Array kleinerer quadratischer Matrizen (Blöcke []) mit jeweils einem für die Subdomäne geeigneten Format (z. B. komprimierte Zeilenspeicherung: CRS, komprimierte diagonale Speicherung: CDS, dicht, usw.). und eine Hintergrundmatrix (die derzeit CRS verwendet), die die Konnektivität zwischen Subdomänen berücksichtigt.
Der "Hotspot" in den meisten (alle?) Iterativen Solvern ist die Matrix-Vektor-Multiplikation, und dies gilt für meine Bibliothek. Daher habe ich mich auf die Optimierung meiner MxV-Routinen konzentriert. Für die Blockdiagonalstruktur, die Pseudo-Code für M * x = b wäre wie folgt:
b=background_matrix*x
start_index = 1;
end_index = 0;
for(i=1:number of blocks) {
end_index=start_index+blocks[i].numRows();
b.range(start_index, end_index) += blocks[i] * x.range(start_index, end_index);
start_index = end_index+1;
}
wo background_matrix ist der Hintergrund (CRS) Matrix, die Blöcke ist die Anordnung von Subdomäne Matrizen und .Range gibt den Teil des Vektors von einem Startindex zu einem Endindex zurück.
Offensichtlich kann (und wurde) die Schleife parallelisiert werden, da die Operationen unabhängig von anderen Iterationen der Schleife sind (die Bereiche sind nicht überlappend). Da wir in einem typischen System 10-15 Blöcke haben, macht 4+ Threads tatsächlich einen signifikanten Unterschied.
Die andere Stelle, an der die Parallelisierung als eine gute Option angesehen wurde, ist die MxV-Operation für jedes Subdomänenspeicherschema (Aufrufe in den Zeilen 1 und 6 im obigen Code). Es gibt viel da draußen bei der Parallelisierung von CRS-, CDS- und dichte Matrix-MxV-Operationen. In der Regel wird ein schöner Boost mit 2 Threads erzielt, mit stark abnehmenden Renditen, wenn mehr Threads hinzugefügt werden.
Ich stelle mir ein Schema vor, bei dem 4 Threads in der Blockschleife für den obigen Code verwendet würden und jeder dieser Threads 2 Threads für die Subdomänen-Lösungen verwenden würde. Ich bin mir jedoch nicht sicher, wie man mit OpenMP den Pool von Threads verwalten kann - ist es möglich, die Anzahl der Threads in einem openmp for force zu begrenzen? Ist diese mehrstufige Parallelität in der Praxis sinnvoll? Alle anderen Gedanken auf, was ich hier vorgeschlagen würde geschätzt (und vielen Dank für das Lesen den ganzen Weg bis zum Ende!)
Welchen Löser haben Sie am Ende benutzt? – Jacob
@ Jacob - das System, das ich löse, hat mehrere verschiedene Arten von Subdomains, die am effizientesten mit einem jacobi-vorkonditionierten GMRES auf einem CRS, ICC-vorkonditioniertem CG-Solve auf einem CDS oder einem direkten dichten Solve gelöst werden. Um das Beste aus jeder Subdomain herauszuholen, endete ich mit einem GMRES-Solve auf dem globalen System, indem ich einen einstufigen, nicht überlappenden Additive Schwarz Preconditioner verwendete, wobei das lokale Solve im Preconditoner der geeignete Solveralgorithmus für ist der Unterdomänentyp. – MarkD
Haben Sie überlegt, was Sie tun werden, wenn Sie etwas größere Systeme lösen wollen oder diese Lösungen schneller haben möchten?OpenMP eignet sich hervorragend für einzelne Shared-Memory-Knoten, aber sobald Sie daran vorbeikommen (aus Gründen der Größe oder einfach die Berechnung in kürzerer Zeit durchführen), werden Sie am Ende etwas anderes wollen, das skalierbar ist. Ich würde vorschlagen, was mein Labor entwickelt (siehe Profil), aber Sie haben bereits erwähnt, dass OpenMP eine steile Lernkurve hat. Unsere Software ist leider immer noch steiler, obwohl es einige Konstrukte gibt, die Dinge natürlicher darstellen können. – Novelocrat