Допомога gpu. Задіємо можливості GPU для прискорення софту

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

Яка програма потрібна для майнінгу криптовалюти? Що враховувати при виборі обладнання для майнінгу? Як майнути біткоїни та ефіріум за допомогою відеокарти на комп'ютері?

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

З вами Денис Кудерін – експерт журналу «ХітерБобер» з питань фінансів та їхнього грамотного множення. Я розповім, що собою представляє майнінг на відеокартіу 17-18 роках, як правильно вибрати пристрій для заробітку криптовалюти, і чому видобувати біткоїни на відеокартах вже не вигідно.

Ви дізнаєтеся також, де купити саму продуктивну та потужну відеокартудля професійного майнінгу, та отримайте експертні поради щодо підвищення ефективності своєї майнінг-ферми.

1. Майнінг на відеокарті – легкі гроші чи невиправдані витрати

Хороша відеокарта – не просто адаптер цифрових сигналів, але і потужний процесор, здатний вирішувати найскладніші обчислювальні завдання І в тому числі – обчислювати хеш-код для ланцюжка блоків (блокчейна). Це робить графічні плати ідеальним інструментом для майнінгу- Видобування криптовалюти.

Запитання:Чому саме процесор відеокарти? Адже у будь-якому комп'ютері є центральний процесор? Хіба не логічно проводити обчислення за його допомогою?

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

Для тих, хто не має уявлення про те, як добуваються цифрові гроші, невеликий лікнеп. Майнінг - основний, а іноді й єдиний спосіб виробництва криптовалюти.

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

Крім обчислень коду, майнінг виконує ще кілька найважливіших завдань:

  • підтримка децентралізації системи:відсутність прихильності до серверів - основа блокчейна;
  • підтвердження транзакцій– без майнінгу операції не зможуть увійти до нового блоку;
  • формування нових блоків системи– і занесення їх у єдиний всім комп'ютерів реєстр.

Відразу хочу охолодити запал початківців: процес майнінгу з кожним роком стає все важче. Наприклад, за допомогою відеокарти вже давно нерентабельний.

Битки за допомогою GPU добувають зараз лише уперті любителі, оскільки на зміну відеокартам прийшли спеціалізовані процесори ASIC. Ці чіпи споживають менше електроенергії і більш ефективні щодо обчислень. Всім хороші, але стоять порядку 130-150 тисяч рублів .

Потужна модель Antminer S9

На щастя для майнерів, біткоін – не єдина на планеті криптовалюта, а одна із сотень. Інші цифрові гроші – ефіріуми, Zcash, Expanse, догкоїниі т.д. як і раніше, вигідно видобувати за допомогою відеокарт. Винагорода стабільна, а обладнання окупається приблизно через 6-12 місяців.

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

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

На Авіті навіть продають цілі ферми для видобутку криптовалюти.

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

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

Інша річ, що гравців на цьому полі стає дедалі більше. Причому сумарна кількість цифрових монет від цього не зростає. Навпаки, нагорода стає меншою.

Так, шість років тому нагорода за один блокчейн мережі біткоїн дорівнювала 50 монет, зараз це лише 12,5 БТК. Складність обчислень при цьому збільшилась у 10 тисяч разів. Щоправда, і вартість самого біткоїну зросла за цей час багаторазово.

2. Як майнути криптовалюту за допомогою відеокарти – покрокова інструкція

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

99% всіх майнерів працює у пулах(англ. pool – басейн) – спільнотах, зайнятих розподілом обчислювальних завдань. Спільний майнінг нівелює фактор випадковості та гарантує стабільний прибуток.

Один мій знайомий майнер висловився так із цього приводу: я займаюся майнінгом вже 3 роки, за цей час не спілкувався ні з ким, хто б видобував сам.

Такі старателі схожі на золотошукачів 19 століття. Можна шукати роками свій самородок (у нашому випадку – біткоїн) і так і не знайти. Тобто блокчейн так і не буде закритий, а отже, жодної нагороди ви не отримаєте.

Трохи більше шансів у «самотніх мисливців» за ефірами та деякими іншими крипто-монетами.

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

Однією відеокарти для створення повноцінної ферми буде недостатньо: 4 штуки – «прожитковий мінімум» для майнера, що розраховує на стабільний прибуток. Не менш важлива потужна системаохолодження відеоадаптерів. І не упускайте з уваги і таку статтю витрат, як плата за електроенергію.

Покрокова інструкція убезпечить від помилок та прискорить налаштування процесу.

Крок 1. Вибираємо пул

Найбільші у світі криптовалютні пули дислокуються на території КНР, а також в Ісландії та США. Формально ці спільноти не мають державної власності, але російськомовні сайти пулів – рідкість в інтернеті.

Оскільки видобувати на відеокарті вам доведеться швидше за все ефіріум, то й обирати потрібно буде співтовариство, зайняте обчисленням цієї валюти. Хоча Etherium – відносно молодий альткоїн, пулів для його майнінгу існує безліч. Від вибору спільноти багато в чому залежить розмір вашого доходу та його стабільність.

Вибираємо пул за такими критеріями:

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

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

Так, нещодавно стало відомо, що ефір у найближчому майбутньому переходить на іншу систему розподілу прибутку. У двох словах – дохід у мережі Etherium матимуть майнери, у яких є «багато кеце», тобто монет, а добувачам-початківцям залишиться або прикрити лавочку, або переключитися на інші гроші.

Але такі «дрібниці» ентузіастів ніколи не зупиняли. Тим більше, є програма під назвою Profitable Pool. Вона автоматично відстежує найвигідніші для видобутку альткоїни на даний момент. Є й сервіс пошуку самих пулів, а також їх рейтинги в реальному часі.

Крок 2. Встановлюємо та налаштовуємо програму

Зареєструвавшись на сайті пула, потрібно завантажити спеціальну програму-майнер - не обчислювати код вручну за допомогою калькулятора. Таких програм також достатньо. Для біткоїну це – 50 minerабо CGMiner, для ефіру Ethminer.

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

Крок 3. Реєструємо гаманець

Якщо у вас ще немає біткоїн-гаманця або ефіріум-сховища, потрібно їх обов'язково зареєструвати. Гаманці завантажуємо з офіційних сайтів.

Іноді допомогу у цій справі надають самі пули, але з безоплатно.

Крок 4. Запускаємо майнінг та стежимо за статистикою

