TGViewer
Библиотека Go-разработчика | Golang Библиотека Go-разработчика | Golang @goproglib · 24.1K subscribers
Post #7434 3.77K
📎 В Go предложили переносимый SIMD, не привязанный к архитектуре

В трекере Go появилось предложение #78902 о переносимом SIMD API. Автор — David Chase из команды компилятора. Это второй уровень поверх той работы над SIMD, что описана в проекте #73787. Важно сразу оговорить статус. Это предложение в состоянии Active, оно ещё обсуждается и не принято.

Напомним контекст. В Go 1.26 уже появился экспериментальный пакет simd/archsimd, который включается через GOEXPERIMENT=simd. Он даёт доступ к SIMD-инструкциям конкретной архитектуры, то есть вы работаете напрямую с типами вроде Float32x8 и должны сами учитывать, что доступно на целевом процессоре. Новое предложение решает другую боль. Писать под каждую архитектуру и под каждую ширину вектора отдельно неудобно, а код получается непереносимым.

Идея в том, чтобы дать абстрактный интерфейс к SIMD-векторам, не завязанный ни на архитектуру, ни на длину вектора. Там, где инструкции есть, API работает быстро. Там, где их нет, он сохраняет переносимость за счёт эмуляции. При запуске на разных вариантах одной архитектуры библиотека сама выбирает лучший доступный набор, например переключается между AVX, AVX2 и AVX512.

В первой версии список операций небольшой. Это пересечение SIMD API для wasm и текущего amd64. Набор скромный, зато его проще эмулировать на платформах без SIMD и проще поддержать при добавлении новых архитектур. Типы названы по образцу заглавной буквы и множественного числа, например Int8s или Float64s.

Внутри одного запуска программы все векторы имеют одинаковую длину в битах, поэтому их можно переинтерпретировать методами вида x.AsFloat64s(). Маски вынесены в отдельную абстракцию, потому что архитектуры реализуют их по-разному. У типов есть методы .Masked(mask) и .Merged(valueIfFalse, mask), а сами маски комбинируются через And и Or.

Предусмотрен и спуск на уровень конкретной архитектуры через ToArch() и обратно через ToSimd(), хотя в прототипе этого пока нет. По задумке это выглядит так:
//go:build amd64

import (
"simd"
"simd/archsimd"
)

func sum(x simd.Float32s) float32 {
switch a := x.ToArch().(type) {
case archsimd.Float32x8:
a = a.AddPairsGrouped(a)
a = a.AddPairsGrouped(a)
return a.GetLo().GetElem(0) + a.GetHi().GetElem(0)
case archsimd.Float32x16:
// ...
case archsimd.Float32x4:
// ...
}
}


Под капотом код, зависящий от пакета simd, компилятор размножает на несколько вариантов под разные наборы инструкций, а функции со скрытой зависимостью превращает в диспетчеры.

Переписывание идёт рано, чтобы сохранить шанс на инлайнинг. Есть нюанс для инструментов. Сгенерированные имена содержат символ @ и недоступны из исходного кода, что может влиять на отладчики и утилиты, читающие символы объектных файлов.

Есть черновой CL 763100, где сам API лежит в simd/mocks.go и генерируется автоматически. Пробовать в проде рано, но за направлением стоит следить, если вам важна производительность на горячих циклах.

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoLive
  • 🔥 13
  • ❤ 3
  • ⚡ 1
  • 👏 1
  • 💯 1
More from @goproglib
  1. Sep 23, 2026💥 TCP/IP: что происходит с данными в сети Когда Go-приложение отправляет данные по сети,…
  2. Sep 22, 2026🔴 Встроенные функции len, make, panic — встроенные функции Go, которые можно использовать…
  3. Sep 21, 2026🤩 Go с нуля: серия базовых шпаргалок Собрали путь от Hello, World! до goroutines, channel…
  4. Sep 20, 2026🤔 Вопрос с собеседования по Go Что выведет программа? ❤️ — [1 2 3 4 5] / [1 2 10] 🔥 — [1…
  5. Sep 19, 2026🛠 Rune — open-source IDE и terminal multiplexer на Go Rune объединяет IDE, терминал и AI-…
  6. Sep 18, 2026🤩 SQLite вместо отдельного брокера в Go Watermill поддерживает SQLite Pub/Sub — сообщения…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →