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:

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 <assert.h>
#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;
}