================== Verteilte Matrizen [TOC:2] ================== Die Klasse `hpc::mpi::GeMatrix` soll eine $M \times N$ Matrix darstellen, deren Elemente blockweise auf mehreren Rechen-Knoten liegen koennen. Dabei sollen die Knoten als $m \times n$ Gitter zweidimensional organisiert sein, so dass sich folgende Partionierung ergibt: ---- LATEX --------------------------------------------------------------------- B = \left(\begin{array}{c|c|c|c} B_{0,0} & B_{0,1} & \dots & B_{0,n-1} \\ \hline \vdots & & & \vdots \\ \hline B_{m-1,0} & B_{0,1} & \dots & B_{m-1,n-1} \end{array}\right) -------------------------------------------------------------------------------- Die Partitionierung sei dabei quasi-äquidistant, so dass alle inneren Blöcke die gleiche Anzahl an Zeilen bzw. Spalten besitzen. Durch diese Abstraktion sollen technische Details bezüglich MPI sinnvoll versteckt werden. Sei zum Beispiel - `A` vom Typ `hpc::matvec::GeMatrix` also eine lokale Matrix und - `B` vom Typ `hpc::mpi::GeMatrix` eine verteilte Matrix, dann sollen die _Scatter_ und _Gather_ Operationen durch die Funktionsaufrufe ==== CODE (type=cc) ============================================================ gecopy(A, B); // Scatter gecopy(B, A); // Gather ================================================================================ ausgeführt werden. Die Klasse `hpc::mpi::Grid` =========================== Da der Funktionsaufruf keinen MPI-Kommunikator benötigt, muss diese Information in der Matrix-Klasse `hpc::mpi::GeMatrix` _verkapselt_ enthalten sein. Dazu soll die Klasse `hpc::mpi::Grid` dienen. Die Deklaration der Klasse sei als ==== CODE (type=cc) ============================================================ #ifndef HPC_MPI_GRID_H #define HPC_MPI_GRID_H 1 #include namespace hpc { namespace mpi { struct Grid { Grid(); int numNodeRows, numNodeCols; int nodeRow, nodeCol; int nof_processes, rank; MPI_Comm comm; }; } } // namespaces mpi, hpc #endif // HPC_MPI_GRID_H ================================================================================ vorgegeben. Aufgabe ------- Implementiert die Klasse `hpc::mpi::Grid`. Im Konstruktor soll (analog zur Session 22) mit `MPI_Cart_create` der Kommunikator `comm` für ein zweidimensionales Grid angelegt werden. Die weiteren Attribute sollen anschliessend folgende Werte enthalten: - `numNodeRows`, `numNodeCols` die Anzahl der Zeilen und Spalten des Grids. - `nodeRow`, `nodeCol` die Zeile und Spalte des Prozesses im Grid. Die Klasse `hpc::mpi::GeMatrix` =============================== Eine verteilte Matrix vom Typ `hpc::mpi::GeMatrix` speichert den lokalen Matrix-Block in einer Matrix vom Typ `hpc::matvec::GeMatrix`. Informationen bezüglich der Partitionierung können durch folgende Methoden berechnet werden: - `getRowOffset(r, c)` berechnet den globalen Zeilen-Index des Blockes $A_{r,c}$, - `getColOffset(r, c)` berechnet den globalen Spalten-Index des Blockes $A_{r,c}$, - `getNumRows(r, c)` berechnet die Zeilenanzahl des Blockes $A_{r,c}$, - `getNumCols(r, c)` berechnet den Spaltenanzahl des Blockes $A_{r,c}$, Aufgabe ------- Als Vorlage für eine Implementierung soll folgende Vorlage benutzt werden: ==== CODE (type=cc) ============================================================ #ifndef HPC_MPI_GEMATRIX_H #define HPC_MPI_GEMATRIX_H 1 #include #include #include #include namespace hpc { namespace mpi { template struct GeMatrix { typedef T ElementType; typedef I Index; using StorageOrder = hpc::matvec::StorageOrder; GeMatrix(Index numRows, Index numCols, Grid grid); Index getRowOffset(Index nodeRow) const; Index getColOffset(Index nodeCol) const; Index getNumRows(Index nodeRow) const; Index getNumCols(Index nodeCol) const; Index numRows, numCols; Grid grid; hpc::matvec::GeMatrix buffer; }; } } // namespaces mpi, hpc #endif // HPC_MPI_GEMATRIX_H ================================================================================ Aufgabe: Scatter/Gather ======================= Analog zu Session 22 kann nun die Scatter und Gather Operation umgesetzt werden. Bei einem Scatter sollen die Bloecke eine $M \times N$ Matrix vom Typ `hpc::matvec::GeMatrix` an die lokalen Matrix-Bloecke einer verteilten Matrix vom Type `hpc::mpi::GeMatrix` gesendet werden. Beim Gather soll dies umgekehrt werden. Im Gegensatz zur Session 22 soll dies aber durch folgende Funktionen veranlasst werden: ==== CODE (type=cc) ============================================================ #ifndef HPC_MPI_COPY_H #define HPC_MPI_COPY_H 1 #include #include #include #include #include #include #include namespace hpc { namespace mpi { // scatter template void copy(const hpc::matvec::GeMatrix &A, GeMatrix &B) { /* ... */ } // gather template void copy(const GeMatrix &A, hpc::matvec::GeMatrix &B) { /* ... */ } } } // namespaces mpi, hpc #endif // HPC_MPI_COPY_H ================================================================================ Vorlage zum Testen ------------------ ==== CODE (type=cc) ============================================================ #include #include #include #include #include #include int main(int argc, char** argv) { MPI_Init(&argc, &argv); typedef std::size_t Index; hpc::mpi::Grid grid; Index numRows = 10; Index numCols = 10; hpc::matvec::GeMatrix A(numRows, numCols); hpc::matvec::GeMatrix B(numRows, numCols); hpc::mpi::GeMatrix dA(numRows, numCols, grid); if (grid.nodeRow==0 && grid.nodeCol==0) { for (Index i=0; i doc:index next -> doc:session23/page02