インテル® C++ コンパイラー 19.0 デベロッパー・ガイドおよびリファレンス
C++ SIMD の各クラスには、次のような基本的な機能があります。
演算
水平データのサポート
分岐の圧縮/削除
キャッシング・ヒント
目的の結果を得るためには、これら諸機能についてそれぞれ理解し、これら諸機能が互いにどのように作用し合うのかを理解することが重要です。
SIMD C++ の各クラスは、シフトや飽和をはじめとしてほとんどの算術演算用の垂直演算子に対応しています。
演算子の種類としては、+、-、*、/、逆数 (rcp、rcp_nr)、平方根 (sqrt)、平方根の逆数 (rsqrt、rsqrt_nr) があります。
rcp および rsqrt という演算は、非常に短いレイテンシーで近似値の計算ができる命令のことで、最低でも 12 ビットの精度の結果が得られます。インテル以外のプロセッサーで使用すると、異なる結果になることがあります。rcp_nr および rsqrt_nr という演算は、ソフトウェア的にいくつか改良がなされていて、パフォーマンスにはごく小さい影響しか与えずに精度の高い近似値が得られます。("nr" は、近似値を使用してパフォーマンスを改善する数学的手法の 1 つである "Newton-Raphson 法" の頭文字です)。
C++ SIMD の各クラスは、一部の算術演算については水平処理もできます。"水平" とは、1 つのベクトルに含まれているすべての要素について、横方向に端から端まで計算することを指します。一方、"垂直" とは、2 つの異なるベクトルについて、縦方向に要素単位で計算していくことを指します。
例えば add_horizontal、unpack_low、pack_sat という各関数は、水平データに対応しています。このように水平データに対応していると、SIMD 命令の能力をすべては利用できない一部のアルゴリズムも使用できるようになります。
シャッフル組込み関数も水平データフローのもう 1 つの例です。シャッフル組込み関数は、即値引数を使用するため、C++ の各クラスの中には示されていません。ただし、C++ クラスでは、シャッフル組込み関数を他の C++ 関数と混在できます。次に例を示します。
F32vec4 fveca, fvecb, fvecd;
fveca += fvecb;
fvecd = _mm_shuffle_ps(fveca,fvecb,0);
SIMD アーキテクチャーでの分岐処理は、複雑で時間がかかります。SIMD C++ クラスには、論理演算、最大値/最小値関数、条件付き選択、比較を使うことによって分岐をなくすための関数がいくつか用意されています。次の例について考えてみます。
short a[4], b[4], c[4];
for (i=0; i<4; i++)
c[i] = a[i] > b[i] ? a[i] : b[i];
この演算は i の値とは無関係です。i の値が変わるごとに、その結果は、実際の値に応じて A か B のいずれかになります。分岐をなくす簡単な方法の 1 つは、次のように select_gt 関数を使うことです。
Is16vec4 a, b, c
c = select_gt(a, b, a, b)
インテル® ストリーミング SIMD 拡張命令には、プリフェッチとストリーミング・ヒントという機能があります。データをプリフェッチすると、メモリー・レイテンシーの影響を最小限に抑えられます。ストリーミング・ヒントを使用すると、キャッシュしないほうが望ましいデータを示すことができます。