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!