Ice Lake の vfpbench 結果と AVX512 命令

Ice Lake の PC (mac) を手に入れたので vfpbench を AVX512 対応にしてみました。結果は下記のとおりです。

AVX512 reg GFLOPS fop IPC
AVX512VL vmulps ymm 256bit 55.2 8 6.3
AVX512VL vaddps ymm 256bit 55.6 8 6.3
AVX512VL vfmaddps ymm 256bit 111.3 16 6.3
AVX512F vmulps zmm 512bit 53.7 16 3.1
AVX512F vaddps zmm 512bit 54.0 16 3.1
AVX512F vfmaddps zmm 512bit 108.0 32 3.1
AVX512F vfmadd+mulps zmm 512bit 81.0 24 3.1
AVX512F vfmadd+addps zmm 512bit 81.2 24 3.1

・Core i5-1030NG7 (MacBook Air)

AVX512 は、512bit 単位の演算が可能となる Intel の新しい SIMD 命令セットです。AVX/AVX2 は 256bit 幅なので 2倍に増えたことになります。単精度の浮動小数点演算なら 512/32bit = 16並列です。4×4 matrix が 1レジスタに収まります。

SSE から AVX に進化したときと同じように、命令のエンコードも一新されており機能も増えています。SSE → AVX では 3オペランドになり 64bit 時に 16個のレジスタが利用できました。AVX → AVX512 ではレジスタフィールドが 5bit となり、レジスタ数が 32個に増えています。さらに 7個の mask レジスタを併用することができます。

mask レジスタは初期の GPU の Shader にあった書き込みマスクと同じものです。出力レジスタのうち必要な要素のみ置き換えることができます。残りの部分は元の値が残りますが、保存せずにゼロクリアを行うこともできます。

mask レジスタが導入されたことで、大きくて一見小回りがきかないようにみえる 512bit のレジスタも、任意のベクタ長とみなして扱うことができます。単精度なら 16個分ですが、mask を併用すれば 1~15 個の単位でも読み書きができるわけです。

SSE/AVX では少々扱いづらかった x,y,z の 3要素ベクタも簡単にロードすることができます。 下記の例ではベクタ (x,y,z) を 4個まとめて読み込んでいます。長さ 12 のベクタとして読み込んだあと、それぞれ (x,y,z) → (x,y,z,0) に展開しています。

movl    $0x0fff, %eax
kmovw   %eax, %k1
movl    $0x7777, %eax
kmovw   %eax, %k2

movups     data(%rbp), %zmm0{%k1}{z}    ; mask 0xfff で読み込み
vexpandps  %zmm0, %zmm1{%k2}{z}         ; mask 0xfff -> 0x7777 に展開

AVX2 でも gather を使えば似たようなことができますが、どちらかといえば gather 命令は Shader の InputAssembler に相当します。

もちろん常時マスク付きで演算を行うと無駄が生じていることになります。GPU の SIMT のように、SoA で扱う方が AVX512 の本来の形かもしれません。この場合レジスタはベクタではなく 16個(単精度の場合)のスカラーとなり、mask レジスタは 16個のフラグレジスタとみなせます。

float d= n.dot( l );
if( d < 0 ){
    c+= a;
}else{
    c+= b * d;
}

例えば↑こんな感じのコードを 16並列で実行すると↓こうなります。

vmulps        %zmm8, %zmm11, %zmm20
vfmadd231ps   %zmm9, %zmm12, %zmm20
vfmadd231ps   %zmm10, %zmm13, %zmm20
vcmpps        $1, %zmm20, %zmm18, %k1
knotw         %k1, %k2
vfmadd231ps   %zmm20, %zmm19, %zmm21{%k1}
vaddps        %zmm17, %zmm21, %zmm21{%k2}

比較命令の結果であるフラグ値は mask レジスタに入るので、条件成立時と不成立時の演算結果をそのまま合成することができます。

AVX512 の説明が少々長くなりましたが、IceLake の vfpbench の結果を見てみます。ピークの GFLOPS 値は AVX(FMA3) 命令でも AVX512 命令でも変わっていないことがわかります。Ice Lake の場合 zmm (512bit) の AVX512F 命令は同時に 1命令しか実行できないようです。

AVX reg GFLOPS fop IPC
FMA3 vfmaddps ymm 256bit 111.0 16 6.3
AVX512VL vfmaddps ymm 256bit 111.3 16 6.3
AVX512F vfmaddps zmm 512bit 108.0 32 3.1

この結果は Intel のサイトでも確認できます。

Intel: Intrinsics Guide

上記ページの「__m512 _mm512_fmadd_ps (__m512 a, __m512 b, __m512 c)」を見ると、Icelake の throughput は 1 なので実行に 1 cycle かかることがわかります。対して Skylake (server)/Knights Landing の方は 0.5 なので、2 命令実行できることを意味しています。

また同じ AVX512 の命令でも、mask 付きの ymm(256bit) は AVX/FMA 同様 2命令実行できています。Intrinsics Guide で確認してみると throughput は 0.5 なので合っているようです。

よって IceLake の場合は、性能を上げるために無理に AVX512 命令を使う必要は無さそうです。ただし最初に紹介したように、AVX512 ではレジスタが倍増し便利な機能も命令も増えています。mask が使える便利な AVX2 として見ても十分使い物になるのではないでしょうか。

反面 CPU によって対応機能が細かく別れてしまうので、最適化と互換性の両立はますます難しくなりそうです。

なお vfpbench の log で IPC に大きな数値が出ているのは CPU のベースクロックを元にしているためです。今回使用した Core i5-1030NG7 はベースが 1.1GHz で Single Thread の Boost 時に 3.5GHz になります。そのため 3.5/1.1 の 3.18 がおよそ IPC=1 と思ってください。

より詳細なログは下記からどうぞ

Hyperでんち: VFP Benchmark Log 計測結果まとめ

関連エントリ
4倍速い Ryzen 9 3950X の UE4 コンパイル速度
Snapdragon 845 ARMv8.2A 半精度 fp16 演算命令を使ってみる / Deep Learning 命令
Snapdragon 835 と 845 のコンパイル時間の比較&浮動小数点演算能力
Snapdragon 845 の浮動小数点演算速度
ARM CPU の浮動小数点演算能力まとめ
HTC 10 Snapdragon 820 Kyro の浮動小数点演算能力
iPhone SE, Apple A9 の浮動小数点演算速度
ARM Cortex-A53 の浮動小数点演算速度とコンパイル時間の比較
iPod touch 6 の浮動小数点演算速度は Core 2 Duo ライン超え
iPad Air 2 (Apple A8X) の浮動小数点演算能力
ARM cpu vfp の種類と fp16 命令を使ってみる
Intel AVX その3 命令
Intel AVX その2 転送
Intel AVX