Go 1.27 amplia archsimd experimental com NEON no arm64 e SIMD no WebAssembly

O Go 1.27 amplia a API SIMD experimental específica por arquitetura para três alvos: amd64, arm64 e WebAssembly. O amd64, disponível desde o Go 1.26, agora é acompanhado pelo NEON no arm64 e pela abstração SIMD de 128 bits do wasm.
O acesso depende de GOEXPERIMENT=simd, e as APIs ficam no pacote simd/archsimd. Segundo o anúncio no Go Blog, a proposta é reduzir a necessidade de escrever assembly para usar instruções SIMD sem esconder diferenças relevantes entre as arquiteturas.
O que é o archsimd
SIMD significa Single Instruction, Multiple Data. As instruções operam sobre registradores largos, de 128, 256 bits ou mais, divididos em elementos de 8 a 64 bits. Uma única operação pode, assim, processar vários elementos em paralelo.
O archsimd é a camada de baixo nível sobre a qual o pacote portátil simd é construído. Seu papel é semelhante ao de intrinsics em outras linguagens: oferecer acesso a operações próximas do hardware, inclusive recursos que existem apenas em determinada arquitetura.
A cobertura não é igual entre os alvos. O amd64 tem a maior superfície de API, com AVX, AVX2 e diversas extensões AVX-512. O arm64 cobre NEON, enquanto SVE e partes de SVE2 ainda estão em desenvolvimento. No wasm, o suporte é descrito como quase completo devido à abstração SIMD bem definida de 128 bits.
Tipos indicam formato e largura
A API usa structs distintas para representar o tipo dos elementos e o formato do vetor, como Float32x4, Int32x8 e Uint8x16. Máscaras seguem a mesma lógica, com tipos como Mask32x4.
Operações semanticamente equivalentes mantêm o mesmo nome entre larguras e arquiteturas. Uma soma elemento a elemento é expressa como x.Add(y), e o tipo de x determina qual instrução deve ser emitida. Isso evita uma função diferente para cada combinação de largura e arquitetura.
Diferenças de comportamento, porém, permanecem explícitas. A permutação de 16 bytes no amd64, baseada em VPSHUFB, zera índices negativos e aplica módulo 16 aos demais; por isso, recebe o nome PermuteOrZero. No NEON e no wasm, índices fora do intervalo são zerados, comportamento exposto como LookupOrZero.
No amd64, métodos que trabalham separadamente em lanes de 128 bits recebem o sufixo Grouped, como InterleaveLoGrouped. A nomenclatura impede que a fronteira interna do registrador fique implícita.
Carga, conversão e máscaras
O Go 1.27 simplifica cargas e armazenamentos em slices. LoadFloat32x4 carrega um vetor, enquanto Store grava seu conteúdo. Para caudas menores que um vetor completo, LoadFloat32x4Part preenche as lanes restantes com zero e informa quantos elementos foram lidos; StorePart faz a operação correspondente na escrita.
Conversões também mudaram desde o experimento do Go 1.26. Os métodos As<Type>, que geravam uma quantidade quadrática de pares de tipos, foram substituídos por operações combináveis e sem custo em tempo de execução. ToBits reinterpreta inteiros com sinal ou floats como inteiros sem sinal, e métodos como BitsToFloat32 fazem o caminho inverso.
As máscaras abstraem representações diferentes de hardware: registradores k no AVX-512, vetores de bits no AVX, AVX2, NEON e wasm, além de registradores de predicado no SVE. Comparações produzem uma máscara; Masked zera elementos falsos e IfElse seleciona valores conforme a máscara.
O compilador combina essas operações com instruções adjacentes. Conforme detalhado na publicação técnica do projeto, x.Add(y).Masked(m) pode virar uma única instrução VPADD com máscara no AVX-512. Em AVX2, NEON ou wasm, a expressão é reduzida às operações apropriadas de AND, blend ou bitselect.
Limitações e decisão de uso
A API permanece experimental e exige a ativação explícita do experimento. O archsimd suporta atualmente apenas vetores de largura fixa. Extensões escaláveis, como SVE e RVV, precisarão de outros tipos de struct para representar os vetores.
Extensões de matriz, incluindo AMX e SME, também não são suportadas. A equipe ainda não definiu como representar matrizes de forma adequada em Go. Além disso, não foram apresentados benchmarks no material; o ganho efetivo depende de o algoritmo conseguir explorar processamento paralelo em vetores.
O archsimd faz sentido quando uma rotina precisa de uma operação específica de amd64, arm64 ou wasm e o custo de manter assembly seria alto. Para algoritmos que precisam permanecer portáveis entre arquiteturas, a camada simd de nível superior é a opção indicada. Para sistemas que não podem depender de uma API experimental ou de comportamento específico do hardware, a adoção ainda exige cautela.
Leia também
- Desenvolvimento
Go 1.27 lança API SIMD portátil experimental para amd64, arm64 e wasm
7 min de leitura - Desenvolvimento
Rust 1.99 estabiliza funções variádicas C e APIs de layout para ponteiros brutos
3 min de leitura - Desenvolvimento
Cloudflare lança Workers KV Instant com p99 abaixo de 2 ms e replicação em 250 ms
3 min de leitura
Fontes

Fundador da DEVDINIZ
Software em produção
51 ferramentas gratuitas, direto no navegador
Utilitários para CPF, CNPJ, JWT, JSON, regex, cores e mais. Processamento local, sem cadastro e sem conta — a mesma engenharia que sustenta o que escrevemos aqui.