Понимание выравнивания слов
Я понимаю, что означает доступ к памяти так, что она выровнена, но я не понимаю, почему это необходимо. Например, почему я могу получить доступ к одному байту с адреса 0x…1
, но я не могу получить доступ к полуслову (два байта) с того же адреса.
Опять же, я понимаю, что если у вас есть адрес A
и объект размера s
, то доступ выравнивается, если A mod s = 0
. Но я просто не понимаю, почему это важно на аппаратном уровне.
Ответы
Ответ 1
Аппаратное обеспечение сложное; это упрощенное объяснение.
Типичный современный компьютер может иметь 32-битную шину данных. Это означает, что любая выборка, которую должен выполнять процессор, будет извлекать все 32 бита определенного адреса памяти. Поскольку шина данных не может извлекать что-либо меньшую, чем 32 бита, младшие два бита адреса даже не используются на адресной шине, так что, как если бы RAM была организована в последовательность из 32-битных слов вместо 8-битных байтов.
Когда CPU выполняет выборку для одного байта, цикл чтения на шине будет извлекать 32 бита, а затем CPU отбросит 24 этих бита, загружая оставшиеся 8 бит в любой регистр. Если CPU хочет получить 32-битное значение, которое не выровнено по 32-разрядной границе, оно имеет несколько общих вариантов:
- выполнить два отдельных цикла чтения на шине, чтобы загрузить соответствующие части слова данных и собрать их
- прочитайте 32-битное слово по адресу, определяемому путем выброса двух младших битов адреса
- прочитайте некоторую неожиданную комбинацию байтов, собранных в 32-битное слово, возможно, не тот, который вам нужен.
- выполнить исключение
Различные процессоры, с которыми я работал, взяли все четыре из этих путей. В общем, для максимальной совместимости наиболее безопасно выровнять все n-битные чтения с n-разрядной границей. Тем не менее, вы можете, конечно, воспользоваться ярлыками, если вы уверены, что ваше программное обеспечение будет работать в каком-то конкретном семействе процессоров с известным неуправляемым поведением чтения. И даже если возможно одностороннее считывание (например, на процессорах семейства x86), они будут медленнее.
Ответ 2
Компьютер всегда считывает фрагменты фиксированного размера, которые выровнены.
Итак, если вы не выровняете свои данные в памяти, вам, вероятно, придется читать несколько раз.
Пример
- размер слова - 8 байт.
- Ваша структура также составляет 8 байт.
- если вы выровняете его, вам нужно будет прочитать один фрагмент
- Если вы не выровняете его, вам нужно будет прочитать два куска
Итак, это в основном для ускорения.
Ответ 3
Причиной для всех правил выравнивания являются различные ширины линий кэша (в кэше инструкций есть 16 байтовых строк для архитектуры Core2, а в кэше данных есть 64-байтовые строки для строк L1 и 128-байтов для L2).
Итак, если вы хотите хранить/загружать данные, пересекающие границу Cahce-Line, вам нужно загрузить и сохранить обе линии Cache, которая влияет на производительность.
Таким образом, вы просто не делаете этого из-за хита производительности, это так просто.
Ответ 4
Попробуйте прочитать последовательный порт. Данные имеют ширину 8 бит.
Хорошие аппаратные дизайнеры гарантируют, что они лежат на младшем значении байта слова.
Если у вас есть структура C, у которой есть элементы, не выровненные по слову (с обратной совместимости или сохранения памяти)
то адрес любого байта внутри структуры не выравнивается по слову.
Ответ 5
У меня есть основной вопрос (может быть, немой):
Почему эта память не была выровнена на первом месте? Я имею в виду, если вы читаете и записываете данные для данной машины, вы будете следовать ее правилам выравнивания. В 32-битной системе я обязательно буду записывать данные с 32-битным выравниванием.
Это что-то связано с упорядочением сетевых байтов?