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