Перш за все, ви повинні знати про те, що CUDA не буде автоматично робити обчислення швидше. З одного боку, тому що програмування GPU - це мистецтво, і це може бути дуже складним, щоб виправити це правильно . З іншого боку, оскільки графічні процесори добре підходять лише для певних видів обчислень.
Це може здатися заплутаним, оскільки ви можете в основному обчислити що- небудь на GPU. Ключовим моментом є, звичайно, чи вдасться ви досягти хорошої швидкості чи ні. Найважливіша класифікація тут полягає в тому, чи є проблема паралельною задачі чи паралельною даною . Перший стосується, грубо кажучи, проблем, коли декілька ниток працюють над власними завданнями, більш-менш незалежно. Другий стосується проблем, коли багато потоків роблять те саме - але в різних частинах даних.
Останнє - це проблема, з якою добре справляються GPU: У них багато ядер, і всі ядра роблять те саме, але працюють на різних частинах вхідних даних.
Ви згадали, що у вас "проста математика, але з величезною кількістю даних". Хоча це може виглядати як ідеально паралельна проблема даних і, таким чином, як це було добре підходить для GPU, є ще один аспект, який слід врахувати: GPU є смішно швидкими з точки зору теоретичної обчислювальної потужності (FLOPS, Operating Floating Point Operations per Second). Але їх часто пригнічує пропускна здатність пам'яті.
Це призводить до іншої класифікації проблем. А саме, чи пов'язані проблеми з пам'яттю або з обчисленням .
Перший стосується проблем, коли кількість інструкцій, виконаних для кожного елемента даних, є низькою. Наприклад, розглянемо паралельне векторне додавання: Вам доведеться прочитати два елементи даних, потім виконати одне додавання і потім записати суму в вектор результату. Ви не побачите прискорення, роблячи це в GPU, тому що одне доповнення не компенсує зусиль з читання / запису пам'яті.
Другий термін, "обчислений зв'язаний", відноситься до проблем, коли кількість вказівок є великою порівняно з кількістю читання / запису пам'яті. Наприклад, розглянемо множення матриці: Кількість інструкцій буде O (n ^ 3), коли n - розмір матриці. У цьому випадку можна очікувати, що графічний процесор перевершить процесор за певним розміром матриці. Іншим прикладом може бути, коли багато складних тригонометричних обчислень (синус / косинус тощо) виконуються на елементах даних "мало".
Як правило: Ви можете припустити, що читання / запис одного елемента даних з "основного" пам'яті GPU має затримку близько 500 інструкцій ....
Отже, ще одним ключовим моментом для роботи графічних процесорів є локалізація даних : Якщо вам доведеться читати чи записувати дані (і в більшості випадків вам доведеться ;-)), то ви повинні переконатися, що дані зберігаються настільки ж близько, як можливо до ядер GPU. Таким чином, графічні процесори мають певні області пам'яті (їх називають "локальною пам'яттю" або "спільною пам'яттю"), які зазвичай мають розмір лише декілька КБ, але особливо ефективні для даних, які збираються залучатись до обчислення.
Отже, щоб ще раз наголосити на цьому: програмування GPU - це мистецтво, яке лише віддалено пов'язане з паралельним програмуванням на процесорі. Такі речі, як Threads in Java, з усією інфраструктурою паралельності тощо ThreadPoolExecutors
, ForkJoinPools
можуть створити враження, що вам просто потрібно якось розділити свою роботу і розподілити її між декількома процесорами. На графічному процесорі ви можете зіткнутися з проблемами на набагато нижчому рівні: Зайнятість, реєстраційний тиск, загальний тиск пам'яті, об'єм пам'яті ... лише декілька.
Однак, коли у вас є проблема, паралельна даних, пов'язана з обчисленнями для вирішення, GPU - це шлях.
Загальне зауваження: Ви спеціально просили CUDA. Але я настійно рекомендую вам також ознайомитися з OpenCL. Він має ряд переваг. Перш за все, це незалежний від постачальників відкритий галузевий стандарт, а також є реалізація OpenCL від AMD, Apple, Intel та NVIDIA. Крім того, існує набагато ширша підтримка OpenCL у світі Java. Єдиний випадок, коли я вважаю за краще використовувати CUDA - це коли ви хочете використовувати бібліотеки виконання CUDA, наприклад, CUFFT для FFT або CUBLAS для BLAS (матричні / векторні операції). Хоча існують підходи щодо надання подібних бібліотек для OpenCL, вони не можуть безпосередньо використовуватися з боку Java, якщо ви не створите власні прив'язки JNI для цих бібліотек.
Вам також може бути цікаво почути, що в жовтні 2012 року група OpenJDK HotSpot розпочала проект "Суматра": http://openjdk.java.net/projects/sumatra/ . Мета цього проекту - надати підтримку GPU безпосередньо в JVM, за підтримки JIT. Поточний стан та перші результати можна побачити у списку розсилки за адресою http://mail.openjdk.java.net/mailman/listinfo/sumatra-dev
Однак деякий час тому я зібрав деякі ресурси, пов’язані з "Java в GPU" взагалі. Я знову їх підсумую тут, не в конкретному порядку.
( Відмова : Я автор http://jcuda.org/ та http://jocl.org/ )
Переклад коду (байт) та генерація коду OpenCL:
https://github.com/aparapi/aparapi : Бібліотека з відкритим кодом, яку створює та активно підтримує AMD. У спеціальному класі "Ядро" можна перекрити конкретний метод, який слід виконувати паралельно. Байт-код цього методу завантажується під час виконання за допомогою власного зчитувача байтових кодів. Код переводиться в код OpenCL, який потім компілюється за допомогою компілятора OpenCL. Потім результат може бути виконаний на пристрої OpenCL, який може бути графічним процесором або процесором. Якщо компіляція в OpenCL неможлива (або немає OpenCL), код все одно буде виконуватися паралельно, використовуючи пул потоків.
https://github.com/pcpratts/rootbeer1 : Бібліотека з відкритим кодом для перетворення частин Java в програми CUDA. Він пропонує спеціалізовані інтерфейси, які можуть бути реалізовані для вказівки на те, що певний клас повинен виконуватися на GPU. На відміну від Aparapi, він намагається автоматично серіалізувати "відповідні" дані (тобто повну відповідну частину об'єктного графіка!) У подання, яке підходить для GPU.
https://code.google.com/archive/p/java-gpu/ : Бібліотека для перекладеного кодованого коду Java (з деякими обмеженнями) в код CUDA, який потім компілюється в бібліотеку, яка виконує код у GPU. Бібліотека була розроблена в контексті кандидатської дисертації, яка містить глибоку довідкову інформацію про процес перекладу.
https://github.com/ochafik/ScalaCL : Прив'язки Scala для OpenCL. Дозволяє обробляти спеціальні колекції Scala паралельно з OpenCL. Функції, які викликаються елементами колекцій, можуть бути звичайними функціями Scala (з деякими обмеженнями), які потім переводяться у ядра OpenCL.
Розширення мови
http://www.ateji.com/px/index.html : Мовне розширення для Java, яке дозволяє паралельні конструкції (наприклад, паралель для циклів, стиль OpenMP), які потім виконуються на GPU з OpenCL. На жаль, цей дуже перспективний проект більше не підтримується.
http://www.habanero.rice.edu/Publications.html (JCUDA): Бібліотека, яка може перевести спеціальний код Java (званий JCUDA-код) у код Java та CUDA-C, який потім може бути скомпільований і виконаний на GPU. Однак, схоже, бібліотека не є загальнодоступною.
https://www2.informatik.uni-erlangen.de/EN/research/JavaOpenMP/index.html : розширення мови Java для конструкцій OpenMP, із заднім числом CUDA
Java OpenCL / CUDA обов'язкові бібліотеки
https://github.com/ochafik/JavaCL : Прив'язки Java для OpenCL: Об'єктно-орієнтована бібліотека OpenCL, заснована на автоматично сформованих прив'язках низького рівня
http://jogamp.org/jocl/www/ : Прив'язки Java для OpenCL: об'єктно-орієнтована бібліотека OpenCL, заснована на автоматично створених прив'язках низького рівня
http://www.lwjgl.org/ : Прив’язки Java для OpenCL: Автоматично створені прив'язки низького рівня та об'єктно-орієнтовані класи зручності
http://jocl.org/ : Прив'язки Java для OpenCL: Прив'язки низького рівня, які є відображенням оригіналу OpenCL API 1: 1.
http://jcuda.org/ : Прив'язки Java для CUDA: Прив'язки низького рівня, які є відображенням оригінального API CUDA 1: 1.
Різне
http://sourceforge.net/projects/jopencl/ : Прив'язки Java для OpenCL. Здається, це більше не підтримується з 2010 року
http://www.hoopoe-cloud.com/ : Прив'язки Java для CUDA. Здається, це більше не підтримується