#memory #memory-alignment
Вопрос:
Давайте предположим, что у нас есть 64-битный процессор, который всегда будет считывать 8 байтов памяти за раз, и я хочу сохранить 4 байта int. Согласно определению естественного выравнивания, 4-байтовый объект выравнивается по адресу, кратному 4 (например, 0x0000, 0x0004). Но вот в чем проблема, почему я не могу сохранить его, например, по адресу 0x0001? Насколько я понимаю, поскольку процессор всегда будет считывать данные размером 8 байт, чтение с адреса 0x0000 все равно может привести к тому, что int будет сохранен в 0x0001 за один раз. Итак, почему в этом случае требуется естественное выравнивание?
Ответ №1:
Современные процессоры (Intel, Arm) с удовольствием будут считывать данные с несогласованных адресов. Процессоры обычно спроектированы так, чтобы считывать гораздо больше, чем 8 байт за цикл: возможно, 16 байт или 32 байта, и глубокие конвейеры процессоров довольно хорошо справляются с извлечением требуемых 8 байт из произвольных адресов без каких-либо видимых штрафов.
Часто, но не всегда, алгоритмы могут быть написаны без особого беспокойства о выравнивании массивов (или начале каждой строки 2-мерного массива).
Конвейерные архитектуры, возможно, считывают выровненные блоки по 16 байт за раз, что означает, что при считывании 8 байтов с адреса 0x0009 процессору фактически необходимо прочитать 2 16-байтовых блока, объединить их и извлечь средние 8 байтов. Все становится еще сложнее, когда память недоступна в кэше первого уровня, а полная строка кэша в 64 байта должна быть извлечена из кэша следующего уровня или из основной памяти.
По моему опыту (написание и оптимизация алгоритмов обработки изображений для SIMD), многие реализации Arm64 почти идеально скрывают стоимость загрузки с несогласованных адресов для алгоритмов с простым и линейным доступом к памяти. Ситуация ухудшается, если алгоритму необходимо интенсивно считывать данные со многих несогласованных адресов, например, при фильтрации с ядром 3×3 или больше или при вычислении БПФ с высоким радиусом, что предполагает, что возможности процессоров по передаче памяти и объединению вскоре будут исчерпаны.
Комментарии:
1. Спасибо за ответ, вы предполагаете, что современные процессоры могут эффективно обрабатывать не выровненные адреса памяти? Кстати, в чем причина того, что какой-то не «современный» 64-битный процессор не может обрабатывать не выровненную память в приведенном выше сценарии?
2. Разработка и внедрение сопряжены с определенными затратами. AFAIK эта функция в основном отсутствует в недорогих/маломощных встроенных процессорах, таких как armv6.