メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

#78979active

simd/archsimd: enable AMD64 architecture-specific SIMD by default

新規提案

要約

AIによる要約であり、誤りを含む場合があります。

概要

simd/archsimd パッケージに実装されたAMD64向けアーキテクチャ固有のSIMD命令群を、GOEXPERIMENT=simd による実験的フラグなしにデフォルトで利用可能にするためのproposalです。Go 1.26で実験的機能として導入されたSIMD APIを正式化し、標準ライブラリの一部として提供することを目指します。

ステータス変更

(未登録)active
2026年4月29日のProposal Review Meetingにて、@aclementsが本proposalを議事録に追加し、activeカラムへの移動を宣言しました。提案者でもある@aclementsが主要な検証ポイントを整理してミーティングに臨み、APIの安定性と互換性が十分に確認されたとして、正式な審査プロセスへの格上げが適切と判断されました。

技術的背景

現状の問題点

Go言語では従来、SIMD(Single Instruction Multiple Data:1つの命令で複数データを並列処理する技術)命令を利用するには手書きアセンブリが必要でした。この方法には以下の課題がありました。

  • アセンブリコードは記述が困難で保守性が低い
  • 非同期プリエンプション(goroutineの割り込み切り替え)を妨げる
  • 小さなカーネルのインライン展開(inlining)を阻害する
    Go 1.26では GOEXPERIMENT=simd を設定することで simd/archsimd パッケージが試験的に利用可能になりましたが、実験フラグが必要なため本番利用には障壁がありました。

提案された解決策

GOEXPERIMENT=simd なしで simd/archsimd パッケージをデフォルト有効化します。合わせて以下のAPIの追加と修正を行います。
API変更:

  • ShiftAll{Left,Right} 操作の引数型を uint64 から uint8 に変更(ただし@aclementsからは後述の懸念あり)
    API追加:
  • マスク操作: AndNot, Not, Xor, All, Any, None, String
  • ベクタの拡張ブロードキャスト: BroadcastAllTo{4,8,...}
  • 四倍精度ドット積: DotProductQuadruple{Signed,Unsigned}(Int8/Uint8ベクタ同士のドット積をInt32/Uint32で返す)
  • 整数ベクタの符号反転: (IntMxN) Neg() IntMxN

これによって何ができるようになるか

高性能な数値計算、画像処理、機械学習の推論処理などでSIMD命令を安全かつ効率的にGoコードから利用できるようになります。手書きアセンブリ不要で、型安全なAPIとしてSIMD演算が可能になります。

コード例

// Before: GOEXPERIMENT=simd が必要
// $ GOEXPERIMENT=simd go build ./...
import "simd/archsimd"
func addVectors(a, b []float32) []float32 {
    // 実験フラグなしではビルドエラー
    va := archsimd.LoadSlice[archsimd.Float32x8](a)
    vb := archsimd.LoadSlice[archsimd.Float32x8](b)
    return va.Add(vb).StoreSlice(result)
}
// After: 通常のGoコードとして利用可能
// $ go build ./...
import "simd/archsimd"
func sumInt8Vectors(a, b archsimd.Int8x16) archsimd.Int32x4 {
    // ドット積(4要素ごとの積和)を直接計算
    return a.DotProductQuadrupleSigned(b)
}
// マスク操作の例
func processWithMask(v archsimd.Float32x8, mask archsimd.Mask32x8) archsimd.Float32x8 {
    if mask.All() {
        return v.Sqrt() // 全要素が有効な場合のみ実行
    }
    return v.Sqrt().Masked(mask) // マスクされた要素のみ更新
}

議論のハイライト

  • APIの事前検証: Go 1.26実験版でユーザーによるテスト、大規模なソフトウェアエミュレーションによるテストカバレッジ、WebAssembly/ARM64 SVEへの適用可能性検証、ポータブル上位層APIのプロトタイプ実装(AMD64全サイズ・ARM64 NEON・wasm・純ソフトウェアエミュレーション対応)が完了しており、APIの信頼性が高い水準にある
  • 公開順序への懸念: @eliasnaurが「アーキテクチャ固有の archsimd をポータブルな simd より先に公開するのは逆ではないか」と指摘。@aclementsは「simd を構築するには先に archsimd を実装する必要があり、純粋に実用上の理由による」と回答
  • ShiftAllの引数型に関するAPI設計上の問題: @aclementsが uint8 への変更に懸念を表明。ShiftAll{Left,Right} はGoセマンティクス(オーバーシフトで全ゼロ/全1)を実装しているため、引数が255を超える可能性があり、uint8(count) とすると暗黙の切り捨てが発生する危険性がある。uint または uint64 が適切と主張
  • CPU機能チェッカーの必要性: @eliasnaurが #76175 のCPU機能静的チェッカーを必須機能と主張。archsimd は対応CPUを持たないハードウェアでpanic(不正命令例外)を引き起こすため、適切な機能チェックを静的解析で強制する仕組みが重要。@aclementsはフリーズ後に実装を再開予定と回答
  • クロスプラットフォームテスト: arm64マシン上でAMD64 SIMD コードをテストする方法が欲しいという要望が挙がっており、純ソフトウェアエミュレーションが解決策として検討されている

関連リンク