データをアライメントすると、組み込み関数のパフォーマンスが向上します。インテル® ストリーミング SIMD 拡張命令 (インテル® SSE) を使用する場合は、メモリー操作の際にデータのアライメントを 16 バイトに合わせる必要があります。特に、_mm_load、_mm_store の組み込み関数にアドレスを渡したときは、__m128 オブジェクトのアライメントを合わせなければなりません。float 型の配列を宣言し、キャストすることによってそれを __m128 オブジェクトとして扱う場合は、float 型配列のアライメントが正しく揃うようにする必要があります。
より正確なデータのアライメントを合わせるためにコンパイラーへ命令するときは、__declspec(align) を使用してください。例えば int 型のデータ・オブジェクトは、特に指定しなければ 4 の倍数のバイト・アドレスに配置されます。一方、__declspec(align) を使えば、4 の代わりに 8、16、32 のいずれかの倍数のアドレスを使用するようにコンパイラーに命令できます。ただし IA-32 アーキテクチャーの場合は次の制約があります。
この機能を使用して、キャッシュラインの使用効率を最適化できます。よく使用する小さなオブジェクトをいくつか組み合わせて 1 つの構造体 (struct) を作り、その構造体 (struct) を強制的にキャッシュラインの先頭に配置すれば、どのオブジェクトにアクセスしたときでも、すぐにそのオブジェクトがキャッシュにロードされるため、パフォーマンスが大きく向上します。
この拡張属性の構文は、次のとおりです。
align(n)
ここで、n は 2 の何乗かを示す値 (最大 4096) です。データのアライメントは、この値のバイト境界に合わせられます。
このリリースでは、__declspec(align(8)) が正しく動作しません。代わりに__declspec(align(16)) を使用してください。
対象となるデータ型のサイズより小さい値を指定すると、無効になります。言い換えれば、データは、元々設定されているアライメントの最大値か、__declspec(align) で指定したアライメントかのいずれかに揃えられます。
変数の種類が静的か自動かにかかわらず、個々の変数についてアライメント要求を設定できます。(特に指定しない限り、グローバル変数と静的変数には静的記憶域期間が設定されて、ローカル変数には自動記憶域期間が設定されています。) パラメーターのアライメントは調整できません。struct フィールド、class フィールドのアライメントの調整もできません。ただし struct (または union、class) のアライメントは拡げられます。その場合は、該当する型のオブジェクトがすべて影響を受けます。
例えば、ある関数が 2 次元配列の添字にローカル変数 i、j を使用する場合、これらの変数は次のように宣言されます。
int i, j;
2 つの変数は、通常は組み合わせて使用します。しかし、これらの変数が異なるキャッシュラインに割り当てられると、パフォーマンスが低下します。これを防ぐには、次のように 2 つの変数を宣言します。
__declspec(align(16)) struct { int i, j; } sub;
これで、コンパイラーは、2 つの変数を必ず同じキャッシュラインに割り当てます。C++ では、struct 変数名 (上の例では sub) が省略できます。ただし C の場合は必要であり、i、j への参照を、sub.i、sub.j のように記述しなければなりません。
この添字ペアの付いた関数を多く使用する場合は、次の例のように、その関数に対して struct 型を宣言して使用するほうが便利です。typedef struct __declspec(align(16)) { int i, j; } Sub;
キーワード struct の後に __declspec(align) を置くと、該当する型のオブジェクトすべてに対してしかるべきアライメント要求が出ます。各パラメーターの配置は __declspec(align) に影響されません。必要であれば、アライメントの正しく揃っているローカル変数にパラメーターの値を代入できます。
また、配列などのグローバル変数についても、アライメントを指定できます。
__declspec(align(16)) float array[1000];