2008/10/14
Intel AVX その2 転送
やはり、上位 128bit と下位 128bit を横断する命令は限られているようです。
基本的には 128bit 4要素の SSE 命令を、一度に 2個演算できるのが AVX の
256bit 命令です。
・Intel AVX
・Intel-AVX-Programming-Reference-319433003.pdf
上下 128bit への任意転送は 128bit 単位のものが多く、SHUFPS/SHUBPD のような
32/64bit 単位で任意に入れ替えたり転送する命令がみあたりません。
float 8個や double 4個の演算時でも、値を入れ替える場合に 128bit 転送命令を
組み合わせる必要がありそうです。
256/128bit 間の転送には VEXTRACTF128, VINSERTF128 が使えます。
上位下位どちらの 128bit を使用するか選択します。
以下 256bit レジスタの ymm.low を下位 128bit、ymm.hi を上位 128bit と表記します。
VINSERTF128 は VMOVSS 系の部分更新命令なので、合成用の追加のレジスタが増えて
います。
実際は ymm2 に dest (ymm1) と同じレジスタを指定するケースが多いかもしれません。
128bit 単位の入れ替え命令として VPERM2F128 があります。
2つのソース ymm2,ymm3 の任意の 128bit を組み合わせて ymm1 に代入できます。
VBROADCAST は、唯一 32,64,128bit の任意の値を 256bit に転送できます。
複製されます。
F128 は SS, SD, PD, PS に相当し、128bit を表すようです。
(Larrabee では F256 がありそう)
これ以外の命令はほぼ 128bit SSE ×2 個分に相当します。
その他特殊な命令は次の通り。
VZEROALL は、ymm0~15 レジスタすべてをゼロクリアします。
VZEROUPPER はすべてのレジスタの上位 128bit のみクリア。
これらの命令は、レジスタの部分書き換えが発生してしまう Legacy SSE 命令の
レジスタ依存を断ち切ることが出来ます。
メモリとレジスタ間で条件付き転送が出来るようになっています。
転送単位は 32bit or 64bit で、転送するかどうか mask レジスタで指定します。
mask 値は転送データと同じサイズで、最上位 bit (符号) で判断します。
つまり負なら転送。
例えば xmm の各 32bit をシェーダーのように .x .y .z .w で表現すると
xmm2.x= -1
xmm2.y= 0
xmm2.z= -1
xmm2.w= 0
の場合
VMASKMOVPS xmm1, xmm2, m128
は次の転送を行います。
xmm1.x= m128[0]
xmm1.y= 0
xmm1.z= m128[2]
xmm1.w= 0
選択しながら読み出せるため便利ですが、mask レジスタを用意する必要があります。
命令も 3byte 長 VEX (0F38) に含まれています。
積和命令 FMA は AES と同じように別カテゴリに分かれています。
命令フィールドも 0F3A の 3byte VEX で独自のものです。
AVX は基本的に SSE をカバーしていますが SSE1~SSE4.1 までです。
SSE4.2 と AMD SSE5 は含まれていないようです。
積和命令 FMA~ FNMA~ は SSE5 と名称も機能も似通っています。
ちょうど SSE5 を VEX 拡張したかのような位置づけですが、opecode 等を見ても
関連性はありませんでした。
関連エントリ
・Intel AVX
基本的には 128bit 4要素の SSE 命令を、一度に 2個演算できるのが AVX の
256bit 命令です。
・Intel AVX
・Intel-AVX-Programming-Reference-319433003.pdf
上下 128bit への任意転送は 128bit 単位のものが多く、SHUFPS/SHUBPD のような
32/64bit 単位で任意に入れ替えたり転送する命令がみあたりません。
float 8個や double 4個の演算時でも、値を入れ替える場合に 128bit 転送命令を
組み合わせる必要がありそうです。
256/128bit 間の転送には VEXTRACTF128, VINSERTF128 が使えます。
上位下位どちらの 128bit を使用するか選択します。
以下 256bit レジスタの ymm.low を下位 128bit、ymm.hi を上位 128bit と表記します。
VEXTRACTF128 xmm1, ymm2, 0 // xmm1= ymm2.low VEXTRACTF128 xmm1, ymm2, 1 // xmm1= ymm2.hi VINSERTF128 ymm1, ymm2, xmm3, 0 // ymm1.low= xmm3, ymm1.hi= ymm2.hi VINSERTF128 ymm1, ymm2, xmm3, 1 // ymm1.low= ymm2.low, ymm1.hi= xmm3
VINSERTF128 は VMOVSS 系の部分更新命令なので、合成用の追加のレジスタが増えて
います。
実際は ymm2 に dest (ymm1) と同じレジスタを指定するケースが多いかもしれません。
128bit 単位の入れ替え命令として VPERM2F128 があります。
2つのソース ymm2,ymm3 の任意の 128bit を組み合わせて ymm1 に代入できます。
VPERM2F128 ymm1, ymm2, ymm3, 0 // ymm1.low= ymm2.low, ymm1.hi= ymm2.low VPERM2F128 ymm1, ymm2, ymm3, 1 // ymm1.low= ymm2.hi, ymm1.hi= ymm2.low VPERM2F128 ymm1, ymm2, ymm3, 2 // ymm1.low= ymm3.low, ymm1.hi= ymm2.low VPERM2F128 ymm1, ymm2, ymm3, 3 // ymm1.low= ymm3.hi, ymm1.hi= ymm2.low ~
VBROADCAST は、唯一 32,64,128bit の任意の値を 256bit に転送できます。
複製されます。
VBROADCASTSS xmm1, m32 // xmm1 32bit x4= m32, 上位 128bit は 0 VBROADCASTSS ymm1, m32 // ymm1 32bit x8= m32 VBROADCASTSD ymm1, m64 // ymm1 64bit x4= m64 VBROADCASTF128 ymm1, m128 // ymm1 128bit x2= m128
F128 は SS, SD, PD, PS に相当し、128bit を表すようです。
(Larrabee では F256 がありそう)
これ以外の命令はほぼ 128bit SSE ×2 個分に相当します。
その他特殊な命令は次の通り。
VZEROALL VZEROUPPER
VZEROALL は、ymm0~15 レジスタすべてをゼロクリアします。
VZEROUPPER はすべてのレジスタの上位 128bit のみクリア。
これらの命令は、レジスタの部分書き換えが発生してしまう Legacy SSE 命令の
レジスタ依存を断ち切ることが出来ます。
メモリとレジスタ間で条件付き転送が出来るようになっています。
転送単位は 32bit or 64bit で、転送するかどうか mask レジスタで指定します。
mask 値は転送データと同じサイズで、最上位 bit (符号) で判断します。
つまり負なら転送。
VMASKMOVPS xmm1, xmm2, m128 // 32bit x4, xmm2 が mask VMASKMOVPS ymm1, ymm2, m256 // 32bit x8, ymm2 が mask VMASKMOVPD xmm1, xmm2, m128 // 64bit x2, xmm2 が mask VMASKMOVPD ymm1, ymm2, m256 // 64bit x4, ymm2 が mask VMASKMOVPS m128, xmm1, xmm2 // 32bit x4, xmm1 が mask VMASKMOVPS m256, ymm1, ymm2 // 32bit x8, ymm1 が mask VMASKMOVPD m128, xmm1, xmm2 // 64bit x2, xmm1 が mask VMASKMOVPD m256, ymm1, ymm2 // 64bit x4, ymm1 が mask
例えば xmm の各 32bit をシェーダーのように .x .y .z .w で表現すると
xmm2.x= -1
xmm2.y= 0
xmm2.z= -1
xmm2.w= 0
の場合
VMASKMOVPS xmm1, xmm2, m128
は次の転送を行います。
xmm1.x= m128[0]
xmm1.y= 0
xmm1.z= m128[2]
xmm1.w= 0
選択しながら読み出せるため便利ですが、mask レジスタを用意する必要があります。
命令も 3byte 長 VEX (0F38) に含まれています。
積和命令 FMA は AES と同じように別カテゴリに分かれています。
命令フィールドも 0F3A の 3byte VEX で独自のものです。
AVX は基本的に SSE をカバーしていますが SSE1~SSE4.1 までです。
SSE4.2 と AMD SSE5 は含まれていないようです。
積和命令 FMA~ FNMA~ は SSE5 と名称も機能も似通っています。
ちょうど SSE5 を VEX 拡張したかのような位置づけですが、opecode 等を見ても
関連性はありませんでした。
関連エントリ
・Intel AVX