Що важливо під час оптимізації кешу CPU (в C)?


13

Читаючи ці два запитання , я бачу, що розуміння поведінки кешування процесора може бути важливим при роботі з великою кількістю даних в пам'яті. Я хотів би зрозуміти, як працює кешування, щоб додати ще один інструмент до моєї панелі інструментів оптимізації.

Які основні моменти в тому, як працює кеш процесора, щоб я міг написати код, який його розумно використовує? Так само, чи існує спосіб кодування профілю, щоб дізнатися, чи погане використання кешу сповільнює ситуацію?


Схованки скрізь не однакові; найбільш очевидно, вони різняться за розмірами. Не сподівайтесь дізнатися якісь глибокі таємниці, лише добрі практики (наприклад, поради Майкла Боргвардта).
Девід Торнлі

Відповіді:


17
  • Зберігайте ваші дані, якщо це можливо
  • Зберігайте в пам’яті речі, до яких можна отримати доступ разом (або відразу після іншого)
  • Дізнайтеся про параметри оптимізації вашого компілятора
  • Прочитайте, що кожен програміст повинен знати про пам’ять для більш детальної інформації, ніж ви могли хотіти

+1 для "Зберігайте речі, до яких можна отримати доступ один до одного"; це той, який легко забути.
стипендіати

І скажіть компілятору оптимізувати.
праворуч

@WTP: праворуч - додано.
Майкл Боргвардт

Крім того, тримати мутекси добре розділеними. Змінивши мутекс (слід) промийте всі рядки кешу, у яких він є, у всіх процесорах. Це може бути великим хітом для продуктивності, якщо вам вдалося отримати 2-3 мутекси в одному рядку кешу.
Ватін

12

Складність цього питання в наші дні перевершила людське розуміння. (Це так з останніх 5 років.) Поєднайте це з коротковекторним паралелізмом (SIMD), і ви відчуваєте безперспективність, що оптимізація коду вручну вже не є економічно доцільною - це не можливо, але це було б більше не бути рентабельним.

Сучасний підхід полягає в тому, щоб покластися на навчання комп'ютерів оптимізації - шляхом створення варіацій коду, які обчислюють однакові відповіді з різними структурами (циклі, структура даних, алгоритми) та автоматично оцінюють продуктивність. Правила перетворень коду задаються дуже суворою математичною моделлю, так що це те, що і комп'ютерні фахівці можуть зрозуміти, і комп'ютери можуть виконати.

Далі йде посилання, розміщене Ларрі OBrien в одній зі своїх відповідей .

http://onward-conference.org/2011/images/Pueschel_2011_AutomaticPerformanceProgramming_Onward11.pdf


2
найшвидша реалізація BLAS (GotoBLAS) використовує оптимізований вручну код для забезпечення максимального використання кешу для множення матриці
Quant_dev

2

Це цілком можливо зрозуміти та оптимізувати для кешів. Він починається з розуміння обладнання та продовжує контролювати систему. Чим менше контролю над системою, тим менше шансів на успіх. Linux або Windows, де працює безліч додатків / потоків, які не працюють.

Більшість кеш-книг за своїми властивостями дещо схожі, використовуйте деяку частину адресного поля, щоб шукати звернення, мати глибину (способи) та ширину (лінія кешу). Деякі мають буфери для запису, деякі можуть бути налаштовані для запису через або обходу кеша запису тощо.

Потрібно чітко усвідомлювати всі операції з пам'яттю, які відбуваються в кеш-пам'ять (деякі системи мають незалежну кеш-інструкцію та кеш даних, що полегшує завдання).

Ви можете легко зробити кеш марним, не ретельно керуючи своєю пам'яттю. Наприклад, якщо у вас є декілька блоків даних, які ви обробляєте, сподіваючись зберегти їх у кеші, але вони знаходяться в пам’яті за адресами, які навіть кратні відносно перевірки кешу / пропуску, скажімо, 0x10000 0x20000 0x30000, і у вас є більше окрім шляхів у кеш-пам'яті, ви можете дуже швидко зробити щось, що працює доволі повільно, якщо кеш увімкнено, повільніше, ніж із кешем. Але змініть це, можливо, на 0x10000, 0x21000, 0x32000, і цього може бути достатньо, щоб повністю використати кеш, зменшивши виселення.

Підсумок, ключове значення для оптимізації кешу (ну, крім того, що добре знати систему) полягає в тому, щоб одночасно зберігати всі необхідні для керування речі, організуючи ці дані такими, щоб їх можна було мати все це відразу в кеші. І запобігання тим, як виконання коду, переривання та інші регулярні або випадкові події не вилучати значні частини цих даних, які ви використовуєте.

Те саме стосується коду. Це трохи складніше, хоча вам потрібно контролювати місця, де знаходиться код, щоб уникнути зіткнень з іншим кодом, який ви хочете зберегти в кеші. Під час тестування / профілювання будь-якого коду, який проходить через кеш, що додає туди-сюди єдиний рядок коду або навіть єдиний nop, все, що зміщує або змінює адреси, де код живе з однієї компіляції в іншу, на той самий код, змінюється де рядки кеша підпадають під цей код і змінюють те, що вилучається, а що не - для критичних розділів.


1

Обидва nwong - х і Майкл Borgwardt в відповідь дати добру пораду.

Також спочатку довіртесь оптимізації компілятора з цих питань.

Якщо ви використовуєте останній компілятор GCC, ви можете використовувати (з прихильністю) його __builtin_prefetchфункції. Дивіться цю відповідь на stackoverflow.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.