Залишилося тільки запустити процес і чекати на перші надходження. Обов'язково завантажте допоміжну програму, яка відстежуватиме стан основних вузлів вашого комп'ютера – завантаженість, перегрів тощо.

Крок 5. Виводимо криптовалюту

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

Як переводити цифрову валюту у фіатну?Питання, гідне окремої статті. Якщо коротко, то самий швидкий спосіб- Обмінні пункти. Вони беруть собі відсотки за послуги, і ваше завдання знайти найвигідніший курс з мінімальною комісією. Зробити це допоможе професійний сервіспорівняння обмінників.

– найкращий у Рунеті ресурс такого плану. Цей моніторинг порівнює показники більше 300 обмінних пунктів і знаходить кращі котирування за валютними парами, що вас цікавлять. Понад те, сервіс показує резерви криптовалюти в касі. У списках моніторингу – лише перевірені та надійні обмінні сервіси.

3. На що звертати увагу при виборі відеокарти для майнінгу

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

Основні показники такі: продуктивність (потужність), енергоспоживання, охолодження, перспективи розгону.

1) Потужність

Тут все просто – що вища продуктивність процесора, краще для обчислення хеш-коду. Відмінні показники забезпечують карти з об'ємом пам'яті більше ніж 2 ГБ. І вибирайте пристрої із 256-розрядною шиною. 128-розрядні для цієї справи не годяться.

2) Енергоспоживання

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

3) Охолодження

Стандартна складається із 4-16 карт. Вона виробляє надмірну кількість тепла, згубне заліза і небажане самого фермера. В однокімнатній квартирі без кондиціонера житиме і працюватиме, м'яко кажучи, некомфортно.

Якісне охолодження процесора - неодмінна умова успішного майнінгу

Тому при виборі двох карток з однаковою продуктивністю віддавайте перевагу тій, у якої менше показник теплової потужності (TDP) . Найкращі параметриохолодження показують карти Radeon. Ці ж пристрої найдовше інших карт працюють в активному режимі без зносу.

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

4) Можливість розгону

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

Які відеокарти купувати?Вам знадобляться пристрої останнього поколінняабо щонайменше графічні прискорювачі, випущені не раніше ніж 2-3 роки тому. Майнери використовують карти AMD Radeon, Nvidia, Geforce GTX.

Погляньте на таблицю окупності відеокарт (дані актуальні на кінець 2017 року):

4. Де купити відеокарту для майнінгу – огляд ТОП-3 магазинів

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

Вам допоможе наш огляд найкращих точок онлайн-продажів.

1) TopComputer

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

На момент написання статті у продажу є карти AMD, Nvidia(8 Gb) та інші різновиди, що підходять для майнінгу.

2) Мybitcoinshop

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

Компанія неодноразово отримувала неофіційне звання найкращого в РФ магазину для майнерів. Оперативний сервіс, доброзичливе ставлення до клієнтів, передове обладнання – основні складові успіху.

3) Ship Shop America

Купівля та доставка товарів зі США. Посередницька компанія для тих, кому потрібні справді ексклюзивні та передові товари для майнінгу.

Прямий партнер провідного виробника відеокарт для ігор та майнінгу – Nvidia. Максимальний термін очікування товару – 14 днів.

5. Як збільшити дохід від майнінгу на відеокарті – 3 корисні поради

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

Заробітки залежать від обладнання, курсу криптовалюти, ефективності пулу, потужності ферми, кількості хешрейту та купи інших факторів. Одним вдається отримувати щомісяця до 70 000 у рублях , інші задовольняються 10 доларамив тиждень. Це нестабільний та непередбачуваний бізнес.

Корисні поради допоможуть підвищити доходи та оптимізувати витрати.

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

Порада 2. Використовуйте калькулятор майнінгу для вибору оптимального обладнання

Калькулятор майнінгу на сайті пула або на іншому спеціалізованому сервісі допоможе вибрати оптимальну програму та навіть відеокарту для майнінгу.

Використання GPU для обчислень за допомогою C++ AMP

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

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

Розширення C++ AMP засновані мовою C++ і саме тому у цій статті демонструватимуться приклади мовою C++. Однак, при помірному використанні механізму взаємодій. NET, ви зможете використовувати алгоритми C++ AMP у своїх програмах для .NET. Але про це ми поговоримо наприкінці статті.

Введення у C++ AMP

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

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

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

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

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

    збільшення та зменшення різкості зображень та інші перетворення;

    швидке перетворення Фур'є;

    транспонування та множення матриць;

    сортування чисел;

    інверсія хеша "в лоб".

Відмінним джерелом додаткових прикладів може бути блог Microsoft Native Concurrency, де наводяться фрагменти коду та пояснення до них для різних алгоритмів, реалізованих на C++ AMP.

C++ AMP - це фреймворк, що входить до складу Visual Studio 2012, що дає розробникам на C++ простий спосіб виконання обчислень на графічному процесорі і вимагає наявності драйвера DirectX 11. Корпорація Microsoft випустила C++ AMP як відкриту специфікацію , яку може реалізувати будь-який виробник компі.

Фреймворк C++ AMP дозволяє виконувати код на графічних прискорювачів (accelerators), що є обчислювальними пристроями. За допомогою драйвера DirectX 11 фреймворк C++ AMP динамічно виявляє усі прискорювачі. До складу C++ AMP входять також програмний емулятор прискорювача та емулятор на базі звичайного процесора, WARP, які служить запасним варіантом у системах без графічного процесора або з графічним процесором, але без драйвера DirectX 11, і використовує кілька ядер та інструкції SIMD.

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

Void VectorAddExpPointwise(float* first, float* second, float* result, int length) ( for (int i = 0; i< length; ++i) { result[i] = first[i] + exp(second[i]); } }

Щоб розпаралелити цей алгоритм на звичайному процесорі, потрібно розбити діапазон ітерацій на кілька піддіапазонів і запустити по одному потоку виконання для кожного з них. Ми присвятили досить багато часу в попередніх статтях саме такому способу розпаралелювання нашого першого прикладу пошуку простих чисел - ми бачили, як це можна зробити, створюючи потоки вручну, передаючи завдання пулу потоків і використовуючи Parallel.For і PLINQ для автоматичного розпаралелювання. Згадайте також, що при розпаралелювання схожих алгоритмів на звичайному процесорі ми особливо дбали, щоб не роздробити завдання на занадто дрібні завдання.

