Сейчас, если нужно использовать SIMD в Go, есть по сути один путь — писать ассемблерные вставки руками. Это медленно, легко ошибиться, а ещё такой код нельзя инлайнить и он мешает асинхронной вытесняющей многозадачности рантайма.
Для задач вроде обработки векторов, хеширования, парсинга протоколов или AI-инфраструктуры это ощутимое ограничение. Команда Go предложила решение — добавить архитектурно-специфичные SIMD-интринсики прямо в язык, без изменения синтаксиса.
Что предлагают
Идея в двухуровневом подходе. Низкий уровень — это архитектурно-специфичный пакет
simd, где операции почти один в один соответствуют машинным инструкциям. Высокий уровень — портируемый API поверх него, который появится позже. Сравнение с syscall и os тут в тему. Большинство кода будет работать с высокоуровневым API, а для редких случаев останется доступ к низкоуровневым операциям.На старте фокус на AMD64. Пробуется всё это под флагом
GOEXPERIMENT=simd, ветка называется dev.simd.Векторные типы описаны как непрозрачные структуры, компилятор распознаёт их и хранит в векторных регистрах:
type Uint32x4 struct { a0, a1, a2, a3 uint32 }
type Float64x4 struct { a0, a1, a2, a3 float64 }Операции реализованы как методы:
// Сложение элементов двух векторов.
// Соответствует инструкции VPADDD на x86.
func (Uint32x4) Add(Uint32x4) Uint32x4
Загрузка и сохранение работают через указатель на массив нужного размера:
func LoadUint32x4(*[4]uint32) Uint32x4
func (Uint32x4) Store(*[4]uint32)
Отдельно продуманы маски. На разных архитектурах маска хранится по-разному — где-то это регистр с одним битом на элемент, где-то обычный векторный регистр. Поэтому маска тоже сделана непрозрачным типом, а компилятор сам выбирает представление в зависимости от того, как маска используется дальше:
func (Uint32x4) AddMasked(Uint32x4, Mask32x4) Uint32x4 // VPADDD.Z
func (Uint32x4) Equal(Uint32x4) Mask32x4 // VCMPEQD или VPCMPD
Для проверки поддержки процессором нужных возможностей добавлены функции вроде
HasAVX512(). Компилятор считает их чистыми функциями, поскольку они не меняются после старта программы, и может использовать это для оптимизаций.Предложение сейчас в статусе active и рассматривается на еженедельных встречах по Go-предложениям. Часть операций, как Gather и Scatter, отложена на Go 1.27 из-за вопросов безопасности памяти. Портируемый высокоуровневый API и поддержка масштабируемых векторов, таких как ARM64 SVE, тоже в планах на будущее.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoLive