Content |
GEMM Packing (Matrix B)
Das Packen der Matrix \(B\) geschieht im Prinzip analog zur Matrix \(A\). Allerdings werden hier aus einem \(k_c \times n_c\) die vertikale Paneele heraus kopiert. Jede Vertikale Paneel besteht theoretisch aus Zeilenvektoren der Länge \(n_r\). In der Praxis kann man den Puffer aber auf zwei Arten interpretieren:
-
Eine \(k_c \times n_c\) Matrix mit vertikalen Paneele, die aus Zeilenvektoren zusammengesetzt sind.
-
Eine \(n_c \times k_c\) Matrix mit horizontalen Paneele, die aus Spaltenvektoren zusammengesetzt sind.
Offensichtlich ist die Matrix im zweiten Fall gerade die Transponierte der Matrix aus dem ersten Fall.
Bespiel
Die Partitionierung der Matrix \(B\) in \(k_c \times n_c\) Blöcke geschieht analog zur Partitionierung von \(A\). Wir betrachten deshalb nur das Packen eines einzelnen Blocks.
Sei \(k_c = 11, n_c = 12\) und \(n_r = 6\). Dann wird
\[\begin{eqnarray*}B &=& \left( \begin{array}{cccccc:cccccc} b_{ 1,1} & b_{ 1,2} & b_{ 1,3} & b_{ 1,4} & b_{ 1,5} & b_{ 1,6} & b_{ 1,7} & b_{ 1,8} & b_{ 1,9} & b_{ 1,10} & b_{ 1,11} & b_{ 1,12} \\ b_{ 2,1} & b_{ 2,2} & b_{ 2,3} & b_{ 2,4} & b_{ 2,5} & b_{ 2,6} & b_{ 2,7} & b_{ 2,8} & b_{ 2,9} & b_{ 2,10} & b_{ 2,11} & b_{ 2,12} \\ b_{ 3,1} & b_{ 3,2} & b_{ 3,3} & b_{ 3,4} & b_{ 3,5} & b_{ 3,6} & b_{ 3,7} & b_{ 3,8} & b_{ 3,9} & b_{ 3,10} & b_{ 3,11} & b_{ 3,12} \\ b_{ 4,1} & b_{ 4,2} & b_{ 4,3} & b_{ 4,4} & b_{ 4,5} & b_{ 4,6} & b_{ 4,7} & b_{ 4,8} & b_{ 4,9} & b_{ 4,10} & b_{ 4,11} & b_{ 4,12} \\ b_{ 5,1} & b_{ 5,2} & b_{ 5,3} & b_{ 5,4} & b_{ 5,5} & b_{ 5,6} & b_{ 5,7} & b_{ 5,8} & b_{ 5,9} & b_{ 5,10} & b_{ 5,11} & b_{ 5,12} \\ b_{ 6,1} & b_{ 6,2} & b_{ 6,3} & b_{ 6,4} & b_{ 6,5} & b_{ 6,6} & b_{ 6,7} & b_{ 6,8} & b_{ 6,9} & b_{ 6,10} & b_{ 6,11} & b_{ 6,12} \\ b_{ 7,1} & b_{ 7,2} & b_{ 7,3} & b_{ 7,4} & b_{ 7,5} & b_{ 7,6} & b_{ 7,7} & b_{ 7,8} & b_{ 7,9} & b_{ 7,10} & b_{ 7,11} & b_{ 7,12} \\ b_{ 8,1} & b_{ 8,2} & b_{ 8,3} & b_{ 8,4} & b_{ 8,5} & b_{ 8,6} & b_{ 8,7} & b_{ 8,8} & b_{ 8,9} & b_{ 8,10} & b_{ 8,11} & b_{ 8,12} \\ b_{ 9,1} & b_{ 9,2} & b_{ 9,3} & b_{ 9,4} & b_{ 9,5} & b_{ 9,6} & b_{ 9,7} & b_{ 9,8} & b_{ 9,9} & b_{ 9,10} & b_{ 9,11} & b_{ 9,12} \\ b_{10,1} & b_{10,2} & b_{10,3} & b_{10,4} & b_{10,5} & b_{10,6} & b_{10,7} & b_{10,8} & b_{10,9} & b_{10,10} & b_{10,11} & b_{10,12} \\ b_{11,1} & b_{11,2} & b_{11,3} & b_{11,4} & b_{11,5} & b_{11,6} & b_{11,7} & b_{11,8} & b_{11,9} & b_{11,10} & b_{11,11} & b_{11,12} \\ \end{array} \right)\\[0.5cm]&=& \left( \begin{array}{c:c} \vec{b}_{ 1}^T & \vec{b}_{12}^T\\ \vec{b}_{ 2}^T & \vec{b}_{13}^T\\ \vec{b}_{ 3}^T & \vec{b}_{14}^T\\ \vec{b}_{ 4}^T & \vec{b}_{15}^T\\ \vec{b}_{ 5}^T & \vec{b}_{16}^T\\ \vec{b}_{ 6}^T & \vec{b}_{17}^T\\ \vec{b}_{ 7}^T & \vec{b}_{18}^T\\ \vec{b}_{ 8}^T & \vec{b}_{19}^T\\ \vec{b}_{ 9}^T & \vec{b}_{20}^T\\ \vec{b}_{10}^T & \vec{b}_{21}^T\\ \vec{b}_{11}^T & \vec{b}_{22}^T\\ \end{array} \right)\end{eqnarray*}\]umkopiert zur zeilenweise gespeicherten Matrix
\[\tilde{B} = \left( \begin{array}{c} \vec{b}_{ 1}^T \\ \vec{b}_{ 2}^T \\ \vec{b}_{ 3}^T \\ \vec{b}_{ 4}^T \\ \vec{b}_{ 5}^T \\ \vec{b}_{ 6}^T \\ \vec{b}_{ 7}^T \\ \vec{b}_{ 8}^T \\ \vec{b}_{ 9}^T \\ \vec{b}_{10}^T \\ \vec{b}_{11}^T \\ \vec{b}_{12}^T \\ \vec{b}_{13}^T \\ \vec{b}_{14}^T \\ \vec{b}_{15}^T \\ \vec{b}_{16}^T \\ \vec{b}_{17}^T \\ \vec{b}_{18}^T \\ \vec{b}_{19}^T \\ \vec{b}_{20}^T \\ \vec{b}_{21}^T \\ \vec{b}_{22}^T \\ \end{array} \right)\]Dies ist bezüglich dem Speicherlayout identisch zu der spaltenweise gespeicherten Matrix:
\[\tilde{B} = \left( \begin{array}{cccccccccccccccccccccc} \vec{b}_{ 1} & \vec{b}_{ 2} & \vec{b}_{ 3} & \vec{b}_{ 4} & \vec{b}_{ 5} & \vec{b}_{ 6} & \vec{b}_{ 7} & \vec{b}_{ 8} & \vec{b}_{ 9} & \vec{b}_{10} & \vec{b}_{11} & \vec{b}_{12} & \vec{b}_{13} & \vec{b}_{14} & \vec{b}_{15} & \vec{b}_{16} & \vec{b}_{17} & \vec{b}_{18} & \vec{b}_{19} & \vec{b}_{20} & \vec{b}_{21} & \vec{b}_{22} \end{array} \right)\]Aufgabe
Erweitert euren Code um das Packen der Matrix \(B\). Ein Grundgerüst sieht so aus:
#include <stdio.h>
#define M 14
#define K 15
#define N 16
#define MC 8
#define KC 11
#define NC 12
#define MR 4
#define NR 6
double A[M*K];
double B[K*N];
double _A[MC*KC];
double _B[KC*NC];
void
initMatrix(int m, int n, double *X, int ldX, int counter)
{
// ... your code here ...
}
void
printMatrix(int m, int n, const double *X, int ldX)
{
// ... your code here ...
}
void
pack_MRxk(int k, const double *A, int incRowA, int incColA, double *buffer)
{
// ... your code here ...
}
void
pack_A(int mc, int kc, const double *A, int incRowA, int incColA,
double *buffer)
{
// ... your code here ...
}
void
pack_kxNR(int k, const double *B, int incRowB, int incColB, double *buffer)
{
// ... your code here ...
}
void
pack_B(int kc, int nc, const double *B, int incRowB, int incColB,
double *buffer)
{
// ... your code here ...
}
int
main()
{
int i, j, mc, kc, nc;
initMatrix(M, K, A, M, 1);
printf("A = \n");
printMatrix(M, K, A, M);
for (j=0; j<K; j+=KC) {
kc = (j+KC<=K) ? KC : K - j;
for (i=0; i<M; i+=MC) {
mc = (i+MC<=M) ? MC : M - i;
printf("Packing A(%d:%d, %d:%d)\n", i+1, i+mc, j+1, j+kc);
pack_A(mc, kc, &A[i+j*M], 1, M, _A);
printf("Buffer: _A = \n");
printMatrix(MR, KC*MC/MR, _A, MR);
}
}
initMatrix(K, N, B, K, M*K+1);
printf("B = \n");
printMatrix(K, N, B, K);
for (j=0; j<N; j+=NC) {
nc = (j+NC<=N) ? NC : N - j;
for (i=0; i<K; i+=KC) {
kc = (i+KC<=K) ? KC : K - i;
printf("Packing B(%d:%d, %d:%d)\n", i+1, i+kc, j+1, j+nc);
pack_B(kc, nc, &B[i+j*K], 1, K, _B);
printf("Buffer: _B = \n");
printMatrix(NR, KC*NC/NR, _B, NR);
}
}
return 0;
}