📚

AVX10.2の新機能

2024/08/13に公開

将来のIntel製CPUに搭載される命令セット拡張、AVX10.2の情報が先日出ました。

この記事では、AVX10.2の新機能をざっくりと紹介します。

静的な丸め指定

浮動小数点演算において演算結果を浮動小数点形式で正確に表現できない場合は丸めが発生します。この丸めのやり方はIEEE 754でいくつか定義されており、x86系では4つが利用可能です。丸めのやり方は通常は浮動小数点演算器の制御レジスターで選択されますが、AVX-512では、命令の機械語で丸め方を指定できるようになりました。

(宣伝:丸め方を静的に指定する話は「Binary Hacks Rebooted」にも書いたので是非読んでください。)

ただ、機械語のエンコードの都合上、AVX-512では「スカラー演算」と「512ビット幅のベクトル演算」にのみ静的な丸め指定が可能で、「128ビット/256ビット幅のベクトル演算」には静的な丸め指定ができませんでした。「機械語のエンコードの都合」というのは前に書いた記事

の「EVEX.L'LとEVEX.RCは実体が同一」の部分です。

AVX10.2ではEVEXプリフィックスが拡張され、3バイト目の「固定」だった部分を活用して256ビットの静的丸めが利用可能になります。詳しいエンコード方法は仕様書を見てください。

AI向けの浮動小数点演算の強化:FP8のサポート、BF16の強化など

FP8

ディープラーニングでは低精度の数値型が多用されます。浮動小数点数のFP16、BF16、整数のINT8、INT4など。浮動小数点数の方にももっと幅の小さいデータ型があると便利だと思われたのか、Open Compute ProjectというところがFP8の仕様を出しているようです:

概要は以下のようになります:

E4M3(またはHF8)

  • 符号ビット:1ビット
  • 指数部:4ビット
    • バイアスは7
  • 仮数部下位:3ビット
  • 指数部を少しでも広く取るため、無限大はない。NaNはある

E5M2(またはBF8)

  • 符号ビット:1ビット
  • 指数部:5ビット
    • バイアスは15
  • 仮数部下位:2ビット
  • 無限大とNaNがある

AVX10.2では、FP8のドット積、幅の広い型への変換、幅の広い型からの変換がサポートされます。

VCVTBIASPH2BF8
VCVTBIASPH2BF8S
VCVTBIASPH2HF8
VCVTBIASPH2HF8S

VCVTBIAS 系の命令は、入力のFP16の値にバイアスと呼ばれる整数(仮数部の下に続くように配置される)を加えて切り捨てによってFP8に変換します。末尾にSがつくものはオーバーフロー時に有限の最大値を返します。

VCVTHF82PH 命令は、E4M3(HF8)の浮動小数点数をFP16に変換します。

E5M2の浮動小数点数をFP16等に変換する命令はなさそうです。

VCVTNEPH2BF8
VCVTNEPH2BF8S
VCVTNEPH2HF8
VCVTNEPH2HF8S
VCVTNE2PH2BF8
VCVTNE2PH2BF8S
VCVTNE2PH2HF8
VCVTNE2PH2HF8S

VCVTNE 系の命令はFP16の入力をE5M2またはE4M3のFP8に変換します。常に最近接丸め(距離が等しい場合は偶数へ)が使用されます。末尾にSがつくものはオーバーフロー時に有限の最大値を返します。

BF16サポートの強化

IntelのCPUはこれまでもBF16 (bfloat16, brain float16)をサポートしてきましたが、従来のサポートは単精度との変換とドット積(AVX512_BF16)と行列演算(AMX-BF16)に限られてきました。

実際のところ、AVX512_BF16の命令はこれだけです:

VCVTNE2PS2BF16
VCVTNEPS2BF16
VDPBF16PS

AVX10.2では、BF16を直に演算対象とする四則演算などの命令が追加されるようです。

IEEE 754-2019のmin/max演算のサポート

浮動小数点数のmin/max演算に色々あるという話は

に書きました。AVX-512DQではIEEE 754-2008のminNum/maxNum演算をサポートしたという話も書きました。

今回追加されるのは、IEEE 754-2019のmin/max演算に対応する命令です。命令としては

VMINMAXNEPBF16
VMINMAX[PH,PS,PD]
VMINMAX[SH,SS,SD]

で、半精度(binary16)、単精度(binary32)、倍精度(binary64)のそれぞれスカラーとベクトル、それにBF16のベクトルに対応しているようです。

VMINMAXNEPBF16 のどこが「NE」なのかはよく分かりません。

WebAssemblyでは「入力のNaNを伝播させるmin/max演算」が採用されているため、Intelはこの機能の売り文句として「making it compatible for WebAssembly application development」としているようです。

飽和変換

