🦉
F#でアセンブリプログラミング(準備編)
F#でのSIMD
F#でSIMD命令を扱う方法を説明していきます。
SIMD命令
SIMD命令はSystem.Runtime.Intrinsics.X86
名前空間に置かれています。
- AVX
Avx
クラスが定義されています。 - AVX2
Avx
クラスを継承したAvx2
クラスが定義されています。 - AVX-512
Avx512F
、Avx512F.VL
、Avx512BW
、Avx512BW.VL
、Avx512DQ
、Avx512DQ.VL
、Avx512CD
、Avx512CD.VL
、Avx512Vbmi
、Avx512Vbmi.VL
に分割して定義されています。
Avx512F
クラスがAvx2
クラスを継承しています。
これらのクラスの静的メソッドを呼び出すとSIMD命令が生成されます。
ベクトルデータ型
SIMD命令は、専用レジスタから値を読み取り、結果を専用レジスタに書き込みます。一部は専用レジスタだけでなく直接メモリを参照することもできます。これらの条件を満たすためにSystem.Runtime.Intrinsics
名前空間に専用のデータ型が用意されています。
JITコンパイラはこれらのデータ型がどのタイミングで読み出され、どのタイミングで書き込まれるかを踏まえてレジスタに割り付けていきます。レジスタが不足する場合はアラインメントされたメモリ上に配置します。また読み出される際、メモリから直接読み込み可能な命令で使われている場合は割と積極的にメモリ割り付けもします。
これらのデータ型を扱いやすくするため、四則演算・ビット操作は演算子オーバーロードされていますので、通常の変数のように扱うことができます。またそれ以外の汎用的な処理についてもVector128
クラス、Vector256
クラス、Vector512
クラスに静的メソッドが用意され、一部は拡張メソッドとしても呼び出せます。
ただし、プロセッサに該当する機能が存在しない場合は、しれっとエミュレートされます[1]。SIMD命令が使われているかどうかJITコンパイル結果を逆アセンブルして確認する必要があります。
実践編へ続く。
-
データがメモリに書き出されて非SIMD命令で処理されます。 ↩︎
Discussion