Content

AVX-Kernel mit Loop-Unrolling

Durch Loop-Unrolling kann die Effizienz nochmal etwas gesteigert werden. Der Assembler-Code folgt weiter unten.

ulmBLAS muss neu erzeugt werden:

$shell> pwd
/home/numerik/hpc/ss16/session08/example03/hpc_project/ulmblas
$shell> make
gcc -Wall -mavx -Ofast -I ..   -c -o lu.o lu.c
gcc -Wall -mavx -Ofast -I ..   -c -o level3.o level3.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_unrolled.o ugemm_4_8_unrolled.s
ar cru ../ulmblas.a lu.o level3.o level1.o level2.o  ugemm_4_8_unrolled.o
ranlib ../ulmblas.a
$shell> 

Und danach der Benchmark neu übersetzt werden:

$shell> pwd
/home/numerik/hpc/ss16/session08/example03/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> ./bench_dgemm_4_8 > report.gemm_avx_unrolled
$shell> gnuplot plot.gemm
$shell> 

Assembler-Code

Wir ersetzen ulmblas/ugemm_4_8.s mit ulmblas/ugemm_4_8_unrolled.s:

#  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)
        vmovlpd                 %xmm1,      -16(%rsp)
        movq                    %rax,       -24(%rsp)
        movq                    %rbx,       -32(%rsp)

        vmovapd           0 * 32(%rdx),         %ymm4
        vmovapd           1 * 32(%rdx),         %ymm5

        vbroadcastsd       0 * 8(%rsi),         %ymm0
        vbroadcastsd       1 * 8(%rsi),         %ymm1
        vbroadcastsd       2 * 8(%rsi),         %ymm2
        vbroadcastsd       3 * 8(%rsi),         %ymm3

        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

        movq                    $4*32,          %rax
        movq                    $8*32,          %rbx

        subq                    $4,             %rdi
        jmp                     check_unrolled

loop_unrolled:
#l=0
        vmulpd                  %ymm0,          %ymm4,          %ymm6
        vaddpd                  %ymm6,          %ymm8,          %ymm8
        vmulpd                  %ymm0,          %ymm5,          %ymm6
        vaddpd                  %ymm6,          %ymm12,         %ymm12
        vbroadcastsd       4 * 8(%rsi),         %ymm0

        vmulpd                  %ymm1,          %ymm4,          %ymm7
        vaddpd                  %ymm7,          %ymm9,          %ymm9
        vmulpd                  %ymm1,          %ymm5,          %ymm7
        vaddpd                  %ymm7,          %ymm13,         %ymm13
        vbroadcastsd       5 * 8(%rsi),         %ymm1

        vmulpd                  %ymm2,          %ymm4,          %ymm6
        vaddpd                  %ymm6,          %ymm10,         %ymm10
        vmulpd                  %ymm2,          %ymm5,          %ymm6
        vaddpd                  %ymm6,          %ymm14,         %ymm14
        vbroadcastsd       6 * 8(%rsi),         %ymm2

        vmulpd                  %ymm3,          %ymm4,          %ymm7
        vaddpd                  %ymm7,          %ymm11,         %ymm11
        vmovapd           2 * 32(%rdx),         %ymm4
        vmulpd                  %ymm3,          %ymm5,          %ymm7
        vaddpd                  %ymm7,          %ymm15,         %ymm15
        vbroadcastsd       7 * 8(%rsi),         %ymm3
        vmovapd           3 * 32(%rdx),         %ymm5
