web-dev-qa-db-ja.com

構造体のメモリ内のレイアウト。配列の構造体およびC / C ++の構造体の配列

C/C++では、次のようにpointという名前の単純な構造体を定義するとします。

struct test
{
double height;
int    age;
char   gender;
}

この構造体の特定のインスタンスについては、test AA.height, A.age, A.genderメモリ内で隣接していますか?

より一般的には、配列の構造と構造の配列のメモリ内のレイアウトはどのように見えますか?写真は本当に役に立ちます。

39
smilingbuddha

それらは必ずしもメモリ内で連続しているとは限りません。これは struct padding が原因です。

ただし、特定のケースでは、連続している可能性があります。しかし、次のような順序に変更した場合:

struct test
{
    char   gender;
    int    age;
    double height;
}

そうなると、おそらくそうならないでしょう。ただし、特定のケースでは、構造体を8バイトに再調整するために、genderの後にパディングが発生する可能性があります。


SoA(Struct of Arrays)とAoS(Array of Structs)は次のようになります。

SoA:

-----------------------------------------------------------------------------------
| double | double | double | *pad* | int | int | int | *pad* | char | char | char |
-----------------------------------------------------------------------------------

AoS:

-----------------------------------------------------------------------------------
| double | int | char | *pad* | double | int | char | *pad* | double | int | char |
-----------------------------------------------------------------------------------

各構造体内のAoSパッドに注意してください。一方、SoAはアレイ間をパディングします。

これらには次のトレードオフがあります:

  1. AoSは、各「オブジェクト」が一緒に保持されるため、プログラマにとって読みやすくなる傾向があります。
  2. AoSは、構造体のすべてのメンバーが一緒にアクセスされる場合、キャッシュの局所性が向上する可能性があります。
  3. SoAは、同じデータ型をグループ化すると、ベクトル化が発生することがあるので、潜在的に効率が上がる可能性があります。
  4. 多くの場合、SoAはより少ないメモリを使用します。なぜなら、パディングはすべての構造体の間ではなく配列の間だけだからです。
64
Mysticial

個々のフィールドは、それらの間に他の変数が格納されないという意味で隣接しています。また、宣言した順序で格納されることが保証されています。ただし、コンパイラは個々のフィールドの間にパディングを挿入して、たとえばWordの境界に合わせて自由に配置できます。したがって、次のようになります。

struct test
{
    double height;
    char   gender;
    int    age;
};

メモリ内では次のようになります。

         +7  +6  +5  +4  +3  +2  +1  +0
        +---+---+---+---+---+---+---+---+
0x0000  |            height             |
        +---+---+---+---+---+---+---+---+
0x0008  |      age      |           |gen|
        +---+---+---+---+---+---+---+---+

SoAとAoSの違いについては、想像どおりにレイアウトされています。

8

「お使いのプラットフォーム、コンパイラ、blahblahblahに依存します」という標準の免責事項を除いて...はい、heightage、およびgenderはメモリ内で連続しない間のパディング:

height|age|gender

ただし、testの配列がある場合、次の要素のgenderが適切に配置されるように、各配列要素は各heightの後にそれらの間にパディングがあります。

|height0|age0|gender0|padding0|height1|age1|gender1|padding1|...

可能な限り少ないメモリ量を使用することが目標である場合は、パディングを使用しないため、「配列の構造」を使用する必要があります。

|height0|height1|...

|age0|age1|...

|gender0|gender1|...

0
Jim Buck