続Go 1.26のSIMD実装

前回に続く

bleu48.hatenablog.com

 

前回SaturateToInt8がAVX512依存してしまう話をしていた。

世間的にもAVX2対応が基準だろうと某AIが言うのでそのように対応していたが、そもそもGo言語のライブラリでしれっとAVXバージョン混在状態になっている理由は何故かと考えると、サーバサイドはインテルもAMDもAVX512対応しているからであることに気づく。

Go言語の主戦場は多コアサーバなのでこれでよかったのだ。

 

今回問題となったSaturateToInt8もよくない。

これは各要素を8ビット幅に収める命令だがSIMD命令を使わないと個々の変数を8ビットに収めてSIMDレジスタに格納する手間となる。これはGo言語では相当遅い。

なお、func (Int16x8) SaturateToInt8は128ビット、func (Int16x16) SaturateToInt8は256ビットであるにも関わらずAVX512の命令なのだ。

では、開き直って512ビットのfunc (Int16x32) SaturateToInt8を使えばどうだという話になる。で、AVX512依存を覚悟して他の命令群も512ビット化するとどうなったかというと結構高速化した。全体で2割程度、局所的にはもっと出ていることになる。

 

更に言うとAVX512はZen4とZen5で速度向上が大きい。Zen5でAVX512は効く。

本件メインの演算はDotProductPairsSaturatedであるが、これもAVX2の256ビット命令とAVX512の512ビット命令がある。この命令の実行速度がZen4とZen5の大きな差である。

 

ということで、Zen5においてAVX2実装とAVX512実装で倍くらいの速度差が実現した。

 

 

更新しながら様々なバージョンをFloodgateに投入して迷惑をかけている感があるが、恐らく一番強いのがgo_test13na3でレート2700を超えている。2800というとgpsfishの基準レートなのでもう少しといったところだろうか。ちなみにこれだけZen5である。

念願のYSS1000Kとの直接対局は少ないが超えたかどうかの判定は楽しみである。

 

技術的な話を少ししておくと現状前向き枝狩りが軽いLMRのみである。Stockfish由来の様々な枝狩りを使うのが今風なので、伸びしろを残しているというかコーディングが面倒で放置しているというかメインループが長くなるのが嫌とかそんなところである。まぁ習作なのでコピペプログラミングみたいなことをしても仕方ないってのもある。

気が向いたらStockfishに寄せるかもしれないし、別の伸びしろを見つけるかもしれない。

 

---

インテルがサーバだけAVX512対応している件、邪推してみた。

Zen5が出ている現状AVX512はAMDの方が速い。インテルが対応しても勝てる見込みがない。が、まだ普及していないので非対応とすれば世間的にはAVX2バイナリが流通することになって差が縮まるということだろう。

サーバ側は前バージョンで対応したものを下げることができなかったのでそのまま残していると考える。まぁ、クライアント側はEコアが非搭載なのでしかたないという体になっている。

まぁSIMDが活躍する分野はどの程度あるか分からないが動画音声のエンコードデコード、ファイル圧縮展開、暗号化復号化などは大きく寄与するだろう。そっかサーバには不可欠だな。