インテル® MIC アーキテクチャーの ABI に準拠するデータアクセスのための要素単位のアライメント

同カテゴリーの次の記事

ガイド付き自動並列化

この記事は、インテル® デベロッパー・ゾーンに掲載されている「Element-wise Alignment Requirements for Data Accesses」の日本語参考訳です。


IA-32 アーキテクチャーやインテル® 64 アーキテクチャーと異なり、インテル® MIC アーキテクチャーでは、すべてのデータアクセスがそのサイズに従って適切にアライメントされている必要があります。適切にアラインされていないと、予期しない動作を引き起こすことがあります。

例えば、整数変数 (4 バイトで格納) は 4 の倍数のアドレスに割り当てなければなりません。同様に、倍精度浮動小数点変数やポインター変数 (8 バイトで格納) は 8 の倍数のアドレスに割り当てなければなりません。

構造体と共用体は、正確にアラインされたコンポーネントのアライメントを想定します。各メンバーは、適切なアライメントで最小のオフセットに割り当てられます。オブジェクトのサイズは、常にオブジェクトのアライメントの倍数です。

なお、IA-32 アーキテクチャーやインテル® 64 アーキテクチャーでも、適切にソースを変更してアラインすると、パフォーマンスの向上につながることがあります。

1. インテル® MIC アーキテクチャーの ABI に準拠していない Fortran の例を次に示します。オブジェクト内部で “sequence” 文が使用されていることに注意してください。sequence 文を使用する場合,データ宣言の順序を、すべてのデータ項目が自然にアライメントされるように指定する必要があります。

次のサンプルコードについて考えてみましょう。

    type, publicpublic :: GridEdge_t
        sequence
        integer :: head_face ! needed if head vertex has shape (i.e. square)
        integer :: tail_face ! needed if tail vertex has shape (i.e. square)
        integer :: head_ind !
        integer :: tail_ind !
        type (GridVertex_t),pointer :: head ! edge head vertex
        type (GridVertex_t),pointer :: tail ! edge tail vertex
        logical :: reverse
    end type GridEdge_t

個々のフィールドのサイズを合計すると、オブジェクトのサイズは 36 バイトになります。sequence 文が使用されているため、オブジェクトはメモリーで連続しています。オブジェクトを配列にする場合、配列要素はパディングバイトなしでパックされます。このため、最初の要素以外では、フィールドの先頭または最後にアクセスするときにアラインされていない可能性があります。 ABI の要件によれば、フィールドの先頭と最後は 8 バイトでアラインしなければいけません。つまり、GridEdge_t のアライメントは 8 バイトで、GridEdge_t のサイズは 8 の倍数でなければいけません。sequence 文が削除されると、コンパイラーは 40 バイトの正しいサイズで GridEdge_t を自動的に作成します。

以下は、ABI に違反した C のサンプルコードです。

#include
int main(int argc, char **argv)
{
        char *blob = (char *)malloc(100); // malloc は 8 バイトにアラインされたポインターを返す
        float *ptr = (float *)(blob + argc); // プログラムが引数なし、argc=1 で呼び出されたと仮定 

        for (int i = 0; i < argc; i++)
        {
                ptr[i] = 0; // 浮動小数点データが 4 バイトにアラインされていないため、GP フォルト
        }
        return 0;
}

この種のアクセス違反は、ユーザーが記述したメモリー割り当てルーチンで発生することがあります。アライメントを意識せずにメモリーを割り当てる関数をユーザーが記述することは珍しくありません。その場合、インテル® MIC アーキテクチャーの ABI の要件により、ランタイムエラーが発生する可能性があります。開発者は、ソースコードに適切な変更を加えて問題に対処する必要があります。

C (または C++) で "#pragma pack" を使用した場合も ABI 違反を引き起こすことがあります。

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

関連記事