Freeman писал(а):
pavia писал(а):
Думаю что выравнивание в структурах данных нужно только для store to load forwarding.
А в каких процессорах оно появилось? В интернетах видел ссылки на Intel Core. А ведь Delphi 6 выпущен 12 лет назад, когда был только Pentium 4.
Появилось в Pentium 4.
Прочитал более старый мануал. Теперь я могу ответить почти полностью на ваш вопрос.
Но первое хочу сказать что.
1) Директива {$Align} хотя и равнозначна {$A8} но выравнивание у компилятора Delphi 6 хитрое.
Вот описание от Delphi очень плохое.
Цитата:
The $A directive controls alignment of fields in Delphi record types and class structures.
In the {$A1} or {$A-} state, fields are never aligned. All record and class structures are packed.
In the {$A2} state, fields in record types that are declared without the packed modifier and fields in class structures are aligned on word boundaries.
In the {$A4} state, fields in record types that are declared without the packed modifier and fields in class structures are aligned on double-word boundaries.
In the {$A8} or {$A+} state, fields in record types that are declared without the packed modifier and fields in class structures are aligned on quad word boundaries.
Что там написано. Если вникать в смысл то он прост. Поля выравниваются так что-бы не пересекать границу в 1,2,4,8 байт. По умолчанию 8.
Это
не значит что в структуре между a и b будет 7 байт.
Код:
record
a,b:Byte;
end;
Тут байты будут идти вместе! Это так, потому что байт физически не может пересечь границу.
Чтобы было понятен алгоритм выравнивания привожу совет от интела по выравниванию.
Цитата:
Assembly/Compiler Coding Rule 45. (H impact, H generality) Align data on
natural operand size address boundaries. If the data will be accessed with vector
instruction loads and stores, align the data on 16-byte boundaries.
For best performance, align data as follows:
• Align 8-bit data at any address.
• Align 16-bit data to be contained within an aligned 4-byte word.
• Align 32-bit data so that its base address is a multiple of four.
• Align 64-bit data so that its base address is a multiple of eight.
• Align 80-bit data so that its base address is a multiple of sixteen.
• Align 128-bit data so that its base address is a multiple of sixteen.
Теперь понятно что {$A8} задаёт максимальный множитель равный 8! Отсюда очевидно, что пропусков в сложной структуре будет мало.
Почему Delphi выбрала 8 а не 4 или не 16? Есть три причины.
а) Большое выравнивание больше пропусков и данные будут хуже попадать в кэш второго уровня. Хотя если их переупорядычить, то пропусков почти небудет. И тогда лучше выбрать границу 16. Только Delphi это не поддерживает, а зря.
б) Типы которые поддерживает Delphi: byte, word, integer, single, real(double), Extended.
SSE - дельфи не поддерживает и выравнивание для 128 бит не нужно. А Extended Delphi практически не использует. Основной тип Real является 8 байтным.
Тем более вот что пишет интел в ещё более сатром мануэле.
Цитата:
3.5.1.6 ALIGNING DATA IN MEMORY AND ON THE STACK
Accessing 64-bit variables that are not 8-byte aligned costs an extra three cycles on the
Pentium processor. When such a variable crosses a 32-byte cache line boundary it can cause
a DCU split in Pentium Pro and Pentium II processors. Some commercial compilers do not
align doubles on 8-byte boundaries. If, by using the Misaligned Accesses performance
counter, you discover your data is not aligned, the following methods may be used to align
your data:
· Use static variables.
· Use assembly code that explicitly aligns data.
· In C code, use malloc to explicitly allocate variables.
в) Третья причина это как я уже писал store to load forwarding(передача от выгрузке к загрузке). У Delphi - плохо с оптимизацией и она хранит переменные в памяти, а не в регистрах. Поэтому для Delphi это существенно. Тем более как заверяет интел эта оптимизация даёт до 4 кратного прироста.
Почему плохо пересекать границу? Дело в том что если какое либо число окажется на границе то по сути это вызовет дополнительный запрос к кэшу. А это ещё +3 такта (в лучшем случае). Так на выставление адреса так на проверку попадания в кэш и такт на чтение. Что по сути приводит в данном случае к 2-х кратной потере скорости. В общей числе команд запросов к памяти много и попасть на пересечение границ велико. Но вот сколько реально в цифрах я не видел. Да и с выходом новых процессоров трудно протестировать кэш.