⏱️ Lectura: 12 min

Hasta ahora, la única forma de usar instrucciones SIMD en Go era escribir ensamblador a mano, algo que solo valía la pena en los núcleos de cómputo más críticos. Go 1.27 cambia eso: el 24 de septiembre de 2026, David Chase y Junyang Shao presentaron en el blog oficial de Go un paquete experimental llamado simd, la primera implementación de SIMD portátil en Go que corre igual en amd64, arm64 y wasm.

📑 En este artículo
  1. TL;DR
  2. Qué pasó
  3. Contexto e historia
  4. Detalles técnicos del SIMD portátil en Go
  5. Cómo empezar a probar el SIMD portátil en Go
  6. Impacto y análisis
  7. Qué sigue
  8. Preguntas frecuentes
    1. ¿Qué es el paquete simd de Go?
    2. ¿En qué se diferencia de archsimd?
    3. ¿Qué arquitecturas soporta hoy el SIMD portátil en Go?
    4. ¿Cómo activo el paquete simd en mi proyecto?
    5. ¿Es seguro usar simd en producción ya mismo?
    6. ¿simd reemplaza para siempre escribir ensamblador en Go?
  9. Referencias
    1. 📚 Artículos relacionados

El paquete no obliga a mantener una versión de código distinta por arquitectura de CPU. La idea no es nueva para el proyecto: el recolector de basura Green Tea de Go ya usa instrucciones SIMD para acelerar el escaneo de memoria en busca de objetos vivos, así que el equipo sabe de primera mano cuánto rendimiento queda sobre la mesa cuando el resto del código no las aprovecha.

TL;DR

  • Simd, el paquete presentado el 24 de septiembre de 2026, corre en amd64, arm64 y wasm sin recompilar código distinto por arquitectura.
  • Go 1.26 introdujo SIMD solo para amd64 con el paquete archsimd; Go 1.27 sumó arm64 (NEON) y wasm.
  • David Chase y Junyang Shao diseñaron simd inspirándose en la librería Highway de C++, de Google.
  • La nueva API soporta AVX, AVX2 y AVX512 en amd64, NEON en arm64 y las instrucciones SIMD de wasm.
  • Para activarla hay que compilar con la variable de entorno GOEXPERIMENT=simd.
  • El recolector de basura Green Tea de Go ya usa instrucciones SIMD para escanear memoria en busca de objetos vivos.
  • Los tipos de vector se llaman simd.Uint8s, simd.Float32s y similares: primitivos capitalizados y en plural cargados desde slices.
  • Riscv64 admite vectores de tamaño variable entre 128 y 65.536 bits, siempre potencias de dos, un caso que la nueva API abstrae.

Qué pasó

El 24 de septiembre de 2026, el blog oficial de Go confirmó que Go 1.27 suma un paquete simd completamente portátil, además de extender el paquete archsimd (dependiente de arquitectura) a arm64 y wasm. Go 1.26, publicado antes en el mismo año, ya había introducido SIMD para amd64 a través de archsimd.

El paquete simd portátil en Go persigue cuatro objetivos de diseño, según sus autores.

  • Cubrir los algoritmos de procesamiento de datos que se benefician de una implementación vectorizada, sin atarlos a un tamaño de vector fijo.
  • Rendir igual que ensamblador cuando el código fuente coincide con lo que soporta el hardware.
  • Emularse lo mejor posible cuando el hardware no tiene esa instrucción o esa arquitectura no tiene soporte en archsimd.
  • Ser fácil de leer y entender, incluso si termina siendo un modelo de lenguaje quien lo escribe.

Contexto e historia

Antes de estas APIs, la única puerta de entrada a SIMD en Go era escribir ensamblador de Go a mano. Eso solo se justificaba en los núcleos de cómputo verdaderamente críticos, así que buena parte del software que podría beneficiarse de la vectorización simplemente dejaba sin usar buena parte de la CPU.

Go 1.26 abrió la puerta con archsimd para amd64. Go 1.27 extendió esa misma API dependiente de arquitectura a arm64 (específicamente NEON) y a wasm. Pero archsimd, aunque diseñado para ser lo más uniforme posible entre arquitecturas, sigue obligando a escribir una rama de código distinta por cada una. El paquete simd nuevo va un paso más allá: saca los vectores de tamaño fijo del sistema de tipos y solo expone las operaciones que están en la intersección de todas las plataformas soportadas, rellenando los huecos con emulación eficiente en términos de otras instrucciones SIMD.

Go 1.26 sumó SIMD solo para amd64 con archsimd; Go 1.27 lo extendió a arm64 (NEON) y wasm. Foto de ThisisEngineering en Unsplash

Detalles técnicos del SIMD portátil en Go

La variación entre arquitecturas SIMD es enorme, y no solo en qué operaciones soportan sino en cómo representan los vectores. Algunas plataformas usan vectores de tamaño fijo, entre 128 y 512 bits; en otras, el tamaño del vector ni siquiera se conoce en tiempo de compilación y hay que consultarlo cuando arranca el programa.