浮動小数点数を固定長整数型に変換するとき、結果の型で表現できない値はどうすればいいでしょうか?従来のx86では、全ビット1で埋めるとか、2の補数表現の最小値を返していました。しかし、プログラミング言語によってはそれ以外の方法を規定しているというのは

に書いた通りです。この辺の話は「Binary Hacks Rebooted」にも書きました(宣伝)。

今回追加される命令は、以下の方法で整数型に変換します:

  • 小数点以下は切り捨て
  • NaNには0を
  • 無限大や範囲外の値には、表現可能な最大値・最小値を

切り捨て以外の方法を使いたい場合は他の命令と組み合わせます。

Intelによると、WebAssemblyやRustで必要になるので追加したらしいです。WebAssemblyはいいとして、私はRustには詳しくないのでこの言説の妥当性を判断できません。

一昔前なら「Javaで必要になるので」と言ってそうなものですが、WebAssemblyやRustが挙がるのは時代の流れですねえ。

Zero-extending Partial Vector Copies

SIMDレジスターに格納した32ビット値や16ビット値を他のSIMDレジスターにコピーする際、従来は下位128ビットごとコピーするか、32ビットや16ビットをコピーして上位は元の値を残す(あるいは他のレジスターからコピーする)、という選択肢しかありませんでした。今回、上位ビットをゼロクリアする選択肢が追加されます。

VMOVD は32ビットで、VMOVW は16ビットです。

VMOVDVMOVW は命令の名前としては以前からありましたが、SIMDレジスター同士でなく、オペランドの片方は汎用レジスター(またはメモリー)でした。

64ビット値に関しては、以前から (V)MOVQ があります。

FP Scalar Comparison

浮動小数点数の比較については、以前に記事を書きました:

今回、浮動小数点数の比較命令が強化されました。

従来は、浮動小数点数の比較には (v)(u)comis[h,s,d] 命令を使っていました。u の意味ですが、(v)ucomisd は入力にquiet NaNが含まれていても例外を発生させない比較命令です。いずれも、比較結果はEFLAGSレジスターのZF, PF, CFに格納します。疑似コードで書けば次のようになります:

(v)(u)comisd(x, y) {
    match compare(x, y) {
        UNORDERED: ZF,PF,CF := 0b111;
        GREATER_THAN: ZF,PF,CF := 0b000;
        LESS_THAN: ZF,PF,CF := 0b001;
        EQUAL: ZF,PF,CF := 0b100;
    }
    OF,AF,SF := 0b000;
}

フラグが立つ条件は次のようになります:

  • ZF: EQUALまたはUNORDEREDの場合に立つ。
  • PF: UNORDEREDの場合に立つ。
  • CF: LESS_THANまたはUNORDEREDの場合に立つ。

条件ジャンプ命令との関係は次のようになります:

ニーモニック 条件 浮動小数点数の比較結果との対応
JA (above), JNBE (not below or equal) CF=0 and ZF=0 GREATER_THAN
JAE (above or equal), JNB (not below), JNC (not carry) CF=0 EQUAL or GREATER_THAN
JB (below), JC (carry), JNAE (not above or equal) CF=1 LESS_THAN or UNORDERED
JBE (below or equal), JNA (not above) CF=1 or ZF=1 EQUAL, LESS_THAN or UNORDERED
JE (equal), JZ (zero) ZF=1 EQUAL or UNORDERED
JG (greater), JNLE (not less or equal) ZF=0 and SF=OF LESS_THAN or GREATER_THAN
JGE (greater or equal), JNL (not less) SF=OF 全て
JL (less), JNGE (not greater or equal) SF≠OF なし
JLE (less or equal), JNG (not greater) ZF=1 or SF≠OF EQUAL or UNORDERED
JNE (not equal) ZF=0 LESS_THAN or GREATER_THAN
JO (overflow) OF=1 なし
JP (parity), JPE (parity even) PF=1 UNORDERED
JPO (parity odd) PF=0 EQUAL, LESS_THAN or GREATER_THAN
JS (sign) SF=1 なし
浮動小数点数の比較結果の集合 使える命令 代用方法
EQUAL
LESS_THAN JAやJNBEをオペランドを反転させて使えば良い
GREATER_THAN JA, JNBE
UNORDERED JP, JPE
{EQUAL, LESS_THAN} JAE, JNB, JNCをオペランドを反転させて使えば良い
{EQUAL, GREATER_THAN} JAE, JNB, JNC
{EQUAL, UNORDERED} JE, JZ, JLE, JNG
{LESS_THAN, GREATER_THAN} JG, JNLE
{LESS_THAN, UNORDERED} JB, JC, JNAE
{GREATER_THAN, UNORDERED} JB, JC, JNAEをオペランドを反転させて使えば良い
{EQUAL, LESS_THAN, GREATER_THAN} JPO
{EQUAL, LESS_THAN, UNORDERED} JBE, JNA
{EQUAL, GREATER_THAN, UNORDERED} JBE, JNAをオペランドを反転させて使えば良い
{LESS_THAN, GREATER_THAN, UNORDERED}

これを見ると、「等価性(EQUAL)に基づいた条件ジャンプを一発で実行できる命令がない」ことが分かります。

AVX10.2では、浮動小数点数の比較を行う別の命令群が追加されます。これらは、立てるフラグの組み合わせが異なります。

VCOMXSD
VCOMXSH
VCOMXSS
VUCOMXSD
VUCOMXSH
VUCOMXSS

命令にUが含まれるやつはquiet NaNに対して例外を発生させないやつです。疑似コードで書けば

v(u)comxsd(x, y) {
    match compare(x, y) {
        UNORDERED: OF,SF,ZF,PF,CF := 0b11011;
        GREATER_THAN: OF,SF,ZF,PF,CF := 0b00000;
        LESS_THAN: OF,SF,ZF,PF,CF := 0b10001;
        EQUAL: OF,SF,ZF,PF,CF := 0b11100;
    }
    AF := 0;
}

となります。

フラグが立つ条件は次のようになります:

  • OF: EQUALまたはLESS_THANまたはUNORDEREDの場合に立つ。
  • SF: EQUALまたはUNORDEREDの場合に立つ。
  • ZF: EQUALの場合に立つ。
  • PF: UNORDEREDの場合に立つ。
  • CF: LESS_THANまたはUNORDEREDの場合に立つ。

条件ジャンプ命令との関係は次のようになります:

ニーモニック 条件 浮動小数点数の比較結果との対応
JA (above), JNBE (not below or equal) CF=0 and ZF=0 GREATER_THAN
JAE (above or equal), JNB (not below), JNC (not carry) CF=0 EQUAL or GREATER_THAN
JB (below), JC (carry), JNAE (not above or equal) CF=1 LESS_THAN or UNORDERED
JBE (below or equal), JNA (not above) CF=1 or ZF=1 EQUAL, LESS_THAN or UNORDERED
JE (equal), JZ (zero) ZF=1 EQUAL
JG (greater), JNLE (not less or equal) ZF=0 and SF=OF UNORDERED
JGE (greater or equal), JNL (not less) SF=OF EQUAL or UNORDERED
JL (less), JNGE (not greater or equal) SF≠OF LESS_THAN
JLE (less or equal), JNG (not greater) ZF=1 or SF≠OF EQUAL or LESS_THAN
JNE (not equal) ZF=0 LESS_THAN, GREATER_THAN or UNORDERED
JO (overflow) OF=1 EQUAL, LESS_THAN or UNORDERED
JP (parity), JPE (parity even) PF=1 UNORDERED
JPO (parity odd) PF=0 EQUAL, LESS_THAN or GREATER_THAN
JS (sign) SF=1 EQUAL or UNORDERED
浮動小数点数の比較結果の集合 使える命令 代用方法
EQUAL JE, JZ
LESS_THAN JL, JNGE
GREATER_THAN JA, JNBE
UNORDERED JG, JNLE, JP, JPE
{EQUAL, LESS_THAN} JLE, JNG
{EQUAL, GREATER_THAN} JAE, JNB, JNC
{EQUAL, UNORDERED} JGE, JNL, JS
{LESS_THAN, GREATER_THAN}
{LESS_THAN, UNORDERED} JB, JC, JNAE
{GREATER_THAN, UNORDERED} JB, JC, JNAEをオペランドを反転させて使えば良い
{EQUAL, LESS_THAN, GREATER_THAN} JPO
{EQUAL, LESS_THAN, UNORDERED} JBE, JNA, JO
{EQUAL, GREATER_THAN, UNORDERED} JBE, JNA, JOをオペランドを反転させて使えば良い
{LESS_THAN, GREATER_THAN, UNORDERED}

というわけで、AVX10.2を使うと「浮動小数点数が等しいか」を簡潔に判定できるようになります。

Media Acceleration

整数やFP16の内積(VNNI系の命令)や、EVEX版のsum of absolute difference命令が追加されるようです:

VDPPHPS
VMPSADBW
VPDPB[SU,UU,SS]D[,S]
VPDPW[SU,US,SS]D[,S]

まとめと宣伝

AVX10.2の新機能をざっくり紹介しました。

記事中にちょいちょい宣伝を挟みましたが、今度(2024年の8月末)Binary Hacks Rebootedという本が出ます(私は著者の一人です)。流石にAVX10.2の情報は載っていませんが、浮動小数点数のマニアックな話題や、SIMD命令の話題も載っているので、この記事に興味のある人は持っておいて損はないでしょう。

Discussion