OSDev http://osdev.su/ |
|
Выравнивание и кэш http://osdev.su/viewtopic.php?f=5&t=1073 |
Страница 3 из 3 |
Автор: | pavia [ 10 апр 2015, 16:55 ] |
Заголовок сообщения: | Re: Выравнивание и кэш |
dragon писал(а): Цитата: В чем магия числа 8? Почему не 4? 32-битная платформа ведь Магия числа 8 в 64-разрядной шине. 32-битная не платформа а код. 1) Комментарий следующий из грамматики не поясняет смысл сказанного. Какая шина между чем и чем? 2) За один Load загружается регистр XMM, а он 128 битный. И насколько помню там 1 такт на загрузку. И это было до появления 512 битного расширения команд. Так что шина между портом и кэшем всё же шире. 8 байт связанно с тем что 16-байтная шина (128 бит) делится на две части одна часть для загрузки другая для выгрузки. |
Автор: | pavia [ 10 апр 2015, 18:09 ] |
Заголовок сообщения: | Re: Выравнивание и кэш |
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-х кратной потере скорости. В общей числе команд запросов к памяти много и попасть на пересечение границ велико. Но вот сколько реально в цифрах я не видел. Да и с выходом новых процессоров трудно протестировать кэш. |
Автор: | Freeman [ 10 апр 2015, 20:42 ] |
Заголовок сообщения: | Re: Выравнивание и кэш |
pavia писал(а): Если вникать в смысл то он прост. Поля выравниваются так что-бы не пересекать границу в 1,2,4,8 байт. По умолчанию 8. Да, это совпадает с объяснением Himik-а. Правила выравнивания ведь не зависят от языка, а задаются аппаратурой? На ARM свои заморочки. Мой вопрос был не про Delphi, а вообще. Хотелось узнать первопричину появления конкретных цифр в компиляторах. pavia писал(а): SSE - дельфи не поддерживает и выравнивание для 128 бит не нужно. А Extended Delphi практически не использует. Основной тип Real является 8 байтным. Extended в Delphi активно используется библиотечными процедурами, но он передается через регистр сопроцессора, ибо используется соглашение вызова register. А SSE поддерживается встроенным ассемблером Delphi, и появился SSE именно в Delphi 6, если не путаю. Выравнивание на 8 байт также появилось в Delphi 6, в Delphi 5 можно было только на 4. Опять же, если не путаю. После нашего исследования становится ясно, что это не блажь разработчиков компилятора, а нормальное техническое решение, имеющее под собой четкую основу. Стал популярен Pentium 4 -- поменялись и компиляторы. Предполагаю, что в MSVC выравнивание на 8 байт появилось примерно в то же время, вместе с Penitum 4. Пусть кто-нибудь подвердит или опровергнет. pavia писал(а): У Delphi - плохо с оптимизацией и она хранит переменные в памяти, а не в регистрах. Достаточно посмотреть в ассемблерный подстрочник, чтобы увидеть, что это не всегда так. Какие-то оптимизации есть, но их недостаточно, если сравнивать с MSVC, например. Опытным путем я также выяснил, что в class-ах и object-ах Delphi переупорядочивает поля, чтобы добиться наименьшего размера. То есть в памяти поля могут идти не в той последовательности, в какой описаны. Это правильно, поскольку классы и объекты -- высокоуровневые абстракции, в отличие от записей. Это в тему о том, чем отличаются классы от структур с точки зрения разработчика компилятора. А в C++ есть переупорядочивание полей в классах? |
Страница 3 из 3 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |