Content

Lösungsvorschlag

In hpc_project.tgz ist jetzt die Cache-optimierte Implementierung der GEMM-Operation enthalten. Wesentliche Änderungen:

Benchmark durchführen

Um den Benchmark durchzuführen, muss in hpc_project/ulmblas eine statische Bibliothek für ulmBLAS erzeugt werden:

$shell> pwd
/home/numerik/hpc/ss16/session08/example02/hpc_project/ulmblas
$shell> make
gcc -Wall -mavx -Ofast -I ..   -c -o level3.o level3.c
gcc -Wall -mavx -Ofast -I ..   -c -o lu.o lu.c
gcc -Wall -mavx -Ofast -I ..   -c -o level1.o level1.c
gcc -Wall -mavx -Ofast -I ..   -c -o level2.o level2.c
as   -o ugemm_4_8.o ugemm_4_8.s
ar cru ../ulmblas.a level3.o lu.o level1.o level2.o  ugemm_4_8.o
ranlib ../ulmblas.a
$shell> 

Anschließend kann im bench-Verzeichnis der Benchmark erzeugt werden:

$shell> pwd
/home/numerik/hpc/ss16/session08/example02/hpc_project/bench
$shell> make
gcc -Wall -mavx -Ofast -I ..   -c -o aux.o aux.c
gcc -Wall -mavx -Ofast -I ..   -c -o refblas.o refblas.c
gcc -Wall -mavx -Ofast -I ..   -c -o errbound.o errbound.c
gcc -Wall -mavx -Ofast -I ..  aux.o  refblas.o  errbound.o -o bench_dgemm_4_8 bench_dgemm_4_8.c ../ulmblas.a
rm refblas.o aux.o errbound.o
$shell> 

Wie üblich kann ein Plot erzeugt werden, indem die Ausgabe zunächst in eine Datei umgelenkt wird und mit einem GNUplot-Skript verarbeitet wird:

$shell> ./bench_dgemm_4_8 > report.gemm_avx
$shell> gnuplot plot.gemm
$shell> 

Damit erhält man:

Assembler-Code für AVX

#  void
#  gemm_micro(long   k,
#             double alpha,
#             double *A,
#             double *B,
#             double beta,
#             double *C, long incRowC, long incColC);
.globl ugemm_4_8
ugemm_4_8:

#  Arguments:
#           %rdi     long           k
#           %xmm0    double         alpha
#           %rsi     double         *A
#           %rdx     double         *B
#           %xmm1    double         beta
#           %rcx     double         *C
#           %r8      long           incRowC
#           %r9      long           incColC



        vmovlpd                 %xmm0,        -8(%rsp)                          # push alpha
        vmovlpd                 %xmm1,       -16(%rsp)                          # push beta

        movq                    %rax,        -24(%rsp)
        movq                    %rbx,        -32(%rsp)

        vxorpd                  %ymm8,          %ymm8,          %ymm8
        vxorpd                  %ymm9,          %ymm9,          %ymm9
        vxorpd                  %ymm10,         %ymm10,         %ymm10
        vxorpd                  %ymm11,         %ymm11,         %ymm11
        vxorpd                  %ymm12,         %ymm12,         %ymm12
        vxorpd                  %ymm13,         %ymm13,         %ymm13
        vxorpd                  %ymm14,         %ymm14,         %ymm14
        vxorpd                  %ymm15,         %ymm15,         %ymm15

        jmp     check
loop:
        vbroadcastsd        0*8(%rsi),          %ymm0
        vbroadcastsd        1*8(%rsi),          %ymm1
        vbroadcastsd        2*8(%rsi),          %ymm2
        vbroadcastsd        3*8(%rsi),          %ymm3
        vmovapd            0*32(%rdx),          %ymm4
        vmovapd            1*32(%rdx),          %ymm5

        vmulpd                  %ymm0,          %ymm4,          %ymm6
        vmulpd                  %ymm0,          %ymm5,          %ymm7
        vaddpd                  %ymm6,          %ymm8,          %ymm8
        vaddpd                  %ymm7,          %ymm9,          %ymm9

        vmulpd                  %ymm1,          %ymm4,          %ymm6
        vmulpd                  %ymm1,          %ymm5,          %ymm7
        vaddpd                  %ymm6,          %ymm10,         %ymm10
        vaddpd                  %ymm7,          %ymm11,         %ymm11

        vmulpd                  %ymm2,          %ymm4,          %ymm6
        vmulpd                  %ymm2,          %ymm5,          %ymm7
        vaddpd                  %ymm6,          %ymm12,         %ymm12
        vaddpd                  %ymm7,          %ymm13,         %ymm13

        vmulpd                  %ymm3,          %ymm4,          %ymm6
        vmulpd                  %ymm3,          %ymm5,          %ymm7
        vaddpd                  %ymm6,          %ymm14,         %ymm14
        vaddpd                  %ymm7,          %ymm15,         %ymm15

        addq                    $32,            %rsi
        addq                    $64,            %rdx
        decq                    %rdi
check:
        testq                   %rdi,           %rdi
        jg                      loop


        vbroadcastsd         -8(%rsp),          %ymm5                           # alpha
        vmulpd                  %ymm5,          %ymm8,          %ymm8
        vmulpd                  %ymm5,          %ymm9,          %ymm9
        vmulpd                  %ymm5,          %ymm10,         %ymm10
        vmulpd                  %ymm5,          %ymm11,         %ymm11
        vmulpd                  %ymm5,          %ymm12,         %ymm12
        vmulpd                  %ymm5,          %ymm13,         %ymm13
        vmulpd                  %ymm5,          %ymm14,         %ymm14
        vmulpd                  %ymm5,          %ymm15,         %ymm15

        leaq                   (,%r8,8),       %r8
        leaq                   (,%r9,8),       %r9

        leaq                   (,%r9,2),       %r10
        leaq                   (%r10,%r9),     %r11
        leaq                   (%rcx,%r10,2),  %rdx

        vbroadcastsd        -16(%rsp),         %ymm7                            # beta

        # check if beta == 0
        vxorpd                  %ymm0,         %ymm0,           %ymm0
        vucomisd                %xmm0,         %xmm7
        je                      beta_zero

        # case: beta != 0

        # update C(0,:)
        vmovlpd                (%rcx),         %xmm0,           %xmm0
        vmovhpd                (%rcx,%r9),     %xmm0,           %xmm0
        vmovlpd                (%rcx,%r10),    %xmm1,           %xmm1
        vmovhpd                (%rcx,%r11),    %xmm1,           %xmm1
        vmovlpd                (%rdx),         %xmm2,           %xmm2
        vmovhpd                (%rdx,%r9),     %xmm2,           %xmm2
        vmovlpd                (%rdx,%r10),    %xmm3,           %xmm3
        vmovhpd                (%rdx,%r11),    %xmm3,           %xmm3

        vmulpd                  %xmm7,         %xmm0,           %xmm0
        vmulpd                  %xmm7,         %xmm1,           %xmm1
        vmulpd                  %xmm7,         %xmm2,           %xmm2
        vmulpd                  %xmm7,         %xmm3,           %xmm3

        vextractf128            $1,            %ymm8,           %xmm4
        vextractf128            $1,            %ymm9,           %xmm5

        vaddpd                  %xmm0,         %xmm8,           %xmm0
        vaddpd                  %xmm1,         %xmm4,           %xmm1
        vaddpd                  %xmm2,         %xmm9,           %xmm2
        vaddpd                  %xmm3,         %xmm5,           %xmm3

        vmovlpd                 %xmm0,        (%rcx)
        vmovhpd                 %xmm0,        (%rcx,%r9)
        vmovlpd                 %xmm1,        (%rcx,%r10)
        vmovhpd                 %xmm1,        (%rcx,%r11)
        vmovlpd                 %xmm2,        (%rdx)
        vmovhpd                 %xmm2,        (%rdx,%r9)
        vmovlpd                 %xmm3,        (%rdx,%r10)
        vmovhpd                 %xmm3,        (%rdx,%r11)

        # update pointers rcx, rdx to the next row
        addq                    %r8,           %rcx
        addq                    %r8,           %rdx

        # update C(1,:)
        vmovlpd                (%rcx),         %xmm0,           %xmm0
        vmovhpd                (%rcx,%r9),     %xmm0,           %xmm0
        vmovlpd                (%rcx,%r10),    %xmm1,           %xmm1
        vmovhpd                (%rcx,%r11),    %xmm1,           %xmm1
        vmovlpd                (%rdx),         %xmm2,           %xmm2
        vmovhpd                (%rdx,%r9),     %xmm2,           %xmm2
        vmovlpd                (%rdx,%r10),    %xmm3,           %xmm3
        vmovhpd                (%rdx,%r11),    %xmm3,           %xmm3

        vmulpd                  %xmm7,         %xmm0,           %xmm0
        vmulpd                  %xmm7,         %xmm1,           %xmm1
        vmulpd                  %xmm7,         %xmm2,           %xmm2
        vmulpd                  %xmm7,         %xmm3,           %xmm3

        vextractf128            $1,            %ymm10,          %xmm4
        vextractf128            $1,            %ymm11,          %xmm5

        vaddpd                  %xmm0,         %xmm10,          %xmm0
        vaddpd                  %xmm1,         %xmm4,           %xmm1
        vaddpd                  %xmm2,         %xmm11,          %xmm2
        vaddpd                  %xmm3,         %xmm5,           %xmm3

        vmovlpd                 %xmm0,        (%rcx)
        vmovhpd                 %xmm0,        (%rcx,%r9)
        vmovlpd                 %xmm1,        (%rcx,%r10)
        vmovhpd                 %xmm1,        (%rcx,%r11)
        vmovlpd                 %xmm2,        (%rdx)
        vmovhpd                 %xmm2,        (%rdx,%r9)
        vmovlpd                 %xmm3,        (%rdx,%r10)
        vmovhpd                 %xmm3,        (%rdx,%r11)

        # update pointers rcx, rdx to the next row
        addq                    %r8,           %rcx
        addq                    %r8,           %rdx

        # update C(2,:)
        vmovlpd                (%rcx),         %xmm0,           %xmm0
        vmovhpd                (%rcx,%r9),     %xmm0,           %xmm0
        vmovlpd                (%rcx,%r10),    %xmm1,           %xmm1
        vmovhpd                (%rcx,%r11),    %xmm1,           %xmm1
        vmovlpd                (%rdx),         %xmm2,           %xmm2
        vmovhpd                (%rdx,%r9),     %xmm2,           %xmm2
        vmovlpd                (%rdx,%r10),    %xmm3,           %xmm3
        vmovhpd                (%rdx,%r11),    %xmm3,           %xmm3

        vmulpd                  %xmm7,         %xmm0,           %xmm0
        vmulpd                  %xmm7,         %xmm1,           %xmm1
        vmulpd                  %xmm7,         %xmm2,           %xmm2
        vmulpd                  %xmm7,         %xmm3,           %xmm3

        vextractf128            $1,            %ymm12,          %xmm4
        vextractf128            $1,            %ymm13,          %xmm5

        vaddpd                  %xmm0,         %xmm12,          %xmm0
        vaddpd                  %xmm1,         %xmm4,           %xmm1
        vaddpd                  %xmm2,         %xmm13,          %xmm2
        vaddpd                  %xmm3,         %xmm5,           %xmm3

        vmovlpd                 %xmm0,        (%rcx)
        vmovhpd                 %xmm0,        (%rcx,%r9)
        vmovlpd                 %xmm1,        (%rcx,%r10)
        vmovhpd                 %xmm1,        (%rcx,%r11)
        vmovlpd                 %xmm2,        (%rdx)
        vmovhpd                 %xmm2,        (%rdx,%r9)
        vmovlpd                 %xmm3,        (%rdx,%r10)
        vmovhpd                 %xmm3,        (%rdx,%r11)

        # update pointers rcx, rdx to the next row
        addq                    %r8,           %rcx
        addq                    %r8,           %rdx

        # update C(3,:)
        vmovlpd                (%rcx),         %xmm0,           %xmm0
        vmovhpd                (%rcx,%r9),     %xmm0,           %xmm0
        vmovlpd                (%rcx,%r10),    %xmm1,           %xmm1
        vmovhpd                (%rcx,%r11),    %xmm1,           %xmm1
        vmovlpd                (%rdx),         %xmm2,           %xmm2
        vmovhpd                (%rdx,%r9),     %xmm2,           %xmm2
        vmovlpd                (%rdx,%r10),    %xmm3,           %xmm3
        vmovhpd                (%rdx,%r11),    %xmm3,           %xmm3

        vmulpd                  %xmm7,         %xmm0,           %xmm0
        vmulpd                  %xmm7,         %xmm1,           %xmm1
        vmulpd                  %xmm7,         %xmm2,           %xmm2
        vmulpd                  %xmm7,         %xmm3,           %xmm3

        vextractf128            $1,            %ymm14,          %xmm4
        vextractf128            $1,            %ymm15,          %xmm5

        vaddpd                  %xmm0,         %xmm14,          %xmm0
        vaddpd                  %xmm1,         %xmm4,           %xmm1
        vaddpd                  %xmm2,         %xmm15,          %xmm2
        vaddpd                  %xmm3,         %xmm5,           %xmm3

        vmovlpd                 %xmm0,        (%rcx)
        vmovhpd                 %xmm0,        (%rcx,%r9)
        vmovlpd                 %xmm1,        (%rcx,%r10)
        vmovhpd                 %xmm1,        (%rcx,%r11)
        vmovlpd                 %xmm2,        (%rdx)
        vmovhpd                 %xmm2,        (%rdx,%r9)
        vmovlpd                 %xmm3,        (%rdx,%r10)
        vmovhpd                 %xmm3,        (%rdx,%r11)

        jmp     return

beta_zero:
        # case: beta == 0

        # update C(0,:)
        vextractf128            $1,            %ymm8,           %xmm4
        vextractf128            $1,            %ymm9,           %xmm5

        vmovlpd                 %xmm8,        (%rcx)
        vmovhpd                 %xmm8,        (%rcx,%r9)
        vmovlpd                 %xmm4,        (%rcx,%r10)
        vmovhpd                 %xmm4,        (%rcx,%r11)
        vmovlpd                 %xmm9,        (%rdx)
        vmovhpd                 %xmm9,        (%rdx,%r9)
        vmovlpd                 %xmm5,        (%rdx,%r10)
        vmovhpd                 %xmm5,        (%rdx,%r11)

        # update pointers rcx, rdx to the next row
        addq                    %r8,           %rcx
        addq                    %r8,           %rdx

        # update C(1,:)
        vextractf128            $1,            %ymm10,          %xmm4
        vextractf128            $1,            %ymm11,          %xmm5

        vmovlpd                 %xmm10,       (%rcx)
        vmovhpd                 %xmm10,       (%rcx,%r9)
        vmovlpd                 %xmm4,        (%rcx,%r10)
        vmovhpd                 %xmm4,        (%rcx,%r11)
        vmovlpd                 %xmm11,       (%rdx)
        vmovhpd                 %xmm11,       (%rdx,%r9)
        vmovlpd                 %xmm5,        (%rdx,%r10)
        vmovhpd                 %xmm5,        (%rdx,%r11)

        # update pointers rcx, rdx to the next row
        addq                    %r8,           %rcx
        addq                    %r8,           %rdx

        # update C(2,:)
        vextractf128            $1,            %ymm12,          %xmm4
        vextractf128            $1,            %ymm13,          %xmm5

        vmovlpd                 %xmm12,       (%rcx)
        vmovhpd                 %xmm12,       (%rcx,%r9)
        vmovlpd                 %xmm4,        (%rcx,%r10)
        vmovhpd                 %xmm4,        (%rcx,%r11)
        vmovlpd                 %xmm13,       (%rdx)
        vmovhpd                 %xmm13,       (%rdx,%r9)
        vmovlpd                 %xmm5,        (%rdx,%r10)
        vmovhpd                 %xmm5,        (%rdx,%r11)

        # update pointers rcx, rdx to the next row
        addq                    %r8,           %rcx
        addq                    %r8,           %rdx

        # update C(3,:)
        vextractf128            $1,            %ymm14,          %xmm4
        vextractf128            $1,            %ymm15,          %xmm5

        vmovlpd                 %xmm14,       (%rcx)
        vmovhpd                 %xmm14,       (%rcx,%r9)
        vmovlpd                 %xmm4,        (%rcx,%r10)
        vmovhpd                 %xmm4,        (%rcx,%r11)
        vmovlpd                 %xmm15,       (%rdx)
        vmovhpd                 %xmm15,       (%rdx,%r9)
        vmovlpd                 %xmm5,        (%rdx,%r10)
        vmovhpd                 %xmm5,        (%rdx,%r11)


return:
        movq                -24(%rsp),         %rax
        movq                -32(%rsp),         %rbx

        retq