Цель выравнивания памяти - PullRequest
       48

Цель выравнивания памяти

167 голосов
/ 19 декабря 2008

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

Ответы [ 8 ]

268 голосов
/ 19 декабря 2008

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

Скорость

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

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

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

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 LSB всегда равны 0 (например, 32-разрядные машины), тогда она может получить доступ в 4 раза больше памяти (2 сохраненных бита могут представлять 4 различных состояния), или тот же объем памяти с 2 битами для чего-то вроде флагов. Удаление 2 младших битов из адреса даст вам 4-байтовое выравнивание; также называется шагом из 4 байтов. Каждый раз, когда адрес увеличивается, он эффективно увеличивает бит 2, а не бит 0, то есть последние 2 бита всегда будут оставаться равными 00.

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

Атомарность

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

Заключение

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

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

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

Бонус: кэши

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

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

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

54 голосов
/ 19 декабря 2008

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

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

20 голосов
/ 19 декабря 2008

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

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

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

3 голосов
/ 06 апреля 2016

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

enter image description here

3 голосов
/ 01 марта 2011

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

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

Итак:

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

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

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

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

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

2 голосов
/ 16 июня 2011

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

1 голос
/ 20 июня 2014

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

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

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

0 голосов
/ 19 декабря 2008

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

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

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

...