Для графічного процесора ці попередження непотрібні. Графічні процесори мають безліч ядер, що виконують потоки дуже швидко, а вартість перемикання контексту значно нижча, ніж у звичайних процесорах. Нижче наводиться фрагмент, який намагається використовувати функцію parallel_for_eachіз фреймворку C++ AMP:

#include #include using namespace concurrency; void VectorAddExpPointwise(float* first, float* second, float* result, int length) ( array_view avFirst (length, first); array_view avSecond(length, second); array_view avResult(length, result); avResult.discard_data(); parallel_for_each(avResult.extent, [=](index<1>i) restrict(amp) (avResult[i] = avFirst[i] + fast_math::exp(avSecond[i]); )); avResult.synchronize(); )

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

Далі, вхідні дані (параметри first, second та result) обгортаються екземплярами array_view. Клас array_view служить для обгортання даних, які передаються графічному процесору (прискорювачу). Його шаблонний параметр визначає тип даних та їх розмірність. Щоб виконати на графічному процесорі інструкції, що звертаються до даних, спочатку оброблюваним на звичайному процесорі, хтось чи щось має подбати про копіювання даних у графічний процесор, оскільки більшість сучасних графічних карток є окремими пристроями з власною пам'яттю. Це завдання вирішують екземпляри array_view – вони забезпечують копіювання даних на вимогу і тільки коли вони дійсно необхідні.

Коли графічний процесор виконає завдання, копіюються дані назад. Створюючи екземпляри array_view з аргументом типу const, ми гарантуємо, що first і second будуть скопійовані на згадку про графічний процесор, але не копіюватимуться назад. Аналогічно, викликаючи discard_data(), ми виключаємо копіювання результату з пам'яті звичайного процесора в пам'ять прискорювача, але ці дані копіюватимуться у зворотному напрямку.

Функція parallel_for_each приймає об'єкт extent, що визначає форму даних і функцію для застосування до кожного елемента в об'єкті extent. У цьому прикладі ми використовували лямбда-функцію, підтримка яких з'явилася в стандарті ISO C++2011 (C++11). Ключове слово restrict (amp) доручає компілятору перевірити можливість виконання тіла функції на графічному процесорі та відключає більшу частину синтаксису C++, який може бути скомпільований в інструкції графічного процесора.

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

Зрештою, виклик методу synchronize()Наприкінці методу VectorAddExpPointwise гарантує копіювання результатів обчислень з array_view avResult, вироблених графічним процесором, назад у масив результату.

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

Розмноження матриць

Перший «справжній» приклад, який ми розглянемо, – множення матриць. Для реалізації ми візьмемо простий кубічний алгоритм множення матриць, а чи не алгоритм Штрассена, має час виконання, близьке до кубічного ~O(n 2.807). Для двох матриць: матриці A розміром m x w та матриці B розміром w x n, наступна програма виконає їх множення та поверне результат - матрицю C розміром m x n:

Void MatrixMultiply(int * A, int m, int w, int * B, int n, int * C) ( for (int i = 0; i< m; ++i) { for (int j = 0; j < n; ++j) { int sum = 0; for (int k = 0; k < w; ++k) { sum += A * B; } C = sum; } } }

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

Void MatrixMultiply (int * A, int m, int w, int * B, int n, int * C) ( array_view avA(m, w, A); array_view avB(w, n, B); array_view avC(m, n, C); avC.discard_data(); parallel_for_each (avC.extent, [=](index<2>idx) restrict(amp) ( int sum = 0; for (int k = 0; k< w; ++k) { sum + = avA(idx*w, k) * avB(k*w, idx); } avC = sum; }); }

Ця реалізація все ще близько нагадує послідовну реалізацію множення матриць і приклад складання векторів, що наводилися вище, за винятком індексу, який є двовимірним і доступний у внутрішньому циклі із застосуванням оператора . Наскільки ця версія швидше за послідовну альтернативу, що виконується на звичайному процесорі? Помноження двох матриць (цілих чисел) розміром 1024 х 1024 послідовна версія на звичайному процесорі виконує в середньому 7350 мілісекунд, тоді як версія для графічного процесора - тримайтеся міцніше - 50 мілісекунд, у 147 разів швидше!

Моделювання руху частинок

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

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

// тут float4 - це вектори з чотирма елементами, // репрезентують частинки, що беруть участь в операціях void bodybody_interaction (float4& acceleration, const float4 p1, const float4 p2) restrict(amp) ( float4 dist = p2 – p1; // w тут не використовується float absDist = dist.x * dist.x + dist.y * dist.y + dist.z * dist.z; float invDist = 1.0f / sqrt (absDist); = dist*PARTICLE_MASS*invDistCube;

Вихідними даними на кожному кроці моделювання є масив з координатами та швидкостями руху частинок, а в результаті обчислень створюється новий масив з координатами та швидкостями частинок:

Struct particle ( float4 position, velocity; // реалізації конструктора, конструктора копіювання та // оператора = з restrict (amp) опущені для економії місця); void simulation_step (array & previous, array & next, int bodies) (extent<1>ext(bodies); parallel_for_each (ext, [&](index<1>idx) restrict(amp) ( particle p = previous; float4 acceleration(0, 0, 0, 0); for (int body = 0; body)< bodies; ++body) { bodybody_interaction (acceleration, p.position, previous.position); } p.velocity + = acceleration*DELTA_TIME; p.position + = p.velocity*DELTA_TIME; next = p; }); }

Із залученням відповідного графічного інтерфейсу, моделювання може бути дуже цікавим. Повний приклад, представлений командою розробників C++ AMP, можна знайти у блозі Native Concurrency. На моїй системі з процесором Intel Core i7 та відеокартою Geforce GT 740M, моделювання руху 10 000 частинок виконується зі швидкістю ~2.5 кадру в секунду (кроків в секунду) з використанням послідовної версії, що виконується на звичайному процесорі, та 160 кадрів в секунду з використанням оптимізований версії, що виконується на графічному процесорі – величезне збільшення продуктивності.

Перш ніж завершити цей розділ, необхідно розповісти ще одну важливу особливість фреймворку C++ AMP, яка може ще більше підвищити продуктивність коду, що виконується на графічному процесорі. Графічні процесори підтримують програмований кеш даних(часто званий пам'яттю, що розділяється (shared memory)). Значення, що зберігаються в цьому кеші, спільно використовуються всіма потоками виконання однієї мозаїці (tile). Завдяки мозаїчній організації пам'яті, програми на основі фреймворку C++ AMP можуть читати дані з пам'яті графічної карти в пам'ять мозаїки, що розділяється, і потім звертатися до них з декількох потоків виконання без повторного вилучення цих даних з пам'яті графічної карти. Доступ до пам'яті мозаїки виконується приблизно в 10 разів швидше, ніж до пам'яті графічної карти. Іншими словами, у вас є причини читання.

Щоб забезпечити виконання мозаїчної версії паралельного циклу методу parallel_for_each передається домен tiled_extent, який ділить багатовимірний об'єкт extent на багатовимірні фрагменти мозаїки, і лямбда-параметр tiled_index, що визначає глобальний та локальний ідентифікатор потоку всередині мозаїки. Наприклад, матрицю 16x16 можна розділити на фрагменти мозаїки розміром 2x2 (як показано на малюнку нижче) і потім передати функції parallel_for_each:

Extent<2>matrix(16,16); tiled_extent<2,2>tiledMatrix = matrix.tile<2,2>(); parallel_for_each (tiledMatrix, [=](tiled_index<2,2>idx) restrict (amp) ( // ...));

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

При виконанні операцій з матрицями, в ядрі графічного процесора, замість стандартного індексу index<2>, як у прикладах вище, можна використовувати idx.global. Грамотне використання локальної мозаїчної пам'яті та локальних індексів може забезпечити суттєвий приріст продуктивності. Щоб оголосити мозаїчну пам'ять, поділювану всіма потоками виконання однієї мозаїці, локальні змінні можна оголосити зі специфікатором tile_static.

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

Parallel_for_each(tiledMatrix, [=](tiled_index<2,2>idx) restrict(amp) ( // 32 байти спільно використовуються всіма потоками в блоці tile_static int local; // присвоїти значення елементу для цього потоку виконання local = 42; ));

Очевидно, що будь-які вигоди від використання пам'яті, що розділяється, можна отримати тільки в разі синхронізації доступу до цієї пам'яті; тобто потоки не повинні звертатися до пам'яті, доки вона не буде ініціалізована одним із них. Синхронізація потоків у мозаїці виконується за допомогою об'єктів tile_barrier(що нагадує клас Barrier з бібліотеки TPL) - вони зможуть продовжити виконання лише після виклику методу tile_barrier.Wait(), який поверне керування лише коли всі потоки викличуть tile_barrier.Wait. Наприклад:

Parallel_for_each (tiledMatrix, (tiled_index<2,2>idx) restrict(amp) ( // 32 байти спільно використовуються всіма потоками в блоці tile_static int local; // присвоїти значення елементу для цього потоку виконання local = 42; // idx.barrier - екземпляр tile_barrier idx.barrier.wait(); // Тепер цей потік може звертатися до масиву "local", // використовуючи індекси інших потоків виконання!));

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

Суть цього прийому зводиться до наступного. Щоб знайти C i,j (елемент у рядку i і в стовпці j у матриці результату), потрібно обчислити скалярний добуток між A i, * (i-й рядок першої матриці) і B *,j (j-й стовпець у другій матриці ). Однак це еквівалентно обчисленню часткових скалярних творів рядка і стовпця з подальшим підсумовуванням результатів. Ми можемо використовувати цю обставину для перетворення алгоритму множення матриць на мозаїчну версію:

Void MatrixMultiply(int * A, int m, int w, int * B, int n, int * C) ( array_view avA(m, w, A); array_view avB(w, n, B); array_view avC(m, n, C); avC.discard_data(); parallel_for_each (avC.extent.tile<16,16>(), [=](tiled_index<16,16>idx) restrict(amp) ( int sum = 0; int localRow = idx.local, localCol = idx.local; for (int k = 0; k

Суть оптимізації, що описується в тому, що кожен потік в мозаїці (для блоку 16 х 16 створюється 256 потоків) ініціалізує свій елемент в 16 х 16 локальних копіях фрагментів вихідних матриць A і B. Кожному потоку в мозаїці потрібно тільки один рядок і один стовпець з цих блоків, але всі потоки разом будуть звертатися до кожного рядка і кожного стовпця по 16 разів. Такий підхід суттєво знижує кількість звернень до основної пам'яті.

Щоб обчислити елемент (i,j) у матриці результату, алгоритму потрібно повний i-й рядок першої матриці та j-й стовпець другої матриці. Коли потоки мозаїці 16x16, представлені на діаграмі і k=0, заштриховані області першої і другої матрицях будуть прочитані в пам'ять, що розділяється. Потік виконання, що обчислює елемент (i,j) у матриці результату, обчислить частковий скалярний добуток перших k елементів з i-го рядка та j-го стовпця вихідних матриць.

У цьому прикладі застосування мозаїчної організації забезпечує величезний приріст продуктивності. Мозаїчна версія множення матриць виконується набагато швидше за просту версію і займає приблизно 17 мілісекунд (для тих же вихідних матриць розміром 1024 х 1024), що в 430 швидше за версію, що виконується на звичайному процесорі!

Перш ніж закінчити обговорення фреймворку C++ AMP, нам хотілося б згадати інструменти (в Visual Studio), які є у розпорядженні розробників. Visual Studio 2012 пропонує налагоджувач для графічного процесора (GPU), що дозволяє встановлювати контрольні точки, досліджувати стек викликів, читати та змінювати значення локальних змінних (деякі прискорювачі підтримують налагодження для GPU безпосередньо; для інших Visual Studio використовує програмний симулятор), та профільник, що дає можливість оцінювати вигоди, одержувані додатком від розпаралелювання операцій із застосуванням графічного процесора. За додатковою інформацією щодо можливостей налагодження у Visual Studio звертайтеся до статті «Покроковий посібник. Налагодження програми «C++ AMP» на сайті MSDN.

Альтернативи обчислень на графічному процесорі В.NET

До цих пір у цій статті демонструвалися приклади тільки мовою C++, проте є кілька способів використовувати потужність графічного процесора в керованих додатках. Один із способів – використовувати інструменти взаємодій, що дозволяють перекласти роботу з ядрами графічного процесора на низькорівневі компоненти C++. Це рішення відмінно підходить для тих, хто бажає використовувати фреймворк C++ AMP або може використовувати вже готові компоненти C++ AMP в керованих додатках.

Інший спосіб - використовувати бібліотеку, що безпосередньо працює з графічним процесором з керованого коду. Нині є кілька таких бібліотек. Наприклад, GPU.NET та CUDAfy.NET (обидві є комерційними пропозиціями). Нижче наведено приклад з репозиторію GPU.NET GitHub, що демонструє реалізацію скалярного твору двох векторів:

Public static void MultiplyAddGpu(double a, double b, double c) (int ThreadId = BlockDimension.X * BlockIndex.X + ThreadIndex.X; int TotalThreads = BlockDimension.X * GridDimension.X; for (int ElementIdx = ThreadId

Я дотримуюся думки, що набагато простіше та ефективніше освоїти розширення мови (на основі C++ AMP), ніж намагатися організовувати взаємодії на рівні бібліотек чи вносити суттєві зміни до мови IL.

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

Бібліотека Task Parallel Library дає нам унікальну можливість включити в роботу всі наявні ядра центрального процесора, хоча при цьому доведеться вирішувати деякі цікаві проблеми синхронізації, надмірного дроблення завдань і нерівного розподілу роботи між потоками виконання.

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

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

Налаштувати параметри GPU візуалізації

Якщо ваша програма гальмує, то частина або всі кадри оновлення екрана оновлюються більше ніж 16 мілісекунд. Щоб візуально побачити оновлення кадрів на екрані, можна увімкнути на пристрої спеціальну опцію (Profile GPU Rendering).

У вас з'явиться можливість побачити, скільки часу займає малювання кадрів. Нагадаю, що потрібно вкладатися у 16 ​​мілісекунд.

Опція доступна на пристрої, починаючи з Android 4.1. У пристрої слід активувати режим розробника. На пристроях з версією 4.2 і вище стандартний режим прихований. Для активації йде в Налаштування | Про телефоні сім разів клацаємо по рядку Номер складання.

Після активації заходимо до Опції розробниката знаходимо пункт Налаштувати параметри GPU візуалізації(Profile GPU rendering), який слід увімкнути. У спливаючому вікні виберіть опцію На екрані у вигляді стовпчиків(On screen as bars). У цьому випадку графік виводитиметься поверх запущеної програми.

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

Розглянемо збільшену версію графіка.

Зелена лінія відповідає за 16 мілісекунд. Щоб укластися в 60 кадрів на секунду, кожен стовпець графіка повинен малюватись нижче цієї лінії. У якихось моментах стовпець виявиться занадто великим і буде набагато вищим за зелену лінію. Це означає гальмування програми. Кожен стовпець має блакитний, фіолетовий (Lollipop та вище), червоний та помаранчевий кольори.

Блакитний колір відповідає за час, що використовується на створення та оновлення View.

Фіолетова частина є час, витрачений на передачу ресурсів рендерингу потоку.

Червоний колір є час для малювання.

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

Існують спеціальні методики зменшення навантаження на графічний процесор.

Налагодити показник GPU overdraw

Інше налаштування дозволяє дізнатися, як часто перемальовується один і той же ділянку екрану (тобто виконується зайва робота). Знову йдемо в Опції розробниката знаходимо пункт Налагодити показник GPU overdraw(Debug GPU Overdraw), який слід увімкнути. У спливаючому вікні виберіть опцію Показувати зони накладання(Show overdraw areas). Не лякайтесь! Деякі елементи на екрані змінять колір.

Поверніться до будь-якої програми та поспостерігайте за його роботою. Колір підкаже проблемні ділянки вашої програми.

Якщо колір у додатку не змінився, все відмінно. Немає накладання одного кольору поверх іншого.

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

Зелений колір – перемальовується двічі. Потрібно подумати про оптимізацію.

Рожевий колір – перемальовується тричі. Все дуже погано.

Червоний колір – перемальовується багато разів. Щось пішло не так.

Ви можете самостійно перевірити свою програму для пошуку проблемних місць. Створіть активність та помістіть на неї компонент TextView. Надайте кореневому елементу та текстовій мітці якесь тло в атрибуті android:background. У вас вийде наступне: спочатку ви зафарбували одним кольором нижній шар активності. Потім поверх неї малюється новий шар від TextView. До речі, насправді TextViewмалюється ще й текст.

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

Маленька порада. Помістіть після методу setContentView()виклик методу, який прибере перирисування екрану кольором теми. Це допоможе прибрати одне зайве накладання кольору:

GetWindow().setBackgroundDrawable(null);

Обчислення на графічних процесорах

Технологія CUDA (Compute Unified Device Architecture) - програмно-апаратна архітектура, що дозволяє проводити обчислення з використанням графічних процесорів NVIDIA, що підтримують технологію GPGPU (довільних обчислень на відеокартах). Архітектура CUDA вперше з'явилися на ринку з виходом чіпа NVIDIA восьмого покоління - G80 і є у всіх наступних серіях графічних чіпів, які використовуються в сімействах прискорювачів GeForce, ION, Quadro та Tesla.

CUDA SDK дозволяє програмістам реалізовувати на спеціальному спрощеному діалекті мови програмування Сі алгоритми, здійсненні на графічних процесорах NVIDIA і включати спеціальні функції текст програми на Cі. CUDA дає розробнику можливість на власний розсуд організовувати доступ до набору інструкцій графічного прискорювача і керувати його пам'яттю, організовувати на ньому складні паралельні обчислення.

Історія

У 2003 р. Intel та AMD брали участь у спільній гонці за найпотужніший процесор. За кілька років в результаті цих перегонів тактові частоти суттєво зросли, особливо після виходу Intel Pentium 4.

Після приросту тактових частот (між 2001 і 2003 рр. тактова частота Pentium 4 подвоїлася з 1,5 до 3 ГГц), а користувачам довелося задовольнятися десятими частками гігагерц, які вивели на ринок виробники (з 2003 до 2005 рр.) 3,8 ГГц).

Архітектури, оптимізовані під високі тактові частоти, та сама Prescott, так само стали відчувати труднощі, і не тільки виробничі. Виробники чіпів зіштовхнулися із проблемами подолання законів фізики. Деякі аналітики навіть пророкували, що закон Мура перестане діяти. Але цього не сталося. Оригінальний зміст закону часто спотворюють, проте стосується кількості транзисторів лежить на поверхні кремнієвого ядра. Довгий час підвищення числа транзисторів у CPU супроводжувалося відповідним зростанням продуктивності - що призвело до спотворення сенсу. Але потім ситуація ускладнилася. Розробники архітектури CPU підійшли до закону скорочення приросту: число транзисторів, яке потрібно додати для потрібного збільшення продуктивності, ставало все більшим, заводячи в глухий кут.

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

Робота GPU відносно проста. Вона полягає у прийнятті групи полігонів з одного боку та генерації групи пікселів з іншого. Полігони та пікселі незалежні один від одного, тому їх можна обробляти паралельно. Таким чином, GPU можна виділити велику частину кристала на обчислювальні блоки, які, на відміну від CPU, будуть реально використовуватися.

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

Перші розрахунки на GPU

Найперші спроби такого застосування обмежувалися використанням деяких апаратних функцій, таких як растеризація та Z-буферизація. Але в нинішньому столітті з появою шейдерів почали прискорювати обчислення матриць. У 2003 р. на SIGGRAPH окрема секція була виділена під обчислення на GPU, і отримала назву GPGPU (General-Purpose computation on GPU) - універсальні обчислення на GPU).

Найбільш відомий BrookGPU – компілятор потокової мови програмування Brook, створений для виконання неграфічних обчислень на GPU. До появи розробники, які використовують можливості відеочипів для обчислень, вибирали одне із двох поширених API: Direct3D чи OpenGL. Це серйозно обмежувало застосування GPU, адже в 3D графіку використовуються шейдери та текстури, про які фахівці з паралельного програмування знати не зобов'язані, вони використовують потоки та ядра. Brook зміг допомогти полегшити їх завдання. Ці потокові розширення до мови C, розроблені в Стендфордському університеті, приховували від програмістів тривимірний API, і представляли відеочіп у вигляді паралельного співпроцесора. Компілятор обробляв файл.br із кодом C++ та розширеннями, виробляючи код, прив'язаний до бібліотеки з підтримкою DirectX, OpenGL або x86.

Поява Brook викликала інтерес у NVIDIA та ATI і надалі, відкрив цілий новий його сектор - паралельні обчислювачі на основі відеочіпів.

Надалі деякі дослідники з проекту Brook перейшли в команду розробників NVIDIA, щоб представити програмно-апаратну стратегію паралельних обчислень, відкривши нову частку ринку. І головною перевагою цієї ініціативи NVIDIA стало те, що розробники чудово знають всі можливості своїх GPU до дрібниць, і у використанні графічного API немає необхідності, а працювати з апаратним забезпеченням можна за допомогою драйвера. Результатом зусиль команди стала NVIDIA CUDA.

Області застосування паралельних розрахунків на GPU

При перенесенні обчислень на GPU у багатьох завданнях досягається прискорення в 5-30 разів, порівняно зі швидкими універсальними процесорами. Найбільші цифри (близько 100-кратного прискорення і навіть більше!) досягаються на коді, який дуже добре підходить для розрахунків за допомогою блоків SSE, але цілком зручний для GPU.

Це лише деякі приклади прискорення синтетичного коду на GPU проти SSE-векторизованого коду на CPU (за даними NVIDIA):

Флуоресцентна мікроскопія: 12 х.

Молекулярна динаміка (non-bonded force calc): 8-16x;

Електростатика (пряме та багаторівневе підсумовування Кулону): 40-120x та 7x.

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

Перелік основних додатків, в яких застосовуються обчислення на GPU: аналіз та обробка зображень та сигналів, симуляція фізики, обчислювальна математика, обчислювальна біологія, фінансові розрахунки, бази даних, динаміка газів та рідин, криптографія, адаптивна променева терапія, астрономія, обробка звуку , біологічні симуляції, комп'ютерний зір, аналіз даних (data mining), цифрове кіно та телебачення, електромагнітні симуляції, геоінформаційні системи, військові застосування, гірське планування, молекулярна динаміка, магнітно-резонансна томографія (MRI), нейромережі, океанографічні дослідження, фізика частинок, симуляція згортання молекул білка, квантова хімія, трасування променів, візуалізація, радари, гідродинамічний моделювання (reservoir simulation), штучний інтелект, аналіз супутникових даних, сейсмічна розвідка, хірургія, ультразвук, відеоконференції.

Переваги та обмеження CUDA

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

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

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

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

Переваги CUDA перед традиційним підходом до обчислень GPGPU

CUDA забезпечує доступ до розділяється між потоками пам'яті розміром 16 Кб на мультипроцесор, яка може бути використана для організації кешу з широкою смугою пропускання, в порівнянні з текстурними вибірками;

Більш ефективна передача даних між системною та відеопам'яттю;

Відсутність необхідності в графічних API з надмірністю та накладними витратами;

Лінійна адресація пам'яті, і gather і scatter; можливість запису за довільними адресами;

Апаратна підтримка цілих і бітових операцій.

Основні обмеження CUDA:

відсутність підтримки рекурсії для виконуваних функцій;

Мінімальна ширина блоку 32 потоку;

Закрита архітектура CUDA, що належить NVIDIA.

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

Основні переваги CUDA порівняно з попередніми методами GPGPU випливають з того, що ця архітектура спроектована для ефективного використання неграфічних обчислень на GPU та використовує мову програмування C, не вимагаючи перенесення алгоритмів у зручний для концепції графічного конвеєра вигляд. CUDA пропонує новий шлях обчислень на GPU, що не використовує графічні API, що пропонує довільний доступ до пам'яті (scatter або gather). Така архітектура позбавлена ​​недоліків GPGPU та використовує всі виконавчі блоки, а також розширює можливості за рахунок цілісної математики та операцій бітового зсуву.

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

Зручніший у CUDA та доступ до пам'яті. Програмний код у графічних API виводить дані у вигляді 32-х значень з плаваючою точкою одинарної точності (RGBA значення одночасно у вісім render target) у заздалегідь визначені області, а CUDA підтримує scatter запис - необмежену кількість записів за будь-якою адресою. Такі переваги уможливлюють виконання на GPU деяких алгоритмів, які неможливо ефективно реалізувати за допомогою методів GPGPU, заснованих на графічних API.

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

Недоліки CUDA

Один з нечисленних недоліків CUDA – слабка переносимість. Ця архітектура працює тільки на відеочіпах цієї компанії та ще й не на всіх, а починаючи з серії GeForce 8 і 9 і відповідних Quadro, ION і Tesla. NVIDIA наводить цифру в 90 мільйонів CUDA-сумісних відеочіпів.

Альтернативи CUDA

Фреймворк для написання комп'ютерних програм, пов'язаних із паралельними обчисленнями на різних графічних та центральних процесорах. У фреймворк OpenCL входять мову програмування, яка базується на стандарті C99, та інтерфейс програмування додатків (API). OpenCL забезпечує паралелізм лише на рівні інструкцій і лише на рівні даних і є реалізацією техніки GPGPU. OpenCL є повністю відкритим стандартом, його використання не обкладається ліцензійними відрахуваннями.

Мета OpenCL полягає в тому, щоб доповнити OpenGL та OpenAL, які є відкритими галузевими стандартами для тривимірної комп'ютерної графіки та звуку, користуючись можливостями GPU. OpenCL розробляється та підтримується некомерційним консорціумом Khronos Group, до якого входять багато великих компаній, включаючи Apple, AMD, Intel, nVidia, Sun Microsystems, Sony Computer Entertainment та інші.

CAL/IL (Compute Abstraction Layer/Intermediate Language)

ATI Stream Technology - це набір апаратних та програмних технологій, які дозволяють використовувати графічні процесори AMD, спільно з центральним процесором, для прискорення багатьох програм (не тільки графічних).

Областями застосування ATI Stream є програми, вимогливі до обчислювального ресурсу, такі як фінансовий аналіз або обробка сейсмічних даних. Використання потокового процесора дозволило збільшити швидкість деяких фінансових розрахунків у 55 разів у порівнянні з рішенням того ж завдання силами лише центрального процесора.

Технологію ATI Stream у NVIDIA не вважають дуже сильним конкурентом. CUDA та Stream – це дві різні технології, які стоять на різних рівнях розвитку. Програмування для продуктів ATI набагато складніше - їхня мова швидше нагадує асемблер. CUDA C, у свою чергу, набагато більш високорівнева мова. Писати на ньому зручніше та простіше. Для великих компаній розробників це дуже важливо. Якщо говорити про продуктивність, можна помітити, що її пікове значення в продуктах ATI вище, ніж у рішеннях NVIDIA. Але знову все зводиться до того, як цю потужність отримати.

DirectX11 (DirectCompute)

Інтерфейс програмування додатків, який входить до складу DirectX - набору API від Microsoft, призначений для роботи на IBM PC-сумісних комп'ютерах під управлінням операційних систем сімейства Microsoft Windows. DirectCompute призначений для виконання обчислень загального призначення на графічних процесорах, будучи реалізацією концепції GPGPU. Спочатку DirectCompute був опублікований у складі DirectX 11, проте пізніше став доступним і для DirectX 10 та DirectX 10.1.

NVDIA CUDA у російському науковому середовищі.

Станом на грудень 2009 р. програмна модель CUDA викладається у 269 університетах світу. У Росії навчальні курси з CUDA читаються в Московському, Санкт-Петербурзькому, Казанському, Новосибірському та Пермському державних університетах, Міжнародному університеті природи суспільства та людини "Дубна", Об'єднаному інституті ядерних досліджень, Московському інституті електронної техніки, Іванівському державному енергетичному університеті, БДТУ ім. В. Г. Шухова, МДТУ ім. Баумана, РГТУ ім. Менделєєва, Російському науковому центрі "Курчатівський інститут", Міжрегіональному суперкомп'ютерному центрі РАН, Таганрозькому технологічному інституті (ТТІ ЮФУ).

Говорячи про паралельні обчислення на GPU ми повинні пам'ятати, в який час ми живемо, сьогодні цей час коли все у світі прискорено настільки, що ми з вами втрачаємо рахунок часу, не помічаючи, як воно пролітатиме повз. Все, що ми робимо, пов'язано з високою точністю та швидкістю обробки інформації, в таких умовах нам неодмінно потрібні інструменти для того, щоб обробити всю інформацію, яка у нас є і перетворити її на дані, до того ж кажучи про такі завдання треба пам'ятати, що ці завдання необхідні не тільки великим організаціям або мегакорпораціям, вирішення таких завдань зараз потребують і рядові користувачі, які вирішують свої життєві завдання, пов'язані з високими технологіями у себе вдома на персональних комп'ютерах! Поява NVIDIA CUDA була не дивовижною, а, швидше, обґрунтованою, тому, як незабаром буде необхідно обробляти значно трудомісткіші завдання на ПК, ніж раніше. Робота, яка раніше займала дуже багато часу, тепер займатиме лічені хвилини, відповідно, це вплине на загальну картину всього світу!

Що таке обчислення на GPU

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

Що таке CUDA

CUDA — технологія програмування спрощеною мовою Сі алгоритмів, які виконуються на графічних процесорах прискорювачів GeForce восьмого покоління і старше, а також відповідних карток Quadro і Tesla від компанії NVIDIA. CUDA дозволяє включати до тексту Си програми спеціальні функції. Ці функції пишуться спрощеною мовою програмування Сі і виконуються на графічному процесорі. Початкова версія CUDA SDK була представлена ​​15 лютого 2007 року. Для успішної трансляції коду цією мовою до складу CUDA SDK входить власний Сі-компілятор командного рядка nvcc компанії NVIDIA. Компілятор nvcc створений на основі відкритого компілятора Open64 і призначений для трансляції host-коду (головного, керуючого коду) і device-коду (апаратного коду) (файлів з розширенням .cu) в об'єктні файли, придатні в процесі складання кінцевої програми або бібліотеки в будь-якій середовище програмування, наприклад Microsoft Visual Studio.

Можливості технології

  1. Стандартна мова C для паралельної розробки додатків на GPU.
  2. Готові бібліотеки чисельного аналізу для швидкого перетворення Фур'є та базового пакету програм лінійної алгебри.
  3. Спеціальний драйвер CUDA для обчислень із швидкою передачею даних між GPU та CPU.
  4. Можливість взаємодії драйвера CUDA з графічними драйверами OpenGL та DirectX.
  5. Підтримка операційних систем Linux 32/64-bit, Windows XP 32/64-bit та MacOS.

Переваги технології

  1. Інтерфейс програмування програм CUDA (CUDA API) базується на стандартній мові програмування Сі з деякими обмеженнями. Це спрощує і згладжує процес вивчення архітектури CUDA.
  2. Пам'ять (shared memory) розміром 16 Кб, що розділяється між потоками, може бути використана під організований користувачем кеш з ширшою смугою пропускання, ніж при вибірці зі звичайних текстур.
  3. Більш ефективні транзакції між пам'яттю центрального процесора та відеопам'яттю.
  4. Повна апаратна підтримка цілих і побітових операцій.

Приклад застосування технології

cRark

Найважче в цій програмі — це настоянка. Програма має консольний інтерфейс, але завдяки інструкції, яка додається до самої програми, вона може користуватися. Далі наведено коротку інструкцію з налаштування програми. Ми перевіримо програму на працездатність і порівняємо її з іншою подібною програмою, яка не використовує NVIDIA CUDA, в даному випадку це відома програма Advanced Archive Password Recovery.

З скаченого архіву cRark нам потрібно лише три файли: crark.exe, crark-hp.exe і password.def. Сrark.exe - це консольна утиліта розкриття паролів RAR 3.0 без шифрованих файлів усередині архіву (тобто розкриваючи архів ми бачимо назви, але не можемо розпакувати архів без пароля).

Сrark-hp.exe - це консольна утиліта розтину паролів RAR 3.0 із шифруванням всього архіву (тобто розкриваючи архів ми не бачимо ні назви, ні самих архівів і не можемо розпакувати архів без пароля).

Password.def - це будь-який перейменований текстовий файл з дуже невеликим змістом (наприклад: 1-й рядок: ## 2-й рядок: ?* , у цьому випадку відкриття пароля відбуватиметься з використанням усіх символів). Password.def – це керівник програми cRark. У файлі містяться правила розкриття пароля (або область знаків, яку crark.exe буде використовувати у своїй роботі). Докладніше про можливості вибору цих знаків написано в текстовому файлі отриманому при розтині завантаженого на сайті автора програми cRark: russian.def .

Підготовка

Відразу скажу, що програма працює тільки якщо ваша відеокарта заснована на GPU за допомогою рівня прискорення CUDA 1.1. Так що серія відеокарт, заснованих на чіпі G80, таких як GeForce 8800 GTX відпадає, тому що вони мають апаратну підтримку прискорення CUDA 1.0. Програма підбирає за допомогою CUDA лише паролі на архіви RAR версій 3.0+. Необхідно встановити все програмне забезпечення, пов'язане з CUDA, а саме:

  • Драйвери NVIDIA , що підтримують CUDA , починаючи з 169.21
  • NVIDIA CUDA SDK, починаючи з версії 1.1
  • NVIDIA CUDA Toolkit, починаючи з версії 1.1

Створюємо будь-яку папку в будь-якому місці (наприклад на диску С:) і називаємо будь-яким ім'ям, наприклад, «3.2». Поміщаємо туди файли: crark.exe, crark-hp.exe та password.def та запаролений/зашифрований архів RAR.

Далі, слід запустити консоль командного рядка Windows і перейти до неї створену папку. У Windows Vista та 7 слід викликати меню "Пуск" і в полі пошуку ввести "cmd.exe", у Windows XP з меню "Пуск" спочатку слід викликати діалог "Виконати" і вже в ньому вводити "cmd.exe". Після відкриття консолі слід ввести команду виду: cd C:\папка\, cd C:\3.2 у цьому випадку.

Набираємо в текстовому редакторі два рядки (можна також зберегти текст як файл .bat у папці з cRark) для підбору пароля запароленого RAR-архіву із незашифрованими файлами:

echo off;
cmd /K crark (назва архіву).rar

для підбору пароля запароленого та зашифрованого RAR-архіву:

echo off;
cmd /K crark-hp (назва архіву).rar

Копіюємо 2 рядки текстового файлу в консоль і натискаємо Enter (або запускаємо файл .bat).

Результати

Процес розшифровки показаний малюнку:

Швидкість підбору на cRark за допомогою CUDA становила 1625 паролів/секунду. За одну хвилину тридцять шість секунд був підібраний пароль із трьома символами: «q)$». Для порівняння: швидкість перебору Advanced Archive Password Recovery на моєму двоядерному процесорі Athlon 3000+ дорівнює максимум 50 паролів/секунду і перебір мав би тривати 5 годин. Тобто підбір по bruteforce в cRark архіву RAR за допомогою відеокарти GeForce 9800 GTX+ відбувається у 30 разів швидше, ніж на CPU.

Для тих, у кого процесор Intel, хороша системна плата з високою частотою системної шини (FSB 1600 МГц), показник CPU rate та швидкість перебору будуть вищими. А якщо у вас чотириядерний процесор і пари відеокарт рівня GeForce 280 GTX, то швидкодія перебору паролів прискорюється в рази. Підбиваючи підсумки прикладу треба сказати, що це завдання було вирішено із застосуванням технології CUDA всього за якихось 2 хвилини замість 5-ти годин, що говорить про високий потенціал можливостей для даної технології!

Висновки

Розглянувши сьогодні технологію для паралельних обчислень CUDA, ми наочно побачили всю міць і величезний потенціал для розвитку даної технології на прикладі програми для відновлення пароля для RAR архівів. Треба сказати про перспективи даної технології, дана технологія неодмінно знайде місце в житті кожної людини, яка вирішить їй скористатися, чи то наукові завдання, чи завдання, пов'язані з обробкою відео, чи навіть економічні завдання, які вимагають швидкого точного розрахунку, все це призведе до неминучого. підвищенню продуктивності праці, яку не можна буде не помітити. На сьогоднішній день до лексикону вже починає входити словосполучення «домашній суперкомп'ютер»; Цілком очевидно, що для втілення такого предмета в реальність у кожному будинку вже є інструмент під назвою CUDA. Починаючи з моменту виходу карт, заснованих на чіпі G80 (2006 р.), випущено величезну кількість прискорювачів на базі NVIDIA, що підтримують технологію CUDA, яка здатна втілити мрії про суперкомп'ютери в кожному будинку в реальність. Просуваючи технологію CUDA, NVIDIA піднімає свій авторитет в очах клієнтів у вигляді надання додаткових можливостей їхнього обладнання, яке у багатьох вже куплено. Залишається тільки вірити, що незабаром CUDA буде розвиватися дуже швидко і дасть користувачам повною мірою скористатися всіма можливостями паралельних обчислень на GPU.

Підтримайте проект - поділіться посиланням, дякую!
Читайте також
Як встановити безкоштовний антивірус аваст Як встановити безкоштовний антивірус аваст Як очистити комп'ютер від вірусів самостійно Як очистити комп'ютер від вірусів самостійно Як повністю очистити комп'ютер від вірусів Як повністю очистити комп'ютер від вірусів