Mais um blog inútil.

Abril 29, 2009

Byte Swap com SSSE3

Filed under: Assembly,Coding,Serious Business,Useless — dongs @ 5:26

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.

Um comentário a “Byte Swap com SSSE3”

  1. Armorfist diz:

    Realmente a performance aumentou bastante! Obrigado mais uma vez dcoder!

Leave a Reply for Armorfist

widgeon
widgeon
widgeon
widgeon