Макет в памяти структуры. структура массивов и массив структур в C/С++
В C/С++ предположим, что я определяю простую структуру с именем point
следующим образом.
struct test
{
double height;
int age;
char gender;
}
Для конкретного экземпляра этой структуры говорят, что test A
являются A.height, A.age, A.gender
смежными
в памяти?
В более общем плане, как выглядят макеты в памяти для структуры массивов и массива структур? Изображение было бы действительно полезно.
Ответы
Ответ 1
Они не обязательно будут смежными в памяти. Это связано с структурой прокладки.
Однако в вашем конкретном случае это может быть очень смежным. Но если вы изменили порядок на что-то вроде этого:
struct test
{
char gender;
int age;
double height;
}
то они, скорее всего, не будут. Однако в вашем конкретном случае вы, вероятно, получите дополнение после gender
, чтобы перестроить структуру до 8 байтов.
Разница между 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 прокладывает между массивами.
Они имеют следующие компромиссы:
- AoS имеет тенденцию быть более читабельным для программиста, поскольку каждый "объект" хранится вместе.
- AoS может иметь лучшую локальность кэша, если к нему будут доступны все члены структуры.
- SoA потенциально может быть более эффективным, так как группирование одинаковых типов данных иногда выставляет векторизацию.
- Во многих случаях SoA использует меньше памяти, потому что заполнение происходит только между массивами, а не между каждой структурой.
Ответ 2
Отдельные поля смежны в том смысле, что между ними не будут храниться другие переменные. Они также гарантированно хранятся в том порядке, в котором вы заявили. Но компилятор может свободно вставлять промежутки между отдельными полями, например, для выравнивания объектов до границ слов. Итак, следующее:
struct test
{
double height;
char gender;
int age;
};
может выглядеть так в памяти:
+7 +6 +5 +4 +3 +2 +1 +0
+---+---+---+---+---+---+---+---+
0x0000 | height |
+---+---+---+---+---+---+---+---+
0x0008 | age | |gen|
+---+---+---+---+---+---+---+---+
Что касается разницы между SoA и AoS, они выложены точно так, как вы могли себе представить.
Ответ 3
Кроме стандартного отказа от слова "это зависит от вашей платформы, компилятора, бла-бла-блаха"... да, height
, age
и gender
будет смежным в памяти без промежуточного промежутка между ними:
height|age|gender
Однако, если у вас есть массив test
, каждый элемент массива будет иметь отступы между ними после каждого gender
, чтобы следующий элемент height
был правильно выровнен.
|height0|age0|gender0|padding0|height1|age1|gender1|padding1|...
Если ваша цель состоит в том, чтобы использовать наименьший объем памяти, тогда вы должны пойти со структурой массивов, поскольку он не использует отступы.
|height0|height1|...
|age0|age1|...
|gender0|gender1|...