Почему размер структуры должен быть кратным наибольшему выравниванию любого члена структуры

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

Ссылка: http://en.wikipedia.org/wiki/Data_structure_alignment

4 ответа

Решение

Хороший вопрос. Рассмотрим этот гипотетический тип:

struct A {
    int n;
    bool flag;
};

Итак, объект типа A должно занимать пять байтов (четыре для int плюс один для bool), но на самом деле это занимает восемь. Зачем?

Ответ виден, если вы используете такой тип:

const size_t N = 100;
A a[N];

Если каждый A были только пять байтов, то a[0] будет выравнивать, но a[1], a[2] и большинство других элементов не будет.

Но почему выравнивание имеет значение? Есть несколько причин, связанных с аппаратным обеспечением. Одна из причин заключается в том, что недавно / часто используемая память кэшируется в строках кэша на кремнии ЦП для быстрого доступа. Выровненный объект, меньший, чем строка кэша, всегда помещается в одну строку (но см. Интересные комментарии, приложенные ниже), но невыровненный объект может занимать две строки, тратя кеш-память.

На самом деле существуют еще более фундаментальные аппаратные причины, связанные с тем, как данные с байтовой адресацией передаются по 32- или 64-битной шине данных, совершенно отдельно от строк кэша. Не только смещение приведет к засорению шины дополнительными выборками (как и раньше, из-за перераспределения), но также заставит регистры сдвигать байты по мере их поступления. Еще хуже то, что смещение приводит к путанице в логике оптимизации (по крайней мере, в руководстве по оптимизации Intel говорится, что это так, хотя у меня нет личных знаний об этом последнем пункте). Таким образом, смещение очень плохо с точки зрения производительности.

По этим причинам обычно стоит тратить байты заполнения.

Обновление: комментарии ниже все полезны. Я рекомендую их.

В зависимости от аппаратного обеспечения выравнивание может быть необходимым или просто помочь ускорить выполнение.

Существует определенное количество процессоров (я полагаю, что ARM), в которых невыровненный доступ приводит к аппаратному исключению. Легко и просто.

Несмотря на то, что типичные процессоры x86 более снисходительны, за доступ к невыровненным фундаментальным типам все еще накладывается штраф, поскольку процессору приходится выполнять больше работы, чтобы вносить биты в регистр, прежде чем он сможет работать с ним. Компиляторы обычно предлагают определенные атрибуты / прагмы, когда упаковка все же желательна.

Если размер регистра ЦП составляет 32 бита, то он может захватить память, находящуюся на 32-битных границах, с помощью одной инструкции сборки. Он медленнее захватывает 32 бита, а затем получает байт, который начинается с бита 8.

Кстати: там не должно быть padding. Вы можете попросить, чтобы структуры были упакованы.

Из-за виртуальной адресации.

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

Кстати, я нашел страницу в Википедии об этом довольно хорошо написано.

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