Расположение в памяти структуры. структура массивов и массив структур в 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 прокладывает между массивами.
Они имеют следующие компромиссы:
- AoS имеет тенденцию быть более читабельным для программиста, поскольку каждый "объект" хранится вместе.
- AoS может иметь лучшую локальность кэша, если все члены структуры доступны вместе.
- SoA потенциально может быть более эффективным, поскольку группирование одних и тех же типов данных иногда приводит к векторизации.
- Во многих случаях 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|...