Go 1.27 : le paquet simd apporte un SIMD portable et émulé
Le paquet expérimental simd de Go 1.27 exécute un seul chemin de code vectoriel sur AVX-512, NEON, wasm et RISC-V, et l'émule là où le SIMD matériel manque.
4 min de lecture

L'équipe Go a expliqué le fonctionnement de son nouveau paquet SIMD portable, dans un billet publié sur le blog de Go et daté du 24 septembre 2026. Go 1.27 livre un paquet expérimental simd qui permet à un même morceau de code Go d'utiliser les instructions vectorielles de nombreux processeurs différents. C'est important, car jusqu'à Go 1.26, le seul moyen d'atteindre ces instructions depuis Go était d'écrire de l'assembleur à la main.
SIMD signifie single instruction, multiple data. C'est une fonction du processeur qui applique une opération à tout un lot de valeurs à la fois, par exemple additionner huit paires de nombres en une seule étape. Elle accélère des tâches comme la compression, la cryptographie, le traitement d'images et l'apprentissage automatique.
De l'assembleur à deux paquets expérimentaux
Go compte désormais deux paquets SIMD, et tous deux restent des expériences. Le premier, archsimd, est arrivé avec Go 1.26. Il dépend de l'architecture : il expose les instructions propres à chaque famille de processeurs, si bien que du code écrit pour des puces Intel ne tourne pas sur Arm.
Le second est le nouveau paquet portable simd de Go 1.27. Les auteurs du billet, David Chase et Junyang Shao, le décrivent comme « an experimental platform-agnostic SIMD API ». Phoronix note que sa conception s'inspire de Highway, la bibliothèque C++ de Google pour du code vectoriel portable.
Les deux paquets se trouvent derrière le même interrupteur. On compile avec la variable d'environnement GOEXPERIMENT=simd pour les activer.
Pourquoi le SIMD portable est difficile
Les familles de processeurs divergent sur presque tout en matière de vecteurs. Le blog de Go liste les largeurs de vecteur prises en charge par chaque plateforme.
| Plateforme | Instructions vectorielles | Largeur de vecteur |
|---|---|---|
| amd64 | AVX, AVX2, AVX-512 | 128, 256 et 512 bits |
| arm64 | NEON | 128 bits |
| arm64 (prévu pour Go 1.28) | SVE | 128 à 2 048 bits |
| wasm | WebAssembly SIMD | 128 bits |
| riscv64 | RVV | 128 à 65 536 bits |
Le billet cite aussi loong64, ppc64 et s390x parmi les plateformes prises en charge. Certaines puces ne révèlent leur largeur de vecteur qu'au démarrage d'un programme, donc le code ne peut pas supposer une taille à la compilation.
Le paquet simd résout ce problème en retirant la largeur des types. Les types vectoriels portent le nom des types primitifs, avec une majuscule et au pluriel : simd.Float32s, simd.Int8s, simd.Uint64s. Un Float32s contient autant de flottants 32 bits que le processeur courant peut en traiter à la fois. Les masques, ces valeurs vrai ou faux que produisent les comparaisons, reçoivent des types assortis comme Mask32s.
Comment aller vite sans connaître la largeur
C'est le compilateur qui spécialise. Selon le blog de Go, il réécrit les fonctions qui utilisent simd en variantes pour chaque largeur de vecteur, étiquetées par exemple @simd128. Le programme exécute ensuite la variante adaptée à la machine, sans surcoût de répartition dans la boucle critique.
Un réglage GODEBUG contrôle ce choix à l'exécution. simd=0 désactive le code vectoriel, et simd=128, simd=256 ou simd=512 plafonnent la largeur. Aucune recompilation n'est nécessaire pour tester chaque chemin.
Là où une plateforme n'a pas d'instructions adaptées, chaque opération est émulée. Les auteurs énumèrent leurs objectifs pour le paquet. Il doit être « as efficient as assembly language when the source code operations match the underlying hardware ». Sinon, il doit être « emulated as well as possible ». Et il doit être « easy to read and understand (even/especially if an LLM ends up writing the code) ».
Ce qui manque dans Go 1.27
La première version présente des lacunes nettes. Il n'y a pas de réduction horizontale, c'est-à-dire aucun moyen intégré de faire la somme de tous les éléments d'un vecteur. L'exemple du blog écrit une petite boucle scalaire pour cette étape et indique qu'une opération ReduceSum arrivera dans la prochaine version.
Les instructions SVE d'Arm sont elles aussi prévues pour Go 1.28, rapporte Phoronix, avec d'autres opérations. Certaines opérations ne sont aujourd'hui pas disponibles sur certaines architectures.
Ce que cela signifie pour les développeurs
Si votre service Go contient une boucle critique sur des slices de nombres, essayez le paquet dès maintenant sur une branche. Les bons candidats sont les sommes de contrôle, l'analyse syntaxique, les calculs de distance pour la recherche vectorielle et les filtres d'image. L'API portable vous permet d'écrire cette boucle une seule fois au lieu d'une fois par famille de processeurs.
Mesurez chaque largeur, pas seulement celle de votre portable. Lancez le même benchmark avec GODEBUG=simd=0, simd=128, simd=256 et simd=512. Le réglage zéro vous donne la référence scalaire gratuitement, et les autres montrent si des vecteurs plus larges paient vraiment sur vos données.
Tenez-le à l'écart de tout ce que vous ne pouvez pas recompiler rapidement. Les deux paquets SIMD sont verrouillés derrière GOEXPERIMENT, et les API expérimentales peuvent changer d'une version à l'autre. Prévoyez aussi l'absence de ReduceSum : tout code qui additionne un vecteur a besoin d'une boucle scalaire temporaire jusqu'à Go 1.28.
C'est le même compromis que font d'autres écosystèmes. Go a déjà remporté un succès concret : Debian Code Search a abandonné sa dernière dépendance C grâce à l'ancien paquet archsimd. Rust a choisi la voie de la bibliothèque ce mois-ci, quand Fearless SIMD 1.0 a livré une crate SIMD stable et sûre. Go intègre cette capacité à sa chaîne d'outils, et c'est le compilateur qui fait le travail propre à chaque processeur.
Sources
- Platform-independent SIMD in Go - The Go Blog
- Go's Improving SIMD Support, Platform-Independent SIMD Interface - Phoronix
Articles liés

Fearless SIMD 1.0 apporte un SIMD stable et sûr à Rust
Fearless SIMD 1.0, publié le 21 septembre, offre à Rust un SIMD sûr de SSE2 à AVX-512, NEON et WebAssembly, avec une API stable et 3 ans de correctifs de sécurité.

Mojo 1.1 accepte enfin les contributions au compilateur
Mojo 1.1 accepte les contributions externes au compilateur un mois après la publication sous Apache 2.0, et achève la suppression de fn, alias et @parameter if.

LLVM débat de compiler ClangIR par défaut
Une RFC LLVM propose de compiler ClangIR dans Clang par défaut. Personne ne l'utiliserait sans drapeau, mais des estimations doublent les temps de compilation.