Чи застарілий алгоритмічний аналіз за допомогою флоп-підліку?


43

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

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

Примітка: деякі відповіді нижче, здається, відповідають на інше запитання на кшталт "Чи слід нав'язливо переписати свою реалізацію, щоб зберегти кілька флопів або поліпшити кеш-ефективність?" Але те, про що я запитую, більше відповідає рядкам " Чи корисніше оцінювати алгоритмічну складність з точки зору арифметичних операцій чи доступу до пам'яті ?"


1
> "Чи корисніше оцінювати алгоритмічну складність з точки зору арифметичних операцій або доступу до пам'яті?" . З практичної точки зору, вбудовані системи все ще обмежені швидкістю FPU, а не пропускною здатністю пам'яті. Таким чином, навіть якщо підрахунок флопів був визнаний застарілим за стандартами HPC, він все ще корисний для інших громад.
Демієн

Відповіді:


31

Я думаю, що (перший порядок) правильно зробити, це подивитися на відношення флопів до байтів, необхідне в алгоритмі, який я називаю . Нехай - максимальна швидкість флопу процесора, а максимальна пропускна здатність. Якщо , алгоритм буде обмежений пропускною здатністю. Якщо , алгоритм флопу обмежений.F m a x B m a x F m a xβFmaxBmaxBmaxβ>FmaxFmaxβ>BmaxBmaxβ>Fmax

Я думаю, що підрахунок доступу до пам'яті є обов'язковим, але ми також повинні думати про:

  • Скільки потрібно локальної пам'яті

  • Наскільки можлива паралельність у нас

Тоді можна приступати до аналізу алгоритмів сучасного обладнання.


3
Я погоджуюся з Меттом, але хочу зазначити, що зараз досить часто зустрічається в літературі і визначається як "арифметична інтенсивність" та "числова інтенсивність". Я думаю, що модель Roofline від Williams, Waterman та Patterson , напевно, добре почала замислюватися над цими проблемами. Я думаю, що це слід поширити на відношення часу до пам’яті / флопу доступу алгоритму. β
Арон Ахмадія

2
Девід робив більше 8 років до цього.
Метт Кнеплі

3
Гаразд, тому є краща, більш складна модель (як завжди). Але ця модель дає відповідь, яка залежить від машини. Що ми повинні навчити учнів використовувати в якості першого аналізу?
Девід Кетчесон

3
Справа в тому, що машина була зведена до одиничного числа, відношення пікових флопсів до пікової пропускної здатності, як це має алгоритм. Це так просто, як це виходить. Без обчислювальної моделі будь-яка оцінка складності є марною, і це найпростіша реалістична.
Метт Кнеплі

1
Я думаю, ви неправильно зрозуміли проблему. У нас вже є оптичний транспорт, який може перевозити великі вантажі. Проблема полягає в отриманні цього на мікросхемі. У вас лише стільки проводів і максимальна тактова частота. Оптичний транспорт лише полегшить цю проблему на оптичному чіпі.
Метт Кнеплі

22

Я не бачу, чому треба бути "переможцем"; це не гра з нульовою сумою, де кількість флопів та доступ до пам'яті повинні заглушити інших. Ви можете навчити їх обох, і я думаю, що вони обидва користуються. Зрештою, важко сказати, що ваш алгоритм з доступом до пам'яті обов'язково буде швидшим, ніж ваш алгоритм з доступом . Все залежить від відносних витрат на різні частини (той прискіпливий збірник, який ми завжди ігноруємо в цих аналізах!).O ( N ) O ( N log N ) O ( N 2 )O(N4)O(N)O(NlogN)O(N2)

З більш широкої точки зору, я думаю, що аналіз алгоритмічної продуктивності повинен бути "всеохоплюючим". Якщо ми навчаємо людей бути фактичними розробниками та користувачами HPC, то їм потрібно зрозуміти, які витрати на програмування в реальному світі. Моделі абстрактних аналізів у нас не враховують час програміста. Нам слід думати з точки зору "загального часу на рішення", а не просто зчитування флопу та алгоритмічної ефективності. Мало сенсу витрачати три-чотири дні програміста, щоб переписати процедуру, яка зекономить одну секунду комп’ютерного часу на роботу, якщо ви не плануєте виконувати кілька мільйонів обчислень. Аналогічно, кілька днів вкладення коштів, щоб заощадити годину чи дві обчислювального часу, швидко окупаються. Цей новий алгоритм може бути дивовижним,


7
, алгоритм , який виконує доступ до даних? :)O ( N 2 )O(NlogN)O(N2)
Andreas Klöckner

2
Чому ні? Якщо стосується лише ops з плаваючою точкою, можливо, додатково існує значна кількість цілих ops, які викликають доступ до даних :)O ( N 2 )O(NlogN)O(N2)
kini

9

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

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

