Здається, що ви хочете, щоб оцінити, наскільки пов'язаний ваш 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 додаткових упакованих додавань. Якщо ми припускаємо, що найкращим можливим способом поділу є використання апаратного забезпечення (розумного), ми можемо порахувати vdivpd
36 "флопів", що вказує на те, що ми повинні рахувати кожен скалярний поділ як 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
інструкцію з фрагментом вбудованої вбудованої лінії.