Выравнивание памяти на 32-разрядном процессоре Intel
32-разрядные процессоры Intel, такие как Pentium, имеют 64-битную шину данных и, следовательно, извлекают 8 байтов на каждый доступ. Исходя из этого, я предполагаю, что физические адреса, которые эти процессоры испускают на адресной шине, всегда имеют кратность 8.
Во-первых, верно ли это заключение?
Во-вторых, если это правильно, то следует выровнять элементы структуры данных на 8-байтовой границе. Но я видел людей, использующих 4-байтовое выравнивание вместо этих процессоров.
Как они могут быть оправданы при этом?
Ответы
Ответ 1
Обычное эмпирическое правило (прямо из руководств по оптимизации Intels и AMD) заключается в том, что каждый тип данных должен быть выровнен по собственному размеру. int32
должен быть выровнен на 32-битной границе, int64
на 64-битной границе и т.д. A char подойдет только в любом месте.
Другое эмпирическое правило - конечно, "компилятор рассказал о требованиях к выравниванию". Вам не нужно беспокоиться об этом, потому что компилятор знает, что нужно добавить правильные дополнения и смещения, чтобы обеспечить эффективный доступ к данным.
Единственное исключение - при работе с инструкциями SIMD, где вам нужно вручную обеспечить выравнивание для большинства компиляторов.
Во-вторых, если это правильно, то один должен выровнять элементы структуры данных на 8-байтовая граница. Но я видел люди, использующие 4-байтовое выравнивание вместо этого на этих процессорах.
Я не понимаю, как это имеет значение. CPU может просто выдать чтение для 64-битного блока, который содержит эти 4 байта. Это означает, что он либо получает 4 дополнительных байта перед запрошенными данными, либо после него. Но в обоих случаях требуется только одно чтение. 32-битное выравнивание 32-битных данных гарантирует, что он не пересечет 64-битную границу.
Ответ 2
Физическая шина имеет ширину 64 бит... несколько из 8 → да
ОДНАКО, есть еще два фактора:
- Некоторый набор инструкций x86 адресован байтом. Некоторые из них выровнены по 32 бита (поэтому у вас есть 4 байта). Но никакая (основная) команда не выровнена на 64 бита. ЦП может обрабатывать неверный доступ к данным.
- Если вы заботитесь о производительности, вы должны думать о линии кэша, а не о основной памяти. Кэш-линии намного шире.
Ответ 3
Они оправданы тем, что переход к 8-байтовому выравниванию будет представлять собой изменение ABI, а предельное улучшение производительности не стоит проблем.
Как уже сказал кто-то еще, вопрос имеет значение. Все обращения к фактической шине памяти относятся к линиям кэша (64 байта на x86, IIRC). См. "Что каждый программист должен знать о памяти", который уже упоминался. Таким образом, фактический объем трафика памяти равен 64 байтам.
Ответ 4
Шина с 64 битами, на которую вы ссылаетесь, подает кеши. Как процессор, всегда читайте и записывайте целые строки кэша. Размер строки кэша всегда кратен 8, а его физический адрес действительно выровнен с 8-байтовыми смещениями.
Передача кэша в регистр не использует внешнюю шину данных, поэтому ширина этой шины не имеет значения.
Ответ 5
Для случайного доступа и пока данные не смещены (например, пересекают границу), я не думаю, что это имеет большое значение; правильный адрес и смещение в данных можно найти с помощью простой конструкции AND в аппаратном обеспечении. Он становится медленным, когда один доступ для чтения недостаточен для получения одного значения. Это также объясняет, почему компиляторы обычно помещают небольшие значения (байты и т.д.) Вместе, потому что они не должны быть с определенным смещением; шорты должны быть на четных адресах, 32-битных по 4-байтным адресам и 64-битных по 8-байтным адресам.
Обратите внимание, что если у вас есть кеширование и доступ к линейным данным, все будет по-другому.