Выравнивание памяти на 32-разрядном процессоре Intel

32-разрядные процессоры Intel, такие как Pentium, имеют 64-разрядную шину данных и поэтому получают 8 байт на доступ. Исходя из этого, я предполагаю, что физические адреса, которые эти процессоры излучают на адресной шине, всегда кратны 8.

во-первых, правильно ли это заключение?

во-вторых, если это правильно, то следует выровнять элементы структуры данных на 8-байтовой границе. Но я видел людей, использующих 4-байтовое выравнивание вместо этих процессоров.

как они могут быть оправданы в этом?

5 ответов


обычное эмпирическое правило (прямо из руководств Intels и AMD по оптимизации) заключается в том, что каждый тип данных должен быть выровнен по своему размеру. Ан int32 должен быть выровнен по 32-битной границе,int64 на 64-битной границе, и так далее. Чар подойдет где угодно.

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

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

во-вторых, если это правильно, то одного следует выровнять элементы структуры данных по 8-байтовую границу. Но я видел люди, использующие 4-байтовое выравнивание вместо этого на этих процессорах.

Я не вижу, как это делает разницу. CPU может просто выдать чтение для 64-битного блока, который содержит 4 байта. Это означает, что он получает 4 дополнительных байта до запрошенных данных или после них. Но в обоих случаях требуется только одно чтение. 32-разрядное выравнивание 32-разрядных данных гарантирует, что оно не пересечет 64-разрядную границу.


физическая шина шириной 64 бит ...кратно 8 --> да

однако, есть еще два фактора для рассмотрения:

  1. некоторый набор инструкций x86 адресован байтом. Некоторые из них выровнены по 32bit (поэтому у вас есть 4-байтовая вещь). Но никакая (основная) инструкция не выровнена по 64bits. CPU может обрабатывать несоосный доступ к данным.
  2. если вы заботитесь о производительности, вы должны думать о строке кэша, а не основной памяти. Строки кэш-памяти значительно более широкий.

они оправданы в этом, потому что изменение на 8-байтовое выравнивание будет представлять собой изменение ABI, и предельное улучшение производительности не стоит проблем.

Как кто-то уже сказал, cachelines дело. Все обращения к фактической шине памяти осуществляются с точки зрения строк кэша (64 байта на x86, IIRC). Смотрите "что каждый программист должен знать о памяти" ДОК, о котором уже упоминал. Так что реальный трафик выравнивается 64 байта.


64-битная шина, на которую вы ссылаетесь, подает кэши. Как CPU, всегда считывайте и записывайте целые строки кэша. Размер строки кэша всегда кратен 8, и ее физический адрес действительно выровнен на 8 байтовых смещениях.

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


для случайного доступа и до тех пор, пока данные не смещены (например, пересечение границы), я не думаю, что это имеет большое значение; правильный адрес и смещение в данных можно найти с помощью простого и конструктивного оборудования. Он становится медленным, когда одного доступа для чтения недостаточно для получения одного значения. Вот почему компиляторы обычно помещают небольшие значения (байты и т. д.) вместе, потому что они не должны быть на определенном смещении; шорты должны быть на четных адресах, 32-бит на 4-байтовых адресах и 64-разрядные 8-байтовые адреса.

обратите внимание, что если у вас есть кэширование и линейный доступ к данным, все будет по-другому.