Byte Swap com SSSE3
Lembrei-me há pouco, durante as minhas insónias, que podemos aproveitar uma nova instrução introduzida nos Core 2 para acelerar consideravelmente esta operação: PSHUFB.
Essencialmente, o PSHUFB permite-nos criar uma permutação à escolha dentro de um registo XMM. É fácil ver como isto se aplica no nosso caso a inversão de bytes.
Para aumentar o débito, nas escritas utilizo a instrução MOVNTDQ, que dá a dica ao processador que a memória em causa já não vai ser acedida em breve. SFENCE serve para serializar todos estes armazenamentos. Mais uma vez leio/escrevo uma cache line por iteração (podia abusar e fazer isto para uma página inteira -- valerá a pena?).
Código:
BITS 32
%define UNROLL_COUNT (4)
section .data
shuffle: dd 0x04050607, 0x00010203, 0x0c0d0e0f, 0x08090a0b
section .text
global _ssse3_bswap64
_ssse3_bswap64:
push ebp
mov edx, [esp+8] ; buffer -- assumed aligned 16
mov ecx, [esp+12] ; length in #words
test ecx, ecx
jz _end
and ecx, -(UNROLL_COUNT*2) ; make ecx even
jz _finalize
movdqa xmm7, [shuffle]
align 16
_loop:
sub ecx, UNROLL_COUNT*2
; use movntdqa with sse 4.1
movdqa xmm0, [edx + 00]
movdqa xmm1, [edx + 16]
movdqa xmm2, [edx + 32]
movdqa xmm3, [edx + 48]
pshufb xmm0, xmm7 ; p5, 1l 1t
pshufb xmm1, xmm7 ; p5, 1l 1t
pshufb xmm2, xmm7 ; p5, 1l 1t
pshufb xmm3, xmm7 ; p5, 1l 1t
; use movntdq --- the data won't be accessed again
; until the end of the function
movntdq [edx + 00], xmm0
movntdq [edx + 16], xmm1
movntdq [edx + 32], xmm2
movntdq [edx + 48], xmm3
lea edx, [edx+ 16*UNROLL_COUNT];
jnz _loop ; no dependency, all flags were
; computed in the beginning of the loop
_finalize:
sfence ; serialize stores
mov ebp, [esp+8]
and ebp, (UNROLL_COUNT*2)-1 ; ebp = count mod UNROLL
jz _end
_endloop:
mov eax, [edx]
bswap eax ; p0+p5
mov ecx, [edx+4]
bswap ecx
mov [edx], ecx
mov [edx+4], eax
sub ebp, 1
lea edx, [edx+8]
jnz _endloop
_end:
pop ebp
ret
A performance agora é claramente superior em cerca de 10% --- 1500 MB/s neste Core 2 a 2.0 GHz.
Adeus.
Realmente a performance aumentou bastante! Obrigado mais uma vez dcoder!