C++ クラスと SIMD 演算

SIMD 演算用の C++ クラスは、配列 (ベクトルデータ) を並列処理するときに使用するのが基本です。例として、2 つのベクトル AB の加算を考えてみます。各ベクトルは 4 つの要素で構成されているとします。整数ベクトル (Ivec) クラスを使用して、各配列から取り出した要素 A[i]B[i] を下の例のように加算します。

ループを使用して複数の要素を加算するときの一般的な方法

short a[4], b[4], c[4];
for (i=0; i<4; i++) /* needs four iterations */

c[i] = a[i] + b[i]; /* returns c[0], c[1], c[2], c[3] */

次の例を見ると、Ivec クラスを使用すれば 1 回の演算で同じ結果が得られることがわかります。

Ivec クラスを使用して複数の要素を加算する SIMD 手法

sIs16vec4 ivecA, ivecB, ivec C; /*needs one iteration*/

ivecC = ivecA + ivecB; /*returns ivecC0, ivecC1, ivecC2, ivecC3 */

使用できるクラス

並列処理は、C++ では通常それほど簡単には実装できませんが、インテル® C++ SIMD クラスを使用すればそれが可能です。次の表は、インテル® C++ SIMD クラスでクラスとライブラリーがどのように使用されるかを列挙したものです。

SIMD ベクトルクラス

命令セット

クラス

符号の有無

データ型

サイズ

要素の数

ヘッダーファイル

MMX® テクノロジー

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 拡張命令

F32vec4

符号付き

float

32

4

fvec.h

 

F32vec1

符号付き

float

32

1

fvec.h

ストリーミング SIMD 拡張命令 2

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

 

ほとんどのクラスは、どのデータ型についても同じような機能を持っていて、利用できるすべての組み込み関数で表現されています。ただし一部の機能については、データ型が変わるときにその機能を維持しようとするとパフォーマンスが下がる場合があるため、個々のクラスからは除外しています。

Note icon

即値をとるためにクラスの中に簡単に表現できない組み込み関数は実装していません。
(例えば、 _mm_shuffle_ps_mm_shuffle_pi16_mm_shuffle_ps, _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++ クラスの使用方法については、一般的なガイドラインがいくつかあります。クラスごとの使用規則については、「整数ベクトルクラス」および「浮動小数点ベクトルクラス」を参照してください。

MMX® テクノロジー・レジスターの消去

Ivec クラスと Fvec クラスを同時に使用している場合は、Ivec クラスから呼び出される MMX® 命令と、Fvec クラスから呼び出されるインテル® x87 アーキテクチャー浮動小数点命令がプログラムの中で混在していることがあります。次の Fvec 関数の中には浮動小数点命令が含まれています。

Note icon

MMX® テクノロジー・レジスターは浮動小数点レジスター上にエイリアス化されています。したがって、x87 浮動小数点命令を発行する前には、EMMS 命令の組み込み関数を使用して MMX® テクノロジー・ステートを消去する必要があります。次に例を示します。

ivecA = ivecA & ivecB;

MMX® 命令を使用する Ivec 論理演算

empty ();

ステートを消去

cout << f32vec4a;

x87 浮動小数点命令を使用する F32vec4 演算

 

Caution icon警告

MMX® テクノロジー・レジスターを消去しないとレジスターステートが不正な状態になります。そのため、処理が不正確になったり、パフォーマンスが低下したりすることがあります。

EMMS 命令のガイドラインに従う

「EMMS 命令を使用する際のガイドライン」に従うことを強くお勧めします。Ivec クラスを使用してコーディングを行う前に、このトピックを参照してください。