============================================= Scatter/Gather mit ungleichmäßiger Verteilung ============================================= Die Operationen `MPI_Scatter` und `MPI_Gather` setzten voraus, dass jeder Prozess gleich viele Elemente (wie beispielsweise Matrixzeilen) erhält. Was kann getan werden, wenn die Zahl der Zeilen kein Vielfaches der Zahl der Prozesse ist, über die eine Matrix verteilt wird? MPI bietet für diese Fälle Operationen an, bei denen zusätzlich die individuellen Häppchengrößen (zusammen mit den Offsets in `displs[]`) angegeben werden: ---- CODE (type=cpp) ---------------------------------------------------------- int MPI_Scatterv(const void* sendbuf, int sendcounts[], const int displs[], MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm); int MPI_Gatherv(const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, int root, MPI_Comm comm); ------------------------------------------------------------------------------- Aufgabe ======= Es erscheint sinnvoll, Funktionen für das zeilenweise Verteilen von Matrizen anzubieten, die die Parameter soweit wie möglich in Abhängigkeit der übergebenen Matrizen bestimmen. Die Aufteilung kann mit Hilfe eines `hpc::aux::Slices`-Objekt aus der Vorlesungsbibliothek erfolgen. Diese Objekte liefern die fertigen Werte für `sendcounts[]`/`recvcounts[]` und `displs[]`. Die beiden folgenden Funktionen sollen jeweils von `A` nach `B` kopieren. Bei `scatter_by_row` ist `A` die große zu verteilende Matrix und `B` der lokale Ausschnitt. Bei `gather_by_row` ist A der lokale Ausschnitt und `B` die große Matrix, die alle Abschnitte einsammelt. In beiden Fällen ist `A` jeweils `const` deklariert. Da die MPI-Installation auf den Debian-Maschinen im E.44 etwas veraltet ist, erwarten `MPI_Scatterv` und `MPI_Gatherv` noch jeweils `void*` an Stelle von `const void*` beim ersten Argument. Das Problem lässt sich mit einem Cast lösen. Statt `&A(0,0)` einfach `(void*) &A(0,0)` übergeben. Dann wird es vom Übersetzer akzeptiert. ---- CODE (type=cpp) ---------------------------------------------------------- #include #include #include #include #include #include #include template typename std::enable_if< hpc::matvec::IsGeMatrix::value && hpc::matvec::IsGeMatrix::value && std::is_same::value, int>::type scatter_by_row(const MA& A, MB& B, int root, MPI_Comm comm) { /* ... */ } template typename std::enable_if< hpc::matvec::IsGeMatrix::value && hpc::matvec::IsGeMatrix::value && std::is_same::value, int>::type gather_by_row(const MA& A, MB& B, int root, MPI_Comm comm) { /* ... */ } ------------------------------------------------------------------------------- Testen Sie die beiden Funktionen mit Hilfe des folgenden Testprogramms: :import:session22/scatter-gather3.cpp :navigate: up -> doc:index back -> doc:session22/page02 next -> doc:session22/page04