Назначение выравнивания памяти

По общему признанию, я не понимаю. Скажем, у вас есть память с словом памяти длиной 1 байт. Почему вы не можете получить доступ к переменной длиной 4 байта в одном доступе к памяти на неуравновешенном адресе (т.е. Не делимом на 4), как это происходит с выровненными адресами?

Ответы

Ответ 1

Это ограничение многих базовых процессоров. Его обычно можно обойти, выполнив 4 неэффективных однобайтовых выборки, а не один эффективный выбор из слова, но многие спецификаторы языка решили, что было бы проще просто объявить их вне закона и заставить все быть выровненными.

В этой ссылке содержится гораздо больше информации, которую OP обнаружил.

Ответ 2

Подсистема памяти на современном процессоре ограничена доступом к памяти при детализации и выравнивания размера слова; это имеет место по ряду причин.

Speed ​​

Современные процессоры имеют несколько уровней кеш-памяти, которые должны быть перенесены; поддерживающие однобайтовые чтения сделают пропускную способность подсистемы памяти плотно связанной с пропускной способностью исполнительного блока (также известной как cpu-bound); это все напоминает то, как Режим PIO был превзойден DMA по многим причинам на жестких дисках.

ЦП всегда читает размер своего слова (4 байта на 32-битном процессоре), поэтому, когда вы выполняете неравномерный адресный доступ - на процессоре, который его поддерживает, процессор собирается прочитайте несколько слов. ЦП будет считывать каждое слово памяти, которое запрашивает адрес. Это приводит к усилению до 2X количества транзакций памяти, необходимых для доступа к запрошенным данным.

Из-за этого он может очень легко считывать два байта, чем четыре. Например, скажем, у вас есть структура в памяти, которая выглядит так:

struct mystruct {
    char c;  // one byte
    int i;   // four bytes
    short s; // two bytes
}

В 32-битном процессоре он, скорее всего, будет выровнен, как показано здесь:

Struct Layout

Процессор может считывать каждый из этих элементов в одной транзакции.

Скажем, у вас была упакованная версия структуры, возможно, из сети, где она была упакована для эффективности передачи; он может выглядеть примерно так:

Packed Struct

Чтение первого байта будет одинаковым.

Когда вы попросите процессор дать вам 16 бит от 0x0005, ему нужно будет прочитать слово от 0x0004 и сдвинуть влево 1 байт, чтобы поместить его в 16-битный регистр; некоторая дополнительная работа, но большинство из них может справиться с этим за один цикл.

Когда вы запрашиваете 32 бита от 0x0001, вы получите 2-кратное усиление. Процессор будет считывать с 0x0000 в реестр результатов и сдвигать влево 1 байт, затем снова считывать с 0x0004 во временный регистр, сдвигать вправо 3 байта, затем OR с результирующим регистром.

Диапазон

Для любого заданного адресного пространства, если архитектура может предположить, что 2 младших разряда всегда равны 0 (например, 32-разрядные машины), тогда он может получить доступ в 4 раза больше памяти (2 сохраненных бита могут представлять 4 различных состояния) или тот же объем памяти с 2 битами для чего-то вроде флагов. Отключение 2 младших младших разрядов от адреса даст вам 4-байтовое выравнивание; также называемый stride размером 4 байта. Каждый раз, когда адрес увеличивается, он эффективно увеличивает бит 2, а не бит 0, т.е. Последние 2 бита всегда будут оставаться 00.

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

Атомарность

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

Заключение

Система памяти процессора довольно сложна и сложна, чем описано здесь; обсуждение того, как процессор x86 фактически обращается к памяти, может помочь (многие процессоры работают аналогично).

Есть еще много преимуществ для привязки к выравниванию памяти, которые вы можете прочитать в этой статье IBM.

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

Бонус: Кэши

Еще одно выравнивание для производительности, о котором я упоминал ранее, - это выравнивание по строкам кэша, которые (например, на некоторых процессорах) 64B.

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

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

Ответ 3

вы можете с некоторыми процессорами (nehalem может это сделать), но ранее весь доступ к памяти был выровнен по 64-разрядной (или 32 так как шина имеет ширину 64 бита, вам приходилось брать 64 бит за раз, и было значительно проще получить их в выровненных "кусках" из 64 бит.

Итак, если вы хотите получить один байт, вы взяли 64-битный кусок, а затем замаскировали ненужные биты. Легко и быстро, если ваш байт находился в правильном конце, но если бы он находился в середине этого 64-битного фрагмента, вам пришлось бы маскировать нежелательные биты, а затем переводить данные в нужное место. Хуже того, если вам нужна переменная в 2 байта, но она была разделена на 2 куска, то для этого требовалось удвоить требуемый доступ к памяти.

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

Ответ 4

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

Таким образом, процессор считывает из кэша L1 на кристалле, который в наши дни часто составляет 32 КБ. Но шина памяти, которая соединяет кэш L1 с ЦП, будет иметь значительно меньшую ширину размера строки кэша. Это будет порядка 128 бит.

Итак:

262,144 bits - size of memory
    128 bits - size of bus

Misaligned accesses будут иногда перекрывать две строки кэша, и для получения данных потребуется считывание полностью нового кэша. Это может даже пропустить весь путь до DRAM.

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

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

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

Ответ 5

@joshperry дал отличный ответ на этот вопрос. В дополнение к его ответу, у меня есть некоторые цифры, которые показывают графически эффекты, которые были описаны, особенно усиление 2X. Здесь ссылка на таблица Google показывает, как выглядит эффект разных выравниваний слов. Кроме того, здесь ссылка на Github gist с кодом для теста. Тестовый код адаптирован из статьи, написанной Джонатаном Ренцшем, на который ссылается @joshperry. Тесты проводились на Macbook Pro с четырехъядерным 64-разрядным процессором Intel Core i7 с тактовой частотой 2,8 ГГц и 16 ГБ оперативной памяти.

введите описание изображения здесь

Ответ 6

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

Ответ 7

Если у вас есть 32-битная шина данных, адресные шины адресной шины, подключенные к памяти, начинаются с A 2, поэтому можно получить доступ только к 32-разрядным выровненным адресам в одном цикле шины.

Итак, если слово охватывает границу выравнивания адреса - то есть A 0 для 16/32 бит данных или 1 для 32-битных данных не равно нулю, два цикла шины необходимы для получения данных.

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

Ответ 8

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

Sparc и I86 и (я думаю) Itatnium поднимают аппаратные исключения при попытке этого.

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