x86-64の浮動小数点とSIMD入門
XMMスカラー演算からpacked SSE・AVX、アラインメント、機能検出まで
x86-64の浮動小数点とSIMD入門
本記事は講義を目的としています。 SSE2対応x86-64 user modeを出発点とし、AVX系はCPUとOS stateの両方を確認します。
XMMレジスタが見えてもvectorizedとは限らない。addssは低いfloat一個、addpsはfloat四個を加算する。同じ保存領域をscalarとpacked命令が共有する。
XMMは型ではない
packed float32 : 4 × 32-bit lanes
packed float64 : 2 × 64-bit lanes
scalar float32 : low 32 bits
scalar float64 : low 64 bits
packed int32 : 4 × 32-bit lanes
addss xmm0, xmm1
addsd xmm0, xmm1
addps xmm0, xmm1
addpd xmm0, xmm1
opcodeが解釈を決める。x87は旧来のstack-registerモデル、SSE/SSE2はXMMと主に2 operand、AVXはYMMとVEX 3 operand、AVX-512はZMMとmaskを追加する。
laneごとの演算
movups xmm0, [rcx]
movups xmm1, [rdx]
addps xmm0, xmm1
movups [r8], xmm0
結果は[a0+b0, a1+b1, a2+b2, a3+b3]である。lane間carryを持つ128ビット整数加算ではない。paddb/paddw/paddd/paddqもlane幅を示す。
alignment
movaps xmm0, [rcx] ; aligned
movups xmm0, [rcx] ; unaligned
movdqa xmm0, [rcx]
movdqu xmm0, [rcx]
aligned形式へ誤ったアドレスを渡すとfaultし得る。base allocationが整列していてもfield offsetまで整列するとは限らない。cache lineとpage境界も測定する。
FP順序とNaN
IEEE 754加算は結合則を満たさず、vector reductionは順序を変える。scalar基準とbit一致しないことがあるため、許容誤差、NaN、infinity、signed zero、roundingを契約に含める。fast-math optionも記録する。
ucomiss xmm0, xmm1
jp unordered_case
ja above_case
NaNはunorderedを作る。ucomissとcomissは例外動作が異なるため、実際にflagを作ったopcodeを見る。
shuffleとreduction
shufps xmm0, xmm1, imm8
pshufd xmm0, xmm1, imm8
immediateのlane選択はinstruction referenceで読む。多くのshuffleはAoS/SoA変換、transpose、broadcast、horizontal reductionの手掛かりである。
AVX featureとABI
AVX実行前にCPUID、OSのextended state対応、XGETBVのXMM/YMM有効化、配布先CPUの保証を確認する。AVX対応はAVX2やAVX-512対応を意味しない。
legacy SSEとの境界でvzeroupperが見えるのは一部CPUのtransition penalty対策である。必要性はCPUとcompiler conventionに従う。
System Vでは通常XMMはcaller-saved、Microsoft x64ではxmm6〜xmm15の低128ビットがnonvolatileである。Windows handwritten ASMは保存とunwindを正しく行う。
tailとoverread
vector幅の倍数でない長さにはscalar tailまたはmaskが必要である。「allocationに余白がありそう」というoverreadはobject/page/sanitizer契約を破る。APIが明示保証しない限り使わない。
auto-vectorizationはalias、loop-carried dependency、call、strict FP、cost model、target ISA不足で失敗し得る。reportとintrinsicをASMより先に検討する。
まとめ
XMMは128ビット保存領域であり、opcodeがscalar/packedとlane型を決める。SIMDは複数要素を処理する代わりにalignment、tail、FP再結合、feature detection、ABI保存契約を追加する。正確性を証明してから実workloadで測定する。