Расположение в памяти структуры. структура массивов и массив структур в C/C++

В C/C++ предположим, что я определяю простую структуру с именем point следующее.

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

Для конкретного экземпляра этой структуры говорят test A являются A.height, A.age, A.gender смежный в памяти?

В более общем смысле, как выглядят макеты в памяти для структуры массивов и массива структур? Картина была бы действительно полезна.

3 ответа

Решение

Они не обязательно будут смежными в памяти. Это связано с заполнением структуры.

Тем не менее, в вашем конкретном случае, это вполне может быть смежным. Но если вы изменили порядок на что-то вроде этого:

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

тогда их скорее всего не будет. Тем не менее, в вашем конкретном случае, вы все равно, вероятно, получите заполнение после gender, чтобы выровнять структуру до 8 байтов.


Разница между SoA (структура массивов) и AoS (массив структур) будет выглядеть следующим образом:

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 использует меньше памяти, потому что заполнение происходит только между массивами, а не между каждой структурой.

Отдельные поля являются смежными в том смысле, что между ними не будет храниться никаких других переменных. Они также гарантированно хранятся в указанном вами порядке. Но компилятор может свободно вставлять отступ между отдельными полями, например, чтобы выровнять вещи по границам слова. Итак, следующее:

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

может выглядеть так в памяти:

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

Что касается разницы между SoA и AoS, они выложены именно так, как вы можете себе представить.

Кроме стандартного отказа от ответственности "это зависит от вашей платформы, компилятора, бла-бла-бла"... да, height, age, а также gender будет непрерывным в памяти без заполнения между ними:

height|age|gender

Однако, если у вас есть массив testкаждый элемент массива будет иметь отступ между ними после каждого gender так что следующий элемент height правильно выровнен.

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

Если ваша цель состоит в том, чтобы использовать наименьшее количество памяти, то вы должны использовать "структуру массивов", так как она не использует заполнение.

|height0|height1|...

|age0|age1|...

|gender0|gender1|...

Другие вопросы по тегам