Aller au contenu

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.

Par Tech AI Wire Team

4 min de lecture

XLinkedIn
The inner-product example from the Go blog's SIMD post, a Go function that loads float32 slices into simd.Float32s vectors and calls MulAdd.
Photo: The Go Blog

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.

PlateformeInstructions vectoriellesLargeur de vecteur
amd64AVX, AVX2, AVX-512128, 256 et 512 bits
arm64NEON128 bits
arm64 (prévu pour Go 1.28)SVE128 à 2 048 bits
wasmWebAssembly SIMD128 bits
riscv64RVV128 à 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

  1. Platform-independent SIMD in Go - The Go Blog
  2. Go's Improving SIMD Support, Platform-Independent SIMD Interface - Phoronix

Articles liés

A terminal showing a large C++ project compiling, with the CMake percentage counter partway through and object files scrolling past.
Programmation

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.