Чому бажана ефективність роботи в програмуванні GPU?


13

Я читав наступну статтю про те, як зробити паралельне сканування в CUDA:

https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch39.html

У статті зроблено акцент на тому, щоб сканування "працювало ефективно". Іншими словами, алгоритм GPU повинен виконувати не більше доповнень, ніж алгоритм CPU, O (n). Автори представляють два алгоритми, один "наївний", який робить доповнення O (nlogn), і той, який вони вважають "ефективною". Однак алгоритм ефективної роботи робить вдвічі більше ітерацій циклу.

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

Відповіді:


21

Перш за все, повторно: "GPU - це просто гігантські процесори SIMD і повинні працювати в режимі блокування", це трохи складніше, ніж це. Весь GPU не працює синхронно. Шейдерні потоки організовані в групи з 32 під назвою "warps" (на NVIDIA; на AMD - це групи з 64, що називаються "хвилевими фронтами", але таке ж поняття). У рамках основи всі потоки запускаються в стоп-коду як масив SIMD. Однак різні основи не знаходяться між собою. Крім того, деякі деформації можуть активно працювати, тоді як інші можуть бути призупинені, як і потоки процесора. Основи можна призупинити або тому, що вони чогось чекають (наприклад, повернення транзакцій пам'яті або перешкоди для очищення), або тому, що немає "

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

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

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

    Розглянемо кількість активних ниток у наївному алгоритмі. Дивлячись на малюнок 2 у статті, ви бачите, що всі потоки активні, за винятком перших 2 k на k- й ітерації. Отже, з N потоків кількість активних потоків іде як N - 2 k . Наприклад, при N = 1024 кількість активних потоків за ітерацію становить:

    1023, 1022, 1020, 1016, 1008, 992, 960, 896, 768, 512
    

    Якщо я перетворять це на кількість активних деформацій (діленням на 32 та округленням), я отримую:

    32, 32, 32, 32, 32, 31, 30, 28, 24, 16
    

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

     512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512
    

    Перетворення цього типу на активні основи:

    16, 8, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 8, 16
    

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

Враховуючи це, прикро, що стаття про GPU Gems чітко не пояснює нічого з цього, натомість зосереджується на аналізі "кількості доповнень" big-O, який, хоча і не зовсім несуттєво, пропускає багато деталей про те, чому цей алгоритм є швидше.

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