#l=1
        vmulpd                  %ymm0,          %ymm4,          %ymm6
        vaddpd                  %ymm6,          %ymm8,          %ymm8
        vmulpd                  %ymm0,          %ymm5,          %ymm6
        vaddpd                  %ymm6,          %ymm12,         %ymm12
        vbroadcastsd       8 * 8(%rsi),         %ymm0

        vmulpd                  %ymm1,          %ymm4,          %ymm7
        vaddpd                  %ymm7,          %ymm9,          %ymm9
        vmulpd                  %ymm1,          %ymm5,          %ymm7
        vaddpd                  %ymm7,          %ymm13,         %ymm13
        vbroadcastsd       9 * 8(%rsi),         %ymm1

        vmulpd                  %ymm2,          %ymm4,          %ymm6
        vaddpd                  %ymm6,          %ymm10,         %ymm10
        vmulpd                  %ymm2,          %ymm5,          %ymm6
        vaddpd                  %ymm6,          %ymm14,         %ymm14
        vbroadcastsd       10* 8(%rsi),         %ymm2

        vmulpd                  %ymm3,          %ymm4,          %ymm7
        vaddpd                  %ymm7,          %ymm11,         %ymm11
        vmovapd           4 * 32(%rdx),         %ymm4
        vmulpd                  %ymm3,          %ymm5,          %ymm7
        vaddpd                  %ymm7,          %ymm15,         %ymm15
        vbroadcastsd       11* 8(%rsi),         %ymm3
        vmovapd           5 * 32(%rdx),         %ymm5
#l=2
        vmulpd                  %ymm0,          %ymm4,          %ymm6
        vaddpd                  %ymm6,          %ymm8,          %ymm8
        vmulpd                  %ymm0,          %ymm5,          %ymm6
        vaddpd                  %ymm6,          %ymm12,         %ymm12
        vbroadcastsd       12* 8(%rsi),         %ymm0

        vmulpd                  %ymm1,          %ymm4,          %ymm7
        vaddpd                  %ymm7,          %ymm9,          %ymm9
        vmulpd                  %ymm1,          %ymm5,          %ymm7
        vaddpd                  %ymm7,          %ymm13,         %ymm13
        vbroadcastsd       13* 8(%rsi),         %ymm1

        vmulpd                  %ymm2,          %ymm4,          %ymm6
        vaddpd                  %ymm6,          %ymm10,         %ymm10
        vmulpd                  %ymm2,          %ymm5,          %ymm6
        vaddpd                  %ymm6,          %ymm14,         %ymm14
        vbroadcastsd       14* 8(%rsi),         %ymm2

        vmulpd                  %ymm3,          %ymm4,          %ymm7
        vaddpd                  %ymm7,          %ymm11,         %ymm11
        vmovapd           6 * 32(%rdx),         %ymm4
        vmulpd                  %ymm3,          %ymm5,          %ymm7
        vaddpd                  %ymm7,          %ymm15,         %ymm15
        vbroadcastsd       15* 8(%rsi),         %ymm3
        vmovapd           7 * 32(%rdx),         %ymm5
#l=3
        vmulpd                  %ymm0,          %ymm4,          %ymm6
        vaddpd                  %ymm6,          %ymm8,          %ymm8
        vmulpd                  %ymm0,          %ymm5,          %ymm6
        vaddpd                  %ymm6,          %ymm12,         %ymm12
        vbroadcastsd       16* 8(%rsi),         %ymm0

        vmulpd                  %ymm1,          %ymm4,          %ymm7
        vaddpd                  %ymm7,          %ymm9,          %ymm9
        vmulpd                  %ymm1,          %ymm5,          %ymm7
        vaddpd                  %ymm7,          %ymm13,         %ymm13
        vbroadcastsd       17* 8(%rsi),         %ymm1

        vmulpd                  %ymm2,          %ymm4,          %ymm6
        vaddpd                  %ymm6,          %ymm10,         %ymm10
        vmulpd                  %ymm2,          %ymm5,          %ymm6
        vaddpd                  %ymm6,          %ymm14,         %ymm14
        vbroadcastsd       18* 8(%rsi),         %ymm2

        vmulpd                  %ymm3,          %ymm4,          %ymm7
        vaddpd                  %ymm7,          %ymm11,         %ymm11
        vmovapd           8 * 32(%rdx),         %ymm4
        vmulpd                  %ymm3,          %ymm5,          %ymm7
        vaddpd                  %ymm7,          %ymm15,         %ymm15
        vbroadcastsd       19* 8(%rsi),         %ymm3
        vmovapd           9 * 32(%rdx),         %ymm5

        addq                    %rax,           %rsi
        addq                    %rbx,           %rdx
        subq                    $4,             %rdi

