Почему валидация производительности структуры данных важна для производительности?
Может ли кто-нибудь дать мне короткое и правдоподобное объяснение того, почему компилятор добавляет дополнение к структурам данных, чтобы выровнять его элементы? Я знаю, что это сделано для того, чтобы процессор мог получить доступ к данным более эффективно, но я не понимаю, почему это так.
И если это только связано с процессором, почему двойной байт выровнен в Linux и 8 байт выровнены в Windows?
Ответы
Ответ 1
Выравнивание помогает процессору эффективно извлекать данные из памяти: меньше промахов/флешей, меньше транзакций шины и т.д.
Некоторые типы памяти (например, RDRAM, DRAM и т.д.) должны быть доступны структурированным образом (согласованные "слова" и "пакетные транзакции", то есть много слов за один раз), чтобы обеспечить эффективные результаты. Это связано со многими вещами, среди которых:
- время установки: время, необходимое памяти для доступа к ячейкам памяти.
- накладные расходы на арбитраж шины, то есть многим устройствам может потребоваться доступ к устройству памяти.
"Заполнение" используется для корректировки выравнивания структур данных для оптимизации эффективности передачи.
Другими словами, доступ к структуре с неправильным выравниванием приведет к снижению общей производительности. Хороший пример такой ловушки: предположим, что структура данных неверно выровнена и требует, чтобы процессор/контроллер памяти выполнял 2 транзакции шины (вместо 1) для извлечения указанной структуры, поэтому производительность, следовательно, ниже.
Ответ 2
CPU извлекает данные из памяти в группах по 4 байта (это зависит от аппаратного обеспечения 8 или других значений для некоторых типов аппаратного обеспечения, но позволяет придерживаться 4, чтобы упростить его)
все хорошо, если данные начинаются с адреса, который делится на 4, CPU переходит на адрес памяти и загружает данные.
теперь предположим, что данные начинаются в адресе, не делящемся на 4, скажем, для простоты по адресу 1, ЦП должен принимать данные с адреса 0, а затем применять некоторый алгоритм для сброса байта по адресу 0, чтобы получить доступ к фактическим данным в байте 1. Это требует времени и, следовательно, снижает производительность. поэтому гораздо эффективнее согласовать все адреса данных.
Ответ 3
Линия кэша является базовой единицей кэширования. Обычно это 16-64 байта или более.
Pentium IV: 64 байта; Pentium Pro/II: 32 байта; Pentium I: 32 байта; 486: 16 байт.
myrandomreader:
; ...
; ten instructions to generate next pseudo-random
; address in ESI from previous address
; ...
MOV EAX, DS:[ESI] ; X
LOOP myrandomreader
Для чтения в памяти, разделяющего две строки кегли:
(для пропусков кеша L1) процессор должен дождаться, пока вся строка кэша 1 будет считана из L2- > L1 в процессор, прежде чем он сможет запросить вторую строку кэша, что приведет к короткому времени выполнения
(для пропусков кэша L2) процессор должен дождаться двух всплывающих прошивок из кеша L3 (если имеется) или основной памяти для завершения, а не для одного
Процессорные стойки
-
Случайное 4-байтовое чтение будет охватывать границу кешетина примерно в 5% времени для 64-байтных кешин, 10% для 32 байтовых и 20% для 16-байтных.
-
Для некоторых инструкций по неверным данным могут быть дополнительные накладные расходы, даже если они находятся в пределах кэша. Об этом говорится на веб-сайте Intel для некоторых инструкций SSE.
-
Если вы сами определяете структуры, может иметь смысл взглянуть на список всех полей данных < 32bit вместе в struct
, так что дополнительные накладные расходы будут уменьшены или, в качестве альтернативы, рассмотреть вопрос о том, упаковка вкл или выкл для конкретной структуры.
-
В MIPS и многих других платформах вы не получите выбор и должны выровнять - исключение ядра, если вы этого не сделаете!!
-
Выравнивание может также иметь особое значение для вас, если вы выполняете ввод-вывод на шине или используете атомные операции, такие как атомный приращение/уменьшение или если вы хотите перенести свой код на не-Intel.
-
В коде Intel только (!) распространена практика определения одного набора упакованных структур для сети и диска и другого набора для внутренней памяти и для подпрограмм для преобразования данных между этими форматами (также рассмотрите "endianness" для дисков и сетевых форматов).
Ответ 4
В дополнение к ответу jldupont, в некоторых архитектурах есть инструкции по загрузке и хранению (те, которые используются для чтения/записи в память и из памяти), которые только работают на границах, выровненных по слову, выровненное слово из памяти будет принимать две инструкции загрузки, инструкцию сдвига, а затем команду маски - гораздо менее эффективно!