stamatios
← Voltar ao feed
SIMD deve ser conhecido por todo desenvolvedor para ganhar performance
Dev & Engenharia

SIMD deve ser conhecido por todo desenvolvedor para ganhar performance

resumo de ~3 min

O que é SIMD e por que todo desenvolvedor deveria conhecer

SIMD (Single Instruction, Multiple Data) permite que a CPU processe múltiplos valores em paralelo com uma única instrução - por exemplo, comparar 4, 8 ou 16 bytes de uma vez em vez de um por um. Mitchell Hashimoto, criador do Ghostty (emulador de terminal), argumenta que a técnica tem reputação injusta de complexidade e que o caso comum segue sempre o mesmo padrão de cinco passos.

O padrão de cinco passos

  1. Broadcast de constantes: copiar valores de comparação para todas as lanes do vetor (ex.: @splat(0xF)).
  2. Loop por chunks de vetor: iterar sobre a entrada carregando um vetor completo por vez (ex.: 8 valores com AVX2).
  3. Operação SIMD: aplicar a comparação ou aritmética em todas as lanes em paralelo - um único > compara 8 valores de uma vez.
  4. Redução do resultado: transformar o vetor de booleanos em algo utilizável (ex.: bitmask + @ctz para encontrar a primeira lane que falhou).
  5. Cauda escalar: o loop original processa os elementos restantes que não preenchem um vetor completo e serve como fallback para CPUs sem suporte.

Exemplo real no Ghostty

O caso mostrado é um loop que escaneia codepoints decodificados até encontrar um caractere de controle C0 (valor ≤ 0xF). A versão escalar é uma linha. A versão SIMD adiciona 12 linhas e entrega até 4x de ganho com ARM NEON (Apple Silicon), 8x com AVX2 (x86 moderno) e 16x com AVX-512 (Intel e AMD Zen 4+). Em throughput real de ponta a ponta num desktop Intel com AVX2, o ganho foi de 5x.

Por que o compilador não faz isso sozinho?

Compiladores conseguem auto-vetorizar loops aritméticos simples, mas são limitados e frequentemente perdem oportunidades - pesquisa recente ainda documenta esse problema. Além disso, quando o loop é crítico o suficiente para justificar 5x de ganho, Hashimoto prefere que a vetorização seja explícita e previsível, sem risco de uma mudança de código ou atualização de compilador reverter silenciosamente para escalar.

Conclusão

O autor defende que todo desenvolvedor deveria ao menos reconhecer a oportunidade: ao ver um loop quente que escaneia, compara, conta ou transforma grandes volumes de dados contíguos, imagine processá-lo em chunks de vetor. Com bom suporte de linguagem (o post usa Zig, mas o conceito é geral), não é preciso conhecer assembly nem detalhes específicos de CPU para obter ganhos significativos.