check_unrolled:
        testq                   %rdi,           %rdi
        jg                      loop_unrolled


        addq                    $4,             %rdi
        jmp                     check_left

loop_left:
        vmulpd                  %ymm0,          %ymm4,          %ymm6
        vaddpd                  %ymm6,          %ymm8,          %ymm8
        vmulpd                  %ymm0,          %ymm5,          %ymm6
        vaddpd                  %ymm6,          %ymm12,         %ymm12
        vbroadcastsd       4 * 8(%rsi),         %ymm0

        vmulpd                  %ymm1,          %ymm4,          %ymm7
        vaddpd                  %ymm7,          %ymm9,          %ymm9
        vmulpd                  %ymm1,          %ymm5,          %ymm7
        vaddpd                  %ymm7,          %ymm13,         %ymm13
        vbroadcastsd       5 * 8(%rsi),         %ymm1

        vmulpd                  %ymm2,          %ymm4,          %ymm6
        vaddpd                  %ymm6,          %ymm10,         %ymm10
        vmulpd                  %ymm2,          %ymm5,          %ymm6
        vaddpd                  %ymm6,          %ymm14,         %ymm14
        vbroadcastsd       6 * 8(%rsi),         %ymm2

        vmulpd                  %ymm3,          %ymm4,          %ymm7
        vaddpd                  %ymm7,          %ymm11,         %ymm11
        vmovapd           2 * 32(%rdx),         %ymm4
        vmulpd                  %ymm3,          %ymm5,          %ymm7
        vaddpd                  %ymm7,          %ymm15,         %ymm15
        vbroadcastsd       7 * 8(%rsi),         %ymm3
        vmovapd           3 * 32(%rdx),         %ymm5

        addq                    $32,            %rsi
        addq                    $2*32,          %rdx
        decq                    %rdi

check_left:
        testq                   %rdi,           %rdi
        jg                      loop_left

        vbroadcastsd          -8(%rsp),         %ymm6
        vbroadcastsd         -16(%rsp),         %ymm7

        vmulpd                  %ymm6,          %ymm8,          %ymm8
        vmulpd                  %ymm6,          %ymm9,          %ymm9
        vmulpd                  %ymm6,          %ymm10,         %ymm10
        vmulpd                  %ymm6,          %ymm11,         %ymm11
        vmulpd                  %ymm6,          %ymm12,         %ymm12
        vmulpd                  %ymm6,          %ymm13,         %ymm13
        vmulpd                  %ymm6,          %ymm14,         %ymm14
        vmulpd                  %ymm6,          %ymm15,         %ymm15

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

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

#
#       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,             %ymm12,         %xmm5

        vaddpd                  %xmm0,          %xmm8,          %xmm0
        vaddpd                  %xmm1,          %xmm4,          %xmm1
        vaddpd                  %xmm2,          %xmm12,         %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 C(1,:)
#
        addq                    %r8,            %rcx
        addq                    %r8,            %rdx

        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,             %ymm9,          %xmm4
        vextractf128            $1,             %ymm13,         %xmm5

        vaddpd                  %xmm0,          %xmm9,          %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 C(2,:)
#
        addq                    %r8,            %rcx
        addq                    %r8,            %rdx

        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,             %ymm14,         %xmm5

        vaddpd                  %xmm0,          %xmm10,         %xmm0
        vaddpd                  %xmm1,          %xmm4,          %xmm1
        vaddpd                  %xmm2,          %xmm14,         %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 C(3,:)
#
        addq                    %r8,            %rcx
        addq                    %r8,            %rdx

        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,             %ymm11,         %xmm4
        vextractf128            $1,             %ymm15,         %xmm5

        vaddpd                  %xmm0,          %xmm11,         %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)

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

        retq