Content |
Aufgabe: Matrix-Matrix Produkt für verteilte Matrizen
Für das verteilte Matrix-Matrix Produkt soll hpc::matvec::mm verwendet werden, um lokale Matrix-Blöcke zu multiplizieren. Diese lokalen Produkte haben wiederum die Form
\[C_{\text{local}} \leftarrow \beta C_{\text{local}} + \alpha A_{\text{local}} B_{\text{local}}\quad C_{\text{local}} \in \mathbf{M}^{m \times n},\; A_{\text{local}} \in \mathbf{M}^{m \times bs},\; B_{\text{local}} \in \mathbf{M}^{b_k \times n}.\]Zunächst kann dabei \(b_k = 1\) gewählt werden. Für eine gute Performance sollte aber \(b_k\) zumindest ein Vielfaches von \(M_r\) und \(N_r\) sein. Idealweise sollte \(b_k\) zudem in der Größenordnung von \(\max\{M_c, K_c\}\) gewählt werden.
Vorlagen
Als Vorlage erhaltet ihr einerseits die Signatur für das Matrix-Produkt. Zum Testen sollt ihr das Benchmark-Programm für hpc::matvec::mm selbst anpassen.
Funktion hpc::mpi::mm
#ifndef HPC_MPI_MM_H #define HPC_MPI_MM_H 1 #include <hpc/mpi/gematrix.h> #include <hpc/matvec/mm.h> namespace hpc { namespace mpi { template <typename Alpha, typename TA, typename TB, typename Beta, typename TC, typename Index> void mm(const Alpha &alpha, const GeMatrix<TA,Index> &A, const GeMatrix<TB,Index> &B, const Beta &beta, GeMatrix<TC,Index> &C) { /* ... */ } } } // namespaces mpi, hpc #endif // HPC_MPI_MM_H
Test-Programm
Nochmals: Dies ist das Test-Programm von Session 10. Dies muss zunächst angepasst werden. Da wir aber eine ähnlich Abstarktion für Matrizen verwenden soll eine analoge Vorgehensweise deutlich werden.
#include <cstddef> #include <cstdio> #include "bench.h" #include "ulmblas.h" #include "gemm_refcolmajor.h" #include "gemm_blocked.h" #include "gematrix.h" #ifndef COLMAJOR #define COLMAJOR 1 #endif #ifndef MAXDIM_M #define MAXDIM_M 7000 #endif #ifndef MAXDIM_N #define MAXDIM_N 7000 #endif #ifndef MAXDIM_K #define MAXDIM_K 7000 #endif #ifndef MIN_M #define MIN_M 100 #endif #ifndef MIN_N #define MIN_N 100 #endif #ifndef MIN_K #define MIN_K 100 #endif #ifndef MAX_M #define MAX_M 7000 #endif #ifndef MAX_N #define MAX_N 7000 #endif #ifndef MAX_K #define MAX_K 7000 #endif #ifndef INC_M #define INC_M 100 #endif #ifndef INC_N #define INC_N 100 #endif #ifndef INC_K #define INC_K 100 #endif #ifndef ALPHA #define ALPHA 1.5 #endif #ifndef BETA #define BETA 1.5 #endif int main() { using namespace matvec; typedef double T; StorageOrder order = (COLMAJOR) ? StorageOrder::ColMajor : StorageOrder::RowMajor; GeMatrix<T> A_(MAXDIM_M, MAXDIM_K, order); GeMatrix<T> B_(MAXDIM_K, MAXDIM_N, order); GeMatrix<T> C1_(MAXDIM_M, MAXDIM_N, order); GeMatrix<T> C2_(MAXDIM_M, MAXDIM_N, order); initGeMatrix(A_); initGeMatrix(B_); initGeMatrix(C1_); initGeMatrix(C2_); gecopy(C1_, C2_); // Header-Zeile fuer die Ausgabe printf("%5s %5s %5s ", "m", "n", "k"); printf("%20s %9s", "refColMajor: t", "MFLOPS"); printf("%20s %9s %9s", "blocked GEMM: t", "MFLOPS", "diff"); printf("\n"); bench::WallTime<double> wallTime; for (long m = MIN_M, n = MIN_N, k = MIN_K; m <=MAX_M && n <= MAX_N && k <= MAX_K; m += INC_M, n += INC_N, k += INC_K) { double t, diff; GeMatrixView<T> A = A_(0,0,m,k); GeMatrixView<T> B = B_(0,0,k,n); GeMatrixView<T> C1 = C1_(0,0,m,n); GeMatrixView<T> C2 = C2_(0,0,m,n); printf("%5ld %5ld %5ld ", m, n, k); wallTime.tic(); gemm_ref(ALPHA, A, B, BETA, C1); t = wallTime.toc(); printf("%20.4lf %9.2lf", t, 2.*m/1000*n/1000*k/t); wallTime.tic(); gemm_blk(ALPHA, A, B, BETA, C2); t = wallTime.toc(); diff = asumDiffGeMatrix(C1, C2); printf("%20.4lf %9.2lf %9.1e", t, 2.*m/1000*n/1000*k/t, diff); printf("\n"); } }