Grenzen und Umfang eines MPI-Datentyps

Wenn wir nicht den glücklichen Umstand haben, dass die Matrix in row major mit A.incCol == 1 vorliegt, wenn diese in row major zu übertragen ist, dann ist es prinzipiell möglich, den Datentyp einer Matrix in zwei Schritten zu erzeugen:

Dabei ist jedoch zunächst unklar, wie MPI komplexe Datentypen zu einem Vektor aneinanderreiht. Bei unmittelbar im Speicher hintereinander liegenden Datentypen ist dies klar. Im Falle einer col major-Matrix mit A.incRow == 1 liegen die Zeilen nicht konsekutiv hintereinander im Speicher, sondern überlappen sich mit einem Versatz.

Um zu verstehen, wie MPI diese Dinge betrachtet, sollten wir zur Definition eines Datentyps als Tupelsequenz zurückkehren: \(T = \left\{ (bt_1, o_1), (bt_2, o_2), \dots, (bt_n, o_n) \right\}\),

Angenommen, wir hätten eine \(2 \times 3\)-Matrix in col major. Der Datentyp \(R\) für die erste Zeile würde dann so aussehen: \(R = \left\{ (DOUBLE, 0), (DOUBLE, 16), (DOUBLE, 32) \right\}\). Dann ist \(\mbox{lb}(R) = 0\), \(\mbox{ub}(R) = 40\) und \(\mbox{extent}(R) = \mbox{ub}(R) - \mbox{lb}(R) = 40\). Würden wir jetzt zwei solche Zeilen zu einem Vektor kombinieren, wäre das erste absolute Offset des zweiten Zeilenvektors 40, obwohl dieser bei 8 beginnt.

Die MPI-Bibliothek erlaubt es, von der voreingestellten Berechnung mit Hilfe der Funktion MPI_Type_create_resized abzuweichen:

int MPI_Type_create_resized(MPI_Datatype oldtype, MPI_Aint lb,
                            MPI_Aint extent, MPI_Datatype* newtype);

Hierbei spezifiziert lb die neue untere Grenze \(\mbox{lb}(T)\) und extent den Umfang \(\mbox{extent}(T)\), der in Bytes zu spezifizieren ist. Daraus ergibt sich dann implizit auch \(\mbox{ub}(T)\). Es ist dabei zulässig, den Umfang zu wählen, dass zwei “konsekutiv” folgende Objekte sich überlappen. Im obigen Beispiel der col major-Matrix wäre es entsprechend sinnvoll, dem Umfang auf 8 Bytes zu setzen, da &A(0, 0) und &A(1, 0) nur 8 Bytes voneinander entfernt sind.

Im Trivialfall, dass alle Elemente eines Vektors unmittelbar hintereinander liegen, kann auch MPI_Type_contiguous verwendet werden:

int MPI_Type_contiguous(int count, MPI_Datatype oldtype,
                        MPI_Datatype* newtype);

Aufgabe