Вопрос

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

Это было полезно?

Решение

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

Там гораздо больше информации эта ссылка что ОП обнаружил.

Другие советы

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

Скорость

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

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

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

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

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

атомарность

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

Заключение

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

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

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

Бонус:Тайники

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

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

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

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

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

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

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

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

Так:

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

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

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

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

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

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

enter image description here

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top