インテル® C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス

GAP メッセージ (診断 ID 30756)

メッセージ

構造体 '%s' を 2 つに分割することでデータの局所性を向上させます。アクセス回数の多いフィールド '%s' を 1 つの構造体にまとめ、残りのフィールドを別の構造体にまとめることで、パフォーマンスが向上します。また別の方法として、構造体フィールドの順序を変更することでパフォーマンスが向上します。推奨するフィールドの順序: '%s'。

アドバイス

このメッセージは、構造体の分割とフィールドの並べ替えの両方が適用可能な場合に出力されます。構造体の分割が適切に適用されるとパフォーマンスの向上が見込めます。通常、フィールドの並べ替えは簡単に適用できますが、大幅なパフォーマンスの向上は見込めません。

構造体の分割やフィールドの並べ替えを行う前に、これらを適用するための条件が満たされていることを確認する必要があります。適用条件の一部は、それぞれの変換の説明を参照してください。

次の例について考えてみます。

//str_split_reord.c 
struct str {
    int a1, b1, carr[100], c1, e1; 
};
 
#define N 1000000
 
struct str *sp;
 
void allocate_str_mem() {
    sp = malloc(N * sizeof(struct str)); 
}
 
int hot_func1() {
    int i, ret = 0;
 
    for (i = 0; i < 1000000; i++) {
        ret += sp[i].a1;
        ret += sp[i].c1;
    }
    sp->carr[0] = ret;
    return ret; 
}
 
int hot_func2() {
    int ret = 0, i;
    for (i = 0; i < 100000; i++) {
        ret += sp[i].a1;
        ret -= sp[i].e1;
    }
    return ret; 
}
 
int hot_func3() {
    int ret = 0, i;
    for (i = 0; i < 1000000; i++) {
        ret += sp[i].b1;
    }
    return ret; 
}

このプログラムをコンパイルすると、次のようなメッセージが表示されます。

drive: program-name: リマーク #30756: (DTRANS) 構造体 'str' を 2 つに分割することでデータの局所性を向上します。アクセス回数の多いフィールド 'a1, b1, c1' を 1 つの構造体にまとめ、残りのフィールドを別の構造体にまとめることで、パフォーマンスが向上します。また別の方法として、構造体フィールドの順序を変更することでパフォーマンスが向上します。推奨するフィールドの順序: 'a1, c1, e1, b1, carr'。

安全であることが分かっている場合は、次のようにプログラムコードを変更して構造体 'str' を分割します。現在のモジュール以外にある構造体 'str' へのほかの参照も同様に変更する必要があります。

struct str_cold {
    int carr[100], e1; 
};
 
struct str {
    int a1, b1, c1; struct str_cold *cold_ptr; 
};
 
#define N 1000000
 
struct str *sp;
 
void allocate_str_mem() 
{
    struct str *temp;
    struct str_cold *cold_begin;
    int index;
 
    temp = malloc(N * sizeof(struct str) + N * sizeof(struct str_cold));
    sp = temp;
    cold_begin = (struct str_cold *) (temp + N);
    for(index = 0; index < N; index++) {
       temp[index].cold_ptr = cold_begin + index;
    } 
}
 
int hot_func1() {
    int i, ret = 0;
 
    for (i = 0; i < 1000000; i++) {
        ret += sp[i].a1;
        ret += sp[i].c1;
    }
    sp->cold_ptr->carr[0] = ret;
    return ret; 
}
 
int hot_func2() {
    int ret = 0, i;
    for (i = 0; i < 100000; i++) {
        ret += sp[i].a1
        ret -= sp[i].cold_ptr->e1;
    }
    return ret; 
}
 
int hot_func3() {
    int ret = 0, i;
    for (i = 0; i < 1000000; i++) {
        ret += sp[i].b1;
    }
    return ret; 
}

上記の例では、プログラムへの変更は次のように別の方法としてアドバイスされた構造体 'str' のフィールドを並べ替えるだけです。

//str_split_reord.c 
struct str {
    int a1, c1, e1, b1, carr[100]; 
}; 
...

確認

このアドバイスは、現在のコンパイルのフィールド参照に基づくものです。このコード変更は、アプリケーションのすべてのソースファイルのフィールド参照に適用してください。また、このコード変更によってオリジナルのプログラムのセマンティクスが変更されないことを確認してください。