Arquitectura Tamaños de vector Modelo de máscara Soportada en simd (2026)
amd64 (AVX/AVX2/AVX512) 128, 256 y 512 bits Bitmask vectorial (AVX/AVX2) o registros de máscara dedicados (AVX512) Sí
arm64 NEON 128 bits fijos Bitmask vectorial Sí
arm64 SVE/SVE2 Variable, 128-2048 bits (potencias de 2) Un bit por byte; manda el bit menos significativo de cada elemento No todavía
wasm 128 bits fijos Bitmask vectorial (sin comparaciones de enteros de 64 bits) Sí
riscv64 (RVV) Variable, 128-65536 bits (potencias de 2) Registros de máscara dedicados, como AVX512 No todavía
loong64 128 y 256 bits No documentado en el anuncio No todavía

El enmascarado (decidir qué elementos de un vector participan de una operación) también varía muchísimo. wasm, AVX, AVX2 y NEON no tienen registros de máscara dedicados: la selección se hace con operaciones booleanas sobre vectores normales. AVX512 y RVV sí tienen registros de máscara, con un bit por elemento. SVE reserva un bit por cada byte del vector, pero solo cuenta el bit menos significativo de cada elemento. Incluso las operaciones básicas difieren: wasm, por ejemplo, no tiene comparaciones nativas para vectores de enteros de 64 bits. El paquete simd portátil en Go esconde toda esa variación y solo expone operaciones presentes en la intersección de plataformas, emulando el resto.

Así se resume el flujo cuando el compilador procesa código que usa el paquete simd.

flowchart TD
A["Código Go con el paquete simd"] --> B{"Arquitectura de destino"}
B -->|"amd64"| C["Backend AVX / AVX2 / AVX512"]
B -->|"arm64"| D["Backend NEON"]
B -->|"wasm"| E["Instrucciones SIMD de wasm"]
B -->|"otra arquitectura"| F["Emulación con instrucciones equivalentes"]

El mismo código fuente compila a rutas distintas según el backend disponible, y si ninguno aplica, cae en la ruta de emulación en lugar de fallar.

Cómo empezar a probar el SIMD portátil en Go

El paquete vive detrás de una bandera experimental, así que hace falta un toolchain de Go 1.27 (o posterior) y activar GOEXPERIMENT al compilar.

# Linux y macOS (bash/zsh)
GOEXPERIMENT=simd go build ./...

# Windows (PowerShell)
$env:GOEXPERIMENT = "simd"
go build ./...

# Windows (cmd.exe)
set GOEXPERIMENT=simd
go build ./...

Con esa variable activa, el compilador habilita el import path simd además de los paquetes archsimd por arquitectura. Un ejemplo mínimo, adaptando el patrón de producto interno que muestra el blog oficial, se vería así.

package vectormath

import "simd"

// innerProduct calcula el producto punto de x e y usando el paquete
// experimental simd (requiere compilar con GOEXPERIMENT=simd).
func innerProduct(x, y []float32) float32 {
	var acc simd.Float32s
	n := len(x)
	width := acc.Len() // ancho de vector real de esta CPU, no fijo en el codigo

	i := 0
	for ; i+width <= n; i += width {
		vx := simd.LoadFloat32sSlice(x[i:])
		vy := simd.LoadFloat32sSlice(y[i:])
		acc = acc.Add(vx.Mul(vy))
	}

	sum := acc.Sum() // reduce el vector acumulado a un solo float32
	for ; i < n; i++ {
		sum += x[i] * y[i]
	}
	return sum
}

Esta función recorre x e y de a width elementos por vez (el ancho real de vector que exponga la CPU en tiempo de ejecución, no un número fijo en el código) y acumula productos con instrucciones vectoriales; el resto, si n no es múltiplo de width, se suma elemento por elemento al final. En una CPU amd64 con AVX2, width valdría 8 float32 por vector; en un arm64 con NEON, 4.

⚠️ Ojo: El paquete simd es experimental y vive detrás de la bandera GOEXPERIMENT. Su API todavía puede cambiar entre versiones de Go, así que conviene evitar apostar código de producción crítico a la forma exacta de sus funciones por ahora.

Para confirmar que el compilador realmente emitió instrucciones vectoriales, conviene mirar el ensamblador generado y buscar mnemónicos SIMD, y revisar si el binario quedó marcado con la bandera experimental.

go build -gcflags="-S" ./vectormath 2>&1 | grep -iE "vpaddps|vfmadd|vmovups"

go version -m ./mibinario | grep GOEXPERIMENT

Si el segundo comando muestra GOEXPERIMENT=simd en los metadatos del build, el binario se compiló con el paquete habilitado.

simd se activa compilando con GOEXPERIMENT=simd, igual que otras funciones experimentales de Go. Foto de CDC en Unsplash

Impacto y análisis

La llegada del SIMD portátil en Go baja la barrera de entrada para acelerar tareas intensivas en cómputo, como criptografía, procesamiento de datos e inferencia de IA, sin condenar al proyecto a mantener ensamblador por arquitectura. Antes, escribir SIMD a mano en Go implicaba multiplicar el trabajo de mantenimiento por cada arquitectura soportada; ahora ese costo lo absorbe el compilador y la capa de emulación del paquete simd.

💭 Clave: El recolector de basura Green Tea de Go ya usa instrucciones SIMD para acelerar el escaneo de memoria en busca de objetos vivos. La mejora no es solo para el código de aplicación. También beneficia al runtime.

El diseño tiene un costo explícito. Al exponer solo la intersección de operaciones entre plataformas, el paquete simd no permite exprimir instrucciones exóticas de una arquitectura puntual, algo que sí logra escribir ensamblador a mano o usar archsimd directamente. Para un núcleo de cómputo hiperespecífico, donde cada ciclo cuenta y el binario solo corre en un tipo de CPU, archsimd (o el ensamblador puro) sigue siendo la opción más rápida; simd portátil en Go conviene cuando el mismo binario tiene que rendir bien en varias arquitecturas sin triplicar el código fuente.

Qué sigue

El paquete simd sigue gateado por GOEXPERIMENT, lo que en la práctica de Go significa que su API todavía puede cambiar, fusionarse o incluso descartarse antes de convertirse en estable, como pasó con otras funciones experimentales del lenguaje. Hoy cubre amd64, arm64 y wasm; arquitecturas con vectores de tamaño variable como riscv64 (RVV) y arm64 con SVE, o con soporte fijo más chico como loong64, PowerPC y s390x, quedan fuera del alcance inicial.

El equipo de Go no publicó una fecha de graduación a estable para simd, pero el patrón habitual del proyecto es dejar una función detrás de GOEXPERIMENT varias versiones mientras recibe feedback de producción antes de habilitarla por defecto.

📖 Resumen en Telegram: Ver resumen

Probá vos: compilá cualquier función numérica propia con GOEXPERIMENT=simd go build ./… sobre un toolchain de Go 1.27 y compará el ensamblador resultante contra la versión sin la bandera.

Preguntas frecuentes

¿Qué es el paquete simd de Go?

Es una API experimental, introducida en Go 1.27, que expone operaciones vectoriales sin atarlas a una arquitectura ni a un tamaño de vector fijo. El compilador elige el backend adecuado (AVX/AVX2/AVX512 en amd64, NEON en arm64, SIMD de wasm) o emula la operación si hace falta.

¿En qué se diferencia de archsimd?

archsimd, agregado en Go 1.26 para amd64 y extendido en 1.27 a arm64 y wasm, expone el hardware casi sin filtrar: hay que escribir una rama de código por arquitectura. simd, en cambio, es agnóstico de plataforma y de tamaño de vector, y el mismo código fuente corre en todas las arquitecturas soportadas.

¿Qué arquitecturas soporta hoy el SIMD portátil en Go?

Según el anuncio del 24 de septiembre de 2026, simd cubre AVX, AVX2 y AVX512 en amd64, NEON en arm64 y las instrucciones SIMD de wasm. Arquitecturas como riscv64, loong64, PowerPC o s390x todavía no están cubiertas por el paquete portátil.

¿Cómo activo el paquete simd en mi proyecto?

Hace falta compilar con la variable de entorno GOEXPERIMENT=simd, por ejemplo con GOEXPERIMENT=simd go build ./…, usando un toolchain de Go 1.27 o posterior.

¿Es seguro usar simd en producción ya mismo?

Es experimental: vive detrás de GOEXPERIMENT precisamente porque su API todavía puede cambiar. Conviene probarlo en benchmarks propios antes de apostar código crítico a su forma actual.

¿simd reemplaza para siempre escribir ensamblador en Go?

No en todos los casos. Para núcleos hiperespecíficos que solo corren en una arquitectura y necesitan exprimir cada instrucción, archsimd o el ensamblador de Go directo siguen rindiendo más que la capa portátil, que sacrifica algo de especificidad a cambio de portabilidad.

Referencias

  • Go Blog: Platform-independent SIMD in Go: el anuncio original de David Chase y Junyang Shao, publicado el 24 de septiembre de 2026.
  • go.dev: sitio oficial del lenguaje Go, con documentación y notas de cada versión.
  • github.com/golang/go: repositorio del código fuente del compilador y la biblioteca estándar de Go.
  • github.com/google/highway: la librería SIMD portátil de C++ de Google en la que se inspiró el diseño del paquete simd.
  • Wikipedia: SIMD: contexto general sobre el modelo de ejecución Single Instruction, Multiple Data.

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.

Imagen destacada: Foto de Mathew Schwartz en Unsplash


Andrés Morales

Desarrollador e investigador en inteligencia artificial. Escribe sobre modelos de lenguaje, frameworks, herramientas para devs y lanzamientos open source. Cubre papers de ML, ecosistema de startups tech y tendencias de programación.

0 Comentarios

Deja un comentario

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.