Кнут використовує термін gigamems у томі 4A TAOCP при аналізі BDD. Я не впевнений, чи використовує він його в попередніх томах. Він згадав вищезгаданий коментар щодо випробування часом у своїй щорічній лекції про ялинку в 2010 році.

Цікаво, що " You Doing It Wrong" показує, що навіть аналіз продуктивності на основі операцій з пам'яттю не завжди простий, оскільки є такі елементи, як тиск VM, які вступають у дію, якщо дані не вміщуються у фізичну оперативну пам'ять відразу.


8

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

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

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

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

Зрештою, оптимізація кешу корисна лише тоді, коли не залишається нічого для оптимізації паралелізмом та зменшенням асимптотичного числа FLOP.

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


"оптимізація кешу корисна лише в тому випадку, якщо не залишається нічого для оптимізації паралелізмом і зменшенням асимптотичного числа FLOP". Я не погоджуюсь. Якщо ви хочете обчислити велике вираження великого згустку чисел, краще виконувати один крок за часом з усіма числами, ніж усі кроки для кожного числа. Обидва мають однакову кількість FLOPS, але один краще в доступі до пам'яті. Бонус, якщо ви вибрали розмір згустку, який підходить до кешу (або компілятор робить це за вас). Ось що робить numexpr в Python: github.com/pydata/numexpr
Davidmh

6

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

Тепер ви можете оптимізувати це до пекла і заощадити кілька флопів, заробляючи 10% часу роботи. Або ви можете подумати про реалізацію мультисерединного методу та оптимального блокового попереднього кондиціонера, отримавши коефіцієнт 10 у пробігу. Це те, що ми повинні навчити наших учнів робити - подумати над тим, які складні, зовнішні алгоритми можуть перемогти вас, намагаючись знайти кращий внутрішній алгоритм. Ваш начальник (Кіз) має ці слайди щодо прогресу в обчисленнях MHD, що робить це дуже очевидним.


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

Я б не знав, як підрахувати вручну FLOPS або будь-яку іншу кількість інструкцій для складних алгоритмів, що працюють на десятки чи тисячі рядків коду. Подумайте, наприклад, наскільки складна фаза аналізу та побудови алгоритмів AMG. Існує так багато частин цих алгоритмів, і всі вони залежать від фактичних даних, що ви не можете передбачити кількість операцій.
Вольфганг Бангерт

1
Я думаю, що я спочатку неправильно зрозумів, до чого ви стикаєтесь, але я все ще не згоден з вашою думкою. "Зовнішні алгоритми" можуть (і я б заперечував, повинні) все-таки розроблятися з урахуванням асимптотичної складності. Безумовно, ви б не стверджували, що перехід від квадратичного алгоритму до майже лінійного алгоритму в кращому випадку призведе до скорочення часу виконання на 10%; все ж, як інакше кількісно оцінити асимптотичну складність, ніж через флопи та / або оперативні пам'яті?
Джек Поульсон

7
Я думаю, що цей підхід до "алгоритмів руки" до алгоритмів - це лайно. Аналіз потрібно спростити, лише дивлячись на витрати першого порядку та спрощуючи модель так, щоб вона була простежуваною, але сказати, що ви не можете проаналізувати щось на кшталт MG або Cholesky, оскільки це занадто складно, абсолютно невірно.
Метт Кнеплі

1
Що ж, але що означає аналізувати MG або Cholesky, коли кожен розрахований вами FLOP прихований за кількома шарами затримки, викликаними гіперточеними процесорами, кешами, повільною ОЗУ, багатоскалярними процесорами та автоматичною векторизацією? Я хочу зазначити, що в межах коефіцієнта 5-10 ви більше не можете передбачити час роботи своїх алгоритмів, не призначаючи його. Це було зовсім інакше в 50-ті та 60-ті роки, коли люди починали цей ФЛОП підрахунок.
Вольфганг Бангерт

1

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

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


-1

Насправді не відповідаючи на ваше запитання, але більше додайте ще одну змінну, яку слід врахувати: потрібно враховувати особливості мови програмування. Наприклад, Python sortвикористовує алгоритм Timsort , який розроблений (серед інших приємних властивостей) для мінімізації кількості порівнянь, що може бути повільно для об’єктів Python. З іншого боку, порівняння двох плавців у C ++ палає швидко, але заміна їх дорожча, тому вони використовують інші алгоритми.

Іншими прикладами є динамічне розподілення пам’яті (тривіальне в списку Python, швидке і в час виконання, і в розробники, просто .append()), порівняно з FORTRAN або C, де, хоча це можливо і швидше при правильній реалізації, потрібно значно більше часу програмування та мозку. Побачити Python швидше, ніж FORTRAN.


Це правда, але, як ви кажете, не відповідає на запитання. Це на іншу тему.
Девід Кетчесон

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