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