Go 1.27もそろそろ近づいてきたようです。Future Tech Blog恒例のGoリリース連載です。
| Date | Title | Author3 |
|---|---|---|
| 2026/7/28 | インデックス記事+HTTP3/SIMD(この記事) | 渋川 |
| 2026/7/29 | go mod tidy | 真野隼記 |
| 2026/7/30 | ジェネリクスメソッド | 市川裕也 |
| 2026/7/31 | json v2 | 辻大志郎 |
| 2026/8/3 | ゴルーチンリークプロファイル (goroutineleak) を活用したデバッグ | 棚井龍之介 |
別記事で取り上げる以外の更新
betaやRCが出る前から話題沸騰のUUIDv7対応については、convtoさんがすでに詳しく解説を書いてくださいっているのでそちらを参照されるとよいかと思います。
ざっと変更があったところで、細かいところを除くとこんなところかなと思います。
- 80バイト未満のメモリ割り当てコストを最大30%削減
- 量子コンピュータで計算力が上がっても大丈夫になることを見越した、ポスト量子暗号のcrypto/mldsaパッケージの追加
- compress/flate(zipの中で使われる圧縮アルゴリズム)が高速化
- net/httpのHTTP/2サーバーがクライアントの優先度を考慮するようになった
- net/http/httptestのNewServerは127.0.0.1の空きポートを使った実際の通信を行うサーバーだったが、オンメモリで通信を行い、testing/synctestとの親和性の高いNewTestServer()が追加
- 念入りに実行前後でメモリを消去して、取り扱った機密情報が他のgoroutineからアクセスされないようにする
runtime/secretパッケージが追加 bytesとstringsに、最後にマッチした文字列でカットして、その前後を返すCutLast()を追加
HTTP/3はどうか?
3年前のエントリーでGo本体のHTTP3対応の計画を紹介しました。
- 最終的にはnet/quicが作られる
- ただし、APIの安定化のために、まずは準標準パッケージとして golang.org/x/net/quicを作っていく
- github.com/quic-go/quic-go という実装はあるが、それをそのまま取り込むことはしない
現在もquicの実装は粛々と進んでいます。
また、テスト用の実装しかなさそうですが、4月にhttp3パッケージも追加されました。
JavaがJDK26すでにリリースしてしまったのでプログラミング言語でHTTP/3一番乗り、というわけにはいかないのですが楽しみですね。
SIMD
まだ実験的サポートで、GOEXPERIMENT=simdという環境変数がないと使えない機能です。
前回の連載でも取り上げましたが、SIMDは今回もアップデートがありました。
simd/simdarchパッケージ
前回のときはsimd/simdarchパッケージが追加されたという内容を書きましたが、この時はIntel系のSIMD命令(128ビット、256ビット、512ビット)のみに対応していました。今回、1.27ではARMのNeonとWASM(ともに128ビット)にも対応しました。
こちらは今後もアーキテクチャが増えるが、APIは安定ではないとされています。
実際、1.26のときのStore(*[4]int32)はStoreArray(*[4]int32)に変わり、StoreSlice([]int32)がStore([]int32)に変わって引数の型が変わって以前作ったサンプルが動かなかったり、ARMに動いたが、archsimd.Int16x8にはDotProductPairs()メソッドがない、というエラーが出たり、アーキテクチャごとにもサポートしている内容が変わっています。
こちらのパッケージはともかく「アーキテクチャの性能を引き出す低レベルパッケージ」ということで、simd/archsimdのプロポーザルではsyscallパッケージ相当という扱いです。
simdパッケージ
今回はその上により抽象度の高いosパッケージ相当のsimdパッケージが追加されました。
simd/simdarchを見た後にこちらを見ると「????」となること間違いなしです。APIを見ても扱うビット数の情報がどこにもない。32ビット浮動小数点数を扱うデータ型を全部出してみると、simdパッケージの扱うデータサイズが見えてこないですよね。
simdarch.Float32x4simdarch.Float32x8simdarch.Float32x16simd.Float32s
というのも、こちらは実行環境に合わせて扱うビット数が変わるAPIなっています。simdのプロポーザルを見ると、「そのCPUが扱える最大のビット数を扱えるのがとりあえずベストだろう」ということです。
実際、今回新しく作られた型で確認するとM3のARMのmacだと1.27のリリースノート通りに128ビットであることがわかります。
// ビット数を取得 |
実際どの様に使うかというと、指定されたスライスから値を読み込んで、SIMDのメモリ状況を再現した配列のような型と、それに含まれる読み込んだ個数を返すLoadXXXPart()というファクトリ関数を使ってSIMDで扱える単位でデータを切り出します。
func Process(s []int8) { |
前回扱ったベクトル検索では、ベクトルは768次元でした。このような多次元のデータを扱う場合は、環境によって16個単位、32個単位、64個単位という個数が変わっても似た様な感じでループでデータを扱うのであまり問題は発生しないでしょう。
ちょっとおもしろかったのは、simd.Emulated() boolというエミュレーションでも動作するというポイントですね。
とはいえ、これはベストなのか?
この様な仕組みで、例えば座標変換でflaot32が入った4行4列の行列を使いたいとします。これをこのsimdパッケージで扱うとします。128ビットであれば32x4なのでうまく和や積の計算は無駄なく行えますが、512ビットアーキテクチャだったらどうなるでしょうか?
それは開いた領域はゼロ埋めをして計算して有効な箇所だけ取り出すという処理になります。先ほども利用したLoad型名Part()というファクトリ関数は、入力のデータ数がすくなければゼロ埋めをすると書かれています。そうなると、単にメモリ効率が1/4に低下するだけです。先ほどの長大なベクトルを扱うには問題はありませんが、小さい固定長のベクトルではいまいちかもしれません。
もっとも、2つ、4つの座標の計算をまとめて一度に計算するというロジックを作れば効率は良いです。こういう使い方をしてもらいたいのかもしれません。実際、ビット数ごとにロジックを何種類も作るよりかは楽ですね。
もう1つの問題は実行効率です。
AVX512に対応しているからといって、512ビット演算が最速とは限らないケースがあります。64ビットの普通の四則演算と比べると、ビット数が多い分、CPUの中の実装面積が増えます。しかもそんなに四六時中動いているわけじゃない。特に、最近のbig.LITTLE構成を取るインテルのCPUの場合、消費電力が少ない方のコアに委譲が発生します。命令セットが異なるCPUをスムーズにやりとりするのは困難なためか、最近のインテルでは512ビットの取り扱いを省いています。
そういう節約は他社でも行われていて、AMDは256ビットのAVX演算機を2つ組み合わせて512ビットを実現しています。この場合、256ビットが一番効率が良いということもありえます。そのあたりは以下の記事が詳しいです。
Goの処理系はおそらく、CPUの命令セットをサポートしているかどうかで扱うビット数を変えていると思いますが、必ずしも裏の仕組みはCPUの情報には乗らないはずなので、
まとめ
相変わらず、知る人ぞ知るというか、わかっている人向けなSIMDですが、simdパッケージのおかげでだいぶ扱いやすくなってきました。そこそこ高水準で扱いやすい言語だけどSIMDもだいぶ扱いやすい(アセンブラを書くよりは)ということで、アルゴリズムを色々作って比較してみる試作環境としてはだいぶ扱いやすいと思います。多少効率の面では気になったりもしますが、まあ最新のCPU使ってね、ってことですかね。
標準ライブラリではこのようなSIMDの活用なケースはアセンブラでガリガリ書かれていましたがなかなか真似したりやってみるのは困難でした。持っていないアーキテクチャのテストなんかはどうしても雑になってしまいがちでした、サードパーティ含めて今後はSIMDを活用して効率が上がるケースも増えそうです。クロスコンパイルとかも楽ですしね。