Quebrando a cara, de um jeito bom…

Além de mostrar alguns recursos dos processadores da família Intel que suportam o modo x86-64, estou também tentando demonstrar, no meu livro, que o compilador C faz um excelente trabalho de otimização e que assembly não é algo que o programador tenha que usar, necessariamente, para atingir um bom patamar de performance. Usei como exemplo a rotina de calculo de check sum, estabelecida pela RFC 1701, que era usada no projeto T50 (que tá meio abandonado, mas sou eu que o mantenho). A rotina original é essa:

unsigned short cksum(void *addr, size_t count)
{
  register unsigned short sum = 0;
  register unsigned short tmp;

  while (count > 1)
  {
    sum += *(unsigned short *)addr++;
    count -= sizeof(unsigned short);
  }

  if (count)
    sum += *(unsigned char *)addr;

  /* Lida com o carry bit. */
  while (tmp = sum >> 16)
    sum = (sum & 0xffff) + tmp;
  return ~sum;
}

A rotina mais otimizada, que está no código do T50, ainda em C, acumula um “unsigned long” (64 bits, no Linux) por vez, dentro do loop e depois vai acumulando tamanhos menores até o buffer acabar. Essa nova rotina, que chamarei de chksum2 é cerca de 50% mais rápida que a original. Daí, resolvi escrevê-la usando assembly.

Tomei algumas precauções: Tentei evitar, tanto quanto possível, a contenção de unidades de execução por conta de sequências de escrita-leitura de registradores; tentei usar do algorítmo de branch prediction estático, disponível na CPU e tentei não usar regisrtadores que tivessem de ser preservados entre chamadas. Além disso, uso o par de funções ADD/ADC para levar em conta o carry bit, ao invés de usar o artifício medonho mostrado acima.

Eu esperava que minha rotina em assembly fosse, pelo menos, semelhante – em termos de performance – da chksum2.

Obtive uma melhoria de performance de 132%!

Quebrei a cara quando tentei contradizer ao ditado “não há melhor otimizador do que aquele que está entre suas orelhas”! Bem feito pra mim…

OBS: Ambas rotinas do T50 e a mostrada acima têm um bug sutil. Já corrigi o problema no T50…

Anúncios

Deixe um comentário

Faça o login usando um destes métodos para comentar:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s