Підрахунок FLOP для функцій бібліотеки


13

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

Під спеціальними функціями ми маємо на увазі такі речі, як:

  • exp ()
  • sqrt ()
  • sin / cos / tan ()

які зазвичай надаються системними бібліотеками.

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

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

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


Петро, ​​просто швидкий коментар. Хоча ви надаєте кілька хороших прикладів функцій, які надаються математичними бібліотеками, поділи з плаваючою комою зазвичай реалізуються блоком з плаваючою комою.
Арон Ахмадія

Спасибі! Я був недостатньо зрозумілий. Я щойно відредагував, щоб забезпечити кращий контраст.
Пітер Брун

Я був здивований, виявивши, що sin, cos і sqrt фактично реалізовані і в підмножині x87 з плаваючою комою з інструкцій x86. Я думаю, я розумію, але я вважаю, що прийнята практика полягає лише в тому, щоб трактувати це як операції з плаваючою комою з дещо більшими константами :)
Арон Ахмадія

@AronAhmadia Не було причин використовувати x87 протягом більше десяти років. Розділіться і sqrt()знаходяться в SSE / AVX, але це займає набагато більше часу, ніж додавання та множення. Крім того, вони погано векторизовані на Sandy Bridge AVX, займаючи вдвічі довше, ніж інструкція SSE (з половиною ширини). Наприклад, AVX з подвоєною точністю (4 парні ширини) може робити багаторазове множення та упаковка додавати кожен цикл (за умови, що в пам'яті немає залежностей та зупинок), що становить 8 флопів за цикл. Ділення займає від 20 до 44 циклів, щоб зробити ці "4 флопи".
Джед Браун

sqrt () необов’язковий для PowerPC. Багато вбудованих мікросхем цієї архітектури не реалізують інструкцію, наприклад, Freescale MPC5xxx серії.
Демієн

Відповіді:


10

Здається, що ви хочете, щоб оцінити, наскільки пов'язаний ваш FPU код, або наскільки ефективно ви використовуєте FPU, а не підраховувати кількість флопів згідно з тим же анахронічним визначенням "flop". Іншими словами, ви хочете, щоб показник, який досягає того ж піку, якщо кожна одиниця з плаваючою точкою працює на повну потужність кожного циклу. Давайте подивимось на Intel Sandy Bridge, щоб побачити, як це може похитнутись.

Апаратні операції з плаваючою комою

Цей чіп підтримує інструкції AVX , тому регістри мають довжину 32 байти (вміщує 4 подвійні). Надскалярна архітектура дозволяє інструкціям перетинатися, а більшість арифметичних інструкцій займають кілька циклів, хоча нова інструкція може бути спроможна запустити наступний цикл. Ці семантики зазвичай скорочуються, записуючи затримку / зворотну пропускну здатність, значення 5/2 означатиме, що інструкція потребує 5 циклів для завершення, але ви можете починати нову інструкцію через інший цикл (за умови, що операнди доступні, тому даних немає залежність і не чекання пам’яті).

Існує три арифметичні одиниці з плаваючою точкою на одне ядро, але третя не стосується нашого обговорення, ми назвемо відповідні два одиниці A і M, оскільки їх основними функціями є додавання та множення. Приклад інструкцій (див. Таблиці Agner Fog )

  • vaddpd: упакована добавка, що займає блок А на 1 цикл, затримка / зворотна пропускна здатність становить 3/1
  • vmulpd: пачне множення, одиниця М, 5/1
  • vmaxpd: упаковано, виберіть попарно максимум, одиниця A, 3/1
  • vdivpd: упакований поділ, одиниця M (і деякі А), 21/20 до 45/44, залежно від введення
  • vsqrtpd: упакований квадратний корінь, деякі A і M, 21/21 до 43/43, залежно від введення
  • vrsqrtps: упакований реципрочний квадратний корінь низької точності для одноточного введення (8 floats)

Точна семантика того, що може перетинатися vdivpdі vsqrtpd, мабуть, є тонким, і AFAIK, ніде не зафіксовано. Я вважаю, що в більшості застосувань мало можливостей для перекриття, хоча формулювання в посібнику передбачає, що кілька потоків можуть запропонувати більше можливостей для накладання в цій інструкції. Ми можемо вражати пікові флопи, якщо запустити a vaddpdі vmulpdна кожному циклі, загалом 8 флопів за цикл. Шматна матриця-множина матриці ( dgemm) може бути досить близькою до цього піку.

Підраховуючи флопи за спеціальними інструкціями, я би дивився на те, яка частина FPU зайнята. Припустимо, аргумент про те, що у вашому діапазоні введення vdivpdв середньому було потрібно 24 цикли, щоб повністю зайняти одиницю M, але додавання може (якщо воно було доступне) виконуватись одночасно протягом половини циклів. FPU здатний виконувати 24 упакованих множення та 24 упакованих доповнення протягом цих циклів (ідеально переплетених vaddpdі vmulpd), але з a vdivpd, найкраще, що ми можемо зробити, це 12 додаткових упакованих додавань. Якщо ми припускаємо, що найкращим можливим способом поділу є використання апаратного забезпечення (розумного), ми можемо порахувати vdivpd36 "флопів", що вказує на те, що ми повинні рахувати кожен скалярний поділ як 36 "флопів".

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

y *= (3 - x*y*y)*0.5;

Якщо багато з цих операцій потрібно виконати, це може бути значно швидше, ніж наївна оцінка y = 1/sqrt(x). Перед наявністю апаратного орієнтовного прямого квадратного кореня деякі чутливі до продуктивності коди використовували сумнозвісні цілочисельні операції, щоб знайти початкову здогадку про ітерацію Ньютона.

Математичні функції, надані бібліотекою

Ми можемо застосувати аналогічну евристику до математичних функцій, передбачених бібліотекою. Ви можете профілювати, щоб визначити кількість інструкцій SSE, але, як ми вже обговорювали, це не вся історія, і програма, яка витрачає весь свій час на оцінку спеціальних функцій, може не наблизитися до піку, що може бути правдою, але хіба що Не корисно сказати вам, що весь час ви витрачаєте поза вашим контролем у ФПУ.

Я пропоную використовувати хорошу векторну математичну бібліотеку як базову лінію (наприклад, VML Intel, частина MKL). Виміряйте кількість циклів для кожного виклику і помножте на максимально досяжні флопи на цю кількість циклів. Отже, якщо упакований експонент вимагає 50 циклів для оцінки, порахуйте його як 100 флопів, більших за ширину регістра. На жаль, декоративно-математичні бібліотеки іноді важко викликати і не мають усіх спеціальних функцій, тому ви можете в кінцевому підсумку робити скалярну математику, і в цьому випадку ви вважаєте наш гіпотетичний скалярний показник 100 флопами (хоча, мабуть, це все ще займає 50 циклів, тож ви отримаєте лише 25% «піку», якщо весь час витратите на оцінку цих експоненцій).

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


7

Ви можете порахувати їх на реальних системах за допомогою PAPI , який надає доступ до апаратних лічильників та простих тестових програм. Мій улюблений інтерфейс / обгортка PAPI - це IPM (інтегрований монітор продуктивності), але існують інші рішення (наприклад, TAU ). Це повинно дати досить стійке порівняння метод-метод.


4

Я відповім на це запитання так, ніби ви запитали:

"Як я аналітично порівнюю чи передбачую ефективність алгоритмів, які значною мірою покладаються на спеціальні функції, замість традиційних лічильників FLOP на множення і додавання-перенесення, що походять з числової лінійної алгебри"

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

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

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

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

  3. Сліди пам’яті - Це сильно пов'язане з попередніми пунктами, але в міру збільшення комп'ютерів все більше і більше, об'єм пам'яті на одне ядро ​​насправді рухається вниз. Малому сліду пам’яті є дві переваги. Перший полягає в тому, що невелика кількість програмних даних, ймовірно, зможе повністю вміститися в кеш процесора. Друга полягає в тому, що при дуже великих проблемах алгоритм з меншим розміром пам’яті може бути в змозі вписатись у пам'ять процесора, що дозволяє вирішити проблеми, які в іншому випадку перевищуватимуть можливості комп'ютера.


Я б стверджував, що знання FLOPS / сек дозволяє вам відокремити режим вузького вузького місця (пам'ять, спілкування). Наприклад, розглянемо методи Ньютона-Крилова, які проводять багато часу, роблячи матвеки. Matvecs роблять FLOP або два на матричний запис, і все. Нерозбірні плавніші мають потенціал зробити краще. Ми з Джедом говорили і про це, і альтернативне поняття полягає в тому, щоб побачити, скільки циклів ви витрачаєте на обчислення, пов'язані з FLOP. Однак це може зажадати досить тонкого моніторингу, і загальний FLOPS / сек може бути більш практичним.
Пітер Брун

Арон, більша частина цієї відповіді, здається, обходить питання Петра на користь відповіді на це інше питання: scicomp.stackexchange.com/questions/114
Джед Браун

@JedBrown, я згоден, дякую за те, що ви знайшли час, щоб зібрати набагато більш солідну відповідь.
Арон Ахмадія

0

Навіщо турбувати підрахунок флопів? Просто порахуйте цикли для кожної операції, і ви отримаєте щось універсальне.

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