概要
Go 1.26と1.27で SIMD操作用の実験的API が導入。 SIMDにより データベクトルへの高速な一括演算 が可能。 従来は Goアセンブリ記述 のみで利用可能だった。 新APIは アーキテクチャ依存と非依存の両方 を提供。 マルチプラットフォーム・可搬性・効率を両立する simdパッケージ の特徴。
GoのSIMDサポートの進化
- SIMD(Single Instruction Multiple Data) は、現代CPUの ネイティブ機能 であり、ベクトルデータに対し同時に演算を実行可能。
- 例:float64値のペア8組を 単一命令で加算 する処理。
- 暗号処理、データ処理、AI など計算集約タスクで大幅な高速化が可能。
- GoのGreen Teaガベージコレクタ でも、SIMDを利用しメモリスキャンを高速化。
- これまでGoからSIMDを利用するには Goアセンブリ記述 が必須で、パフォーマンスが極端に重要な場合に限られていた。
- 多くのソフトウェアで CPUリソースが未活用 のまま残る課題。
Go 1.26/1.27のSIMD API概要
- Go 1.26 で amd64向けSIMD API を導入。
- Go 1.27 で arm64(NEON) および wasm 向けAPIも追加。
- SIMD APIの設計課題は プラットフォームごとの多様性。
- ベクトルサイズや演算機能、マスク処理方式などが異なる。
- 例:ベクトルサイズが128〜512ビットで固定のものもあれば、起動時にサイズを問い合わせる必要があるものも存在。
- archsimdパッケージ としてアーキテクチャ依存APIを提供。
simdパッケージの特徴と設計
- Go 1.27 では 完全可搬・プラットフォーム非依存 のSIMDインターフェース(simdパッケージ)も実験的導入。
- C++のHighway を参考に設計。
- AVX/AVX2/AVX512(amd64)、NEON(arm64)、wasmのSIMD命令 に対応。
- サポートされていないプラットフォームでは 効率的なエミュレーション を提供。
- GOEXPERIMENT=simd をビルド時に指定して利用。
- ベクトル型は simd.Uint8sやsimd.Float32s などの大文字複数形プリミティブ型。
- ベクトルのロード/ストアはスライスを利用。
- 例:simd.LoadFloat32s(x[i:i+a.Len()])でスライスからベクトルロード。
simdパッケージの操作例
- 内積計算関数の実装例 (float32スライス同士の内積)を提供。
- sum関数 は現状simdで直接サポートされていないが、次期バージョンでReduceSumが追加予定。
- ベクトル比較演算 は各要素幅に対応したマスク型(例:Mask8s)が生成され、選択やフィルタ処理に利用可能。
simdパッケージのサポート関数一覧(Go 1.27時点)
- ベクトルロード/ブロードキャスト/ストア/文字列表現
- 算術演算:加算、減算、乗算、除算、絶対値、平方根、飽和加算/減算、平均、積和演算など
- 論理演算:AND, OR, XOR, NOT, マスク付き操作
- 比較演算:等価、不等価、大なり、小なり、以上、以下
- 型変換:Float/Int/Uint間の変換、マスク変換
- シフト・ローテート:全ビット左/右シフト・ローテート
- ゼロコストリシェイプ:ビット列や異なる幅のベクトルへの変換
SIMDアーキテクチャ間の主な差異
- ベクトルサイズの固定/可変性 (例:wasmは128ビット固定、riscv64は128〜65536ビット可変)
- マスク処理方式 (例:AVX512は要素ごとにマスクビット、NEONやwasmはビット演算で対応)
- 命令セットの違い (例:暗号系演算、要素並べ替え、整数比較などのサポート状況)
アーキテクチャ依存SIMDとの連携
- simdパッケージ型は ToArch()メソッド でアーキテクチャ固有型(any型)に変換可能。
- 逆変換は simd.FromArch 関数で実施。
- これにより 足りない機能だけをアーキテクチャ固有実装 で補うことが可能。
- 完全な例: Int8s.OnesCount() (ビットカウント)のアーキテクチャ依存実装。
まとめ
- GoのSIMDサポートは大きく進化 し、より多くのアプリケーションで CPUリソースを効率活用 可能に。
- simdパッケージは可搬性とパフォーマンスを両立 しつつ、アーキテクチャ固有拡張も許容。
- 今後も APIの拡充とエミュレーション性能向上 が期待される。
この機能は、すでにマルチコアで動いているGoプロジェクトの低レベルパフォーマンスを最適化するための多くの扉を開いてくれるね。確か、SIMDやそのバリエーションをサポートしている標準ライブラリを持っている言語はあまり多くないはず。最近のGoの新しい試みが大好きだよ。