SIMD演算用の C++ クラスは、配列(ベクトルデータ)を並列処理するときに使用するのが基本です。例として、2個のベクトルAとBの加算を考えてみます。 各ベクトルは4個の要素で構成されているとします。整数ベクトル(Ivec)クラスを使用して、各配列から取り出した要素A[i]とB[i]を下の例のように加算します。
次の例を見ると、Ivecクラスを使用すれば1回の演算で同じ結果が得られることがわかります。
並列処理は、C++ では通常それほど簡単には実装できませんが、インテル® C++ SIMD クラスを使用すればそれが可能です。次の表は、インテル C++ SIMD クラスでクラスとライブラリがどのように使用されるかを列挙したものです。
命令セット | クラス | 符号の有無 | データ型 | サイズ | 要素数 | ヘッダファイル |
---|---|---|---|---|---|---|
MMX® テクノロジ(IA-32 ベースおよび Itanium® ベース・システムで利用可) | I64vec1 | 不定 | __m64 | 64 | 1 | ivec.h |
I32vec2 | 不定 | int | 32 | 2 | ivec.h | |
Is32vec2 | 符号付き | int | 32 | 2 | ivec.h | |
Iu32vec2 | 符号なし | int | 32 | 2 | ivec.h | |
I16vec4 | 不定 | short | 16 | 4 | ivec.h | |
Is16vec4 | 符号付き | short | 16 | 4 | ivec.h | |
Iu16vec4 | 符号なし | short | 16 | 4 | ivec.h | |
I8vec8 | 不定 | char | 8 | 8 | ivec.h | |
Is8vec8 | 符号付き | char | 8 | 8 | ivec.h | |
Iu8vec8 | 符号なし | char | 8 | 8 | ivec.h | |
ストリーミングSIMD拡張命令 (IA-32 ベースおよび Itanium ベース・システムで利用可) | F32vec4 | 符号付き | float | 32 | 4 | fvec.h |
F32vec1 | 符号付き | float | 32 | 1 | fvec.h | |
ストリーミングSIMD拡張命令2(IA-32 ベース・システムでのみ利用可) | F64vec2 | 符号付き | double | 64 | 2 | dvec.h |
I128vec1 | 不定 | __m128i | 128 | 1 | dvec.h | |
I64vec2 | 不定 | long int | 64 | 4 | dvec.h | |
Is64vec2 | 符号付き | long int | 64 | 4 | dvec.h | |
Iu64vec2 | 符号なし | long int | 32 | 4 | dvec.h | |
I32vec4 | 不定 | int | 32 | 4 | dvec.h | |
Is32vec4 | 符号付き | int | 32 | 4 | dvec.h | |
Iu32vec4 | 符号なし | int | 32 | 4 | dvec.h | |
I16vec8 | 不定 | int | 16 | 8 | dvec.h | |
Is16vec8 | 符号付き | int | 16 | 8 | dvec.h | |
Iu16vec8 | 符号なし | int | 16 | 8 | dvec.h | |
I8vec16 | 不定 | char | 8 | 16 | dvec.h | |
Is8vec16 | 符号付き | char | 8 | 16 | dvec.h | |
Iu8vec16 | 符号なし | char | 8 | 16 | dvec.h |
ほとんどのクラスは、どのデータ型についても同じような機能を持っていて、利用できるすべての組込み関数で表現されています。ただし一部の機能については、データ型が変わるときにその機能を維持しようとするとパフォーマンスが下がる場合があるため、個々のクラスからは除外しています。
注
即値をとるためにクラスの中に簡単に表現できない組込み関数は実装していません。
(例えば、_mm_shuffle_ps, _mm_shuffle_pi16,
_mm_extract_pi16, _mm_insert_pi16)
必要なクラス・ヘッダファイルは、インテル C++ コンパイラと一緒にインクルード・ディレクトリにインストールされます。各クラスを有効にするときは、次の表に示すように、プログラム・ファイルの中で#includeディレクティブを使用してください。
拡張命令セット | インクルード・ディレクティブ |
---|---|
MMX テクノロジ | #include <ivec.h> |
ストリーミングSIMD拡張命令 | #include <fvec.h> |
ストリーミングSIMD拡張命令2 | #include <dvec.h> |
上の表で、dvec.hはfvec.hの内容を含んでいます。 同様にfvec.hはivec.hの内容を含んでいます。IvecクラスとFvecクラスの両方を使用したい場合は、fvec.hをインクルードするだけで済みます。同様に、ストリーミングSIMD拡張命令2を利用する場合に、その3つとも含むすべてのクラスを使用するときは、dvec.hファイルをインクルードするだけで済みます。
C++ クラスの使用方法については、一般的なガイドラインがいくつかあります。クラスごとの使用規則については、「整数ベクトルクラス」および「浮動小数点ベクトルクラス」を参照してください。
IvecクラスとFvecクラスを同時に使用している場合は、Ivecクラスから呼び出されるMMX 命令と、Fvecクラスから呼び出される Intel x87 アーキテクチャ浮動小数点命令がプログラムの中で混在していることがあります。次のFvec関数の中には浮動小数点命令が含まれています。
注
MMX テクノロジ・レジスタは浮動小数点レジスタ上にエイリアス化されています。したがって、x87浮動小数点命令を発行する前には、EMMS命令の組込み関数を使用してMMX テクノロジ・ステートを消去する必要があります。次に例を示します。
ivecA = ivecA & ivecB; | /* Ivec logical operation that uses MMX instructions */ |
empty (); | /* clear state */ |
cout << f32vec4a; | /* F32vec4 operation that uses x87 floating-point instructions */ |
注意
MMX テクノロジ・レジスタを消去しないとレジスタステートが不正な状態になります。そのため、処理が不正確になったり、パフォーマンスが低下したりすることがあります。
「EMMS命令を使用する際のガイドライン」に従うことを強くお勧めします。Ivec クラスを使用してコーディングをするときは、こちらをご覧ください。