Подтвердить что ты не робот

Почему валидация производительности структуры данных важна для производительности?

Может ли кто-нибудь дать мне короткое и правдоподобное объяснение того, почему компилятор добавляет дополнение к структурам данных, чтобы выровнять его элементы? Я знаю, что это сделано для того, чтобы процессор мог получить доступ к данным более эффективно, но я не понимаю, почему это так.

И если это только связано с процессором, почему двойной байт выровнен в Linux и 8 байт выровнены в Windows?

4b9b3361

Ответ 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, в некоторых архитектурах есть инструкции по загрузке и хранению (те, которые используются для чтения/записи в память и из памяти), которые только работают на границах, выровненных по слову, выровненное слово из памяти будет принимать две инструкции загрузки, инструкцию сдвига, а затем команду маски - гораздо менее эффективно!