Pertama-tama, Anda harus menyadari fakta bahwa CUDA tidak akan secara otomatis membuat perhitungan lebih cepat. Di satu sisi, karena pemrograman GPU adalah seni, dan bisa sangat, sangat menantang untuk memperbaikinya . Di sisi lain, karena GPU hanya cocok untuk jenis komputasi tertentu .
Ini mungkin terdengar membingungkan, karena pada dasarnya Anda dapat menghitung apa pun di GPU. Kuncinya adalah, tentu saja, apakah Anda akan mencapai kecepatan yang baik atau tidak. Klasifikasi paling penting di sini adalah apakah suatu masalah adalah tugas paralel atau data paralel . Yang pertama merujuk, secara kasar, ke masalah di mana beberapa utas sedang mengerjakan tugas mereka sendiri, kurang lebih secara mandiri. Yang kedua mengacu pada masalah di mana banyak utas melakukan hal yang sama - tetapi pada bagian data yang berbeda.
Yang terakhir adalah jenis masalah yang dimiliki GPU dengan baik: GPU memiliki banyak core, dan semua core melakukan hal yang sama, tetapi beroperasi pada bagian input data yang berbeda.
Anda menyebutkan bahwa Anda memiliki "matematika sederhana tetapi dengan sejumlah besar data". Meskipun ini mungkin terdengar seperti masalah paralel-data yang sempurna dan karenanya cocok untuk GPU, ada aspek lain yang perlu dipertimbangkan: GPU sangat cepat dalam hal kekuatan komputasi teoretis (FLOPS, Operasi Titik Apung Per Detik). Tetapi mereka sering dibatasi oleh bandwidth memori.
Ini mengarah pada klasifikasi masalah lain. Yaitu apakah masalah terikat memori atau terikat komputasi .
Yang pertama mengacu pada masalah di mana jumlah instruksi yang dilakukan untuk setiap elemen data rendah. Misalnya, pertimbangkan penambahan vektor paralel: Anda harus membaca dua elemen data, lalu melakukan penambahan tunggal, dan kemudian menulis jumlahnya ke dalam vektor hasil. Anda tidak akan melihat speedup ketika melakukan ini pada GPU, karena penambahan tunggal tidak mengimbangi upaya membaca / menulis memori.
Istilah kedua, "compute bound", mengacu pada masalah di mana jumlah instruksi tinggi dibandingkan dengan jumlah memori yang dibaca / ditulis. Sebagai contoh, pertimbangkan perkalian matriks: Jumlah instruksi akan menjadi O (n ^ 3) ketika n adalah ukuran dari matriks. Dalam hal ini, orang dapat berharap bahwa GPU akan mengungguli CPU pada ukuran matriks tertentu. Contoh lain dapat terjadi ketika banyak perhitungan trigonometri kompleks (sinus / cosinus dll) dilakukan pada "beberapa" elemen data.
Sebagai aturan praktis: Anda dapat berasumsi bahwa membaca / menulis satu elemen data dari memori GPU "utama" memiliki latensi sekitar 500 instruksi ....
Oleh karena itu, titik kunci lain untuk kinerja GPU adalah lokalitas data : Jika Anda harus membaca atau menulis data (dan dalam kebanyakan kasus, Anda harus ;-)), maka Anda harus memastikan bahwa data disimpan sedekat mungkin dengan mungkin untuk core GPU. GPU dengan demikian memiliki area memori tertentu (disebut "memori lokal" atau "memori bersama") yang biasanya hanya berukuran beberapa KB, tetapi sangat efisien untuk data yang akan terlibat dalam perhitungan.
Jadi untuk menekankan ini lagi: Pemrograman GPU adalah seni, yang hanya terkait jarak jauh dengan pemrograman paralel pada CPU. Hal-hal seperti Threads in Java, dengan semua infrastruktur konkurensi seperti ThreadPoolExecutors
, ForkJoinPools
dll. Mungkin memberi kesan bahwa Anda hanya perlu membagi pekerjaan Anda dan mendistribusikannya di antara beberapa prosesor. Pada GPU, Anda mungkin menghadapi tantangan pada level yang jauh lebih rendah: Hunian, tekanan register, tekanan memori bersama, penggabungan memori ... hanya untuk beberapa nama.
Namun, ketika Anda memiliki masalah paralel-data, komputasi-terikat untuk dipecahkan, GPU adalah cara untuk pergi.
Komentar umum: Anda secara khusus meminta CUDA. Tapi saya sangat menyarankan Anda untuk melihat-lihat OpenCL. Ini memiliki beberapa keunggulan. Pertama-tama, ini adalah standar industri terbuka yang independen terhadap vendor, dan ada implementasi OpenCL oleh AMD, Apple, Intel dan NVIDIA. Selain itu, ada dukungan yang jauh lebih luas untuk OpenCL di dunia Java. Satu-satunya kasus di mana saya lebih suka menerima CUDA adalah ketika Anda ingin menggunakan pustaka runtime CUDA, seperti CUFFT untuk FFT atau CUBLAS untuk BLAS (operasi Matriks / Vektor). Meskipun ada pendekatan untuk menyediakan pustaka yang serupa untuk OpenCL, mereka tidak dapat langsung digunakan dari sisi Java, kecuali jika Anda membuat binding JNI Anda sendiri untuk pustaka ini.
Anda juga mungkin tertarik mendengarnya pada bulan Oktober 2012, grup OpenJDK HotSpot memulai proyek "Sumatra": http://openjdk.java.net/projects/sumatra/ . Tujuan dari proyek ini adalah untuk memberikan dukungan GPU langsung di JVM, dengan dukungan dari JIT. Status saat ini dan hasil pertama dapat dilihat di milis mereka di http://mail.openjdk.java.net/mailman/listinfo/sumatra-dev
Namun, beberapa waktu yang lalu, saya mengumpulkan beberapa sumber yang terkait dengan "Java on the GPU" secara umum. Saya akan meringkas ini lagi di sini, tanpa urutan tertentu.
( Penafian : Saya penulis http://jcuda.org/ dan http://jocl.org/ )
(Byte) terjemahan kode dan pembuatan kode OpenCL:
https://github.com/aparapi/aparapi : Perpustakaan open-source yang dibuat dan dikelola secara aktif oleh AMD. Dalam kelas "Kernel" khusus, seseorang dapat mengganti metode tertentu yang harus dijalankan secara paralel. Kode byte dari metode ini dimuat pada saat runtime menggunakan bytecode reader sendiri. Kode tersebut diterjemahkan ke dalam kode OpenCL, yang kemudian dikompilasi menggunakan kompiler OpenCL. Hasilnya kemudian dapat dieksekusi pada perangkat OpenCL, yang mungkin berupa GPU atau CPU. Jika kompilasi ke OpenCL tidak dimungkinkan (atau tidak ada OpenCL tersedia), kode masih akan dieksekusi secara paralel, menggunakan Thread Pool.
https://github.com/pcpratts/rootbeer1 : Perpustakaan open-source untuk mengubah bagian Jawa menjadi program CUDA. Ini menawarkan antarmuka khusus yang dapat diimplementasikan untuk menunjukkan bahwa kelas tertentu harus dijalankan pada GPU. Berbeda dengan Aparapi, ia mencoba untuk membuat serialisasi data "relevan" secara otomatis (yaitu, bagian relevan yang lengkap dari grafik objek!) Ke dalam representasi yang sesuai untuk GPU.
https://code.google.com/archive/p/java-gpu/ : Perpustakaan untuk menerjemahkan kode Java beranotasi (dengan beberapa batasan) menjadi kode CUDA, yang kemudian dikompilasi ke perpustakaan yang mengeksekusi kode pada GPU. Perpustakaan dikembangkan dalam konteks tesis PhD, yang berisi informasi latar belakang mendalam tentang proses penerjemahan.
https://github.com/ochafik/ScalaCL : Scala binding untuk OpenCL. Mengizinkan koleksi Scala khusus diproses secara paralel dengan OpenCL. Fungsi-fungsi yang dipanggil pada elemen-elemen koleksi dapat berupa fungsi Scala biasa (dengan beberapa batasan) yang kemudian diterjemahkan ke dalam kernel OpenCL.
Ekstensi bahasa
http://www.ateji.com/px/index.html : Ekstensi bahasa untuk Java yang memungkinkan konstruksi paralel (misalnya paralel untuk loop, gaya OpenMP) yang kemudian dieksekusi pada GPU dengan OpenCL. Sayangnya, proyek yang sangat menjanjikan ini tidak lagi dipertahankan.
http://www.habanero.rice.edu/Publications.html (JCUDA): Perpustakaan yang dapat menerjemahkan Kode Java khusus (disebut kode JCUDA) menjadi kode Java- dan CUDA-C, yang kemudian dapat dikompilasi dan dieksekusi pada GPU. Namun, perpustakaan sepertinya tidak tersedia untuk umum.
https://www2.informatik.uni-erlangen.de/EN/research/JavaOpenMP/index.html : Ekstensi bahasa Java untuk konstruksi OpenMP, dengan backend CUDA
Java OpenCL / CUDA binding libraries
https://github.com/ochafik/JavaCL : Java bindings untuk OpenCL: Pustaka OpenCL yang berorientasi objek, berdasarkan pada binding tingkat rendah yang dihasilkan secara otomatis
http://jogamp.org/jocl/www/ : Java binding untuk OpenCL: Pustaka OpenCL yang berorientasi objek, berdasarkan binding level rendah yang dihasilkan secara otomatis
http://www.lwjgl.org/ : Java bindings untuk OpenCL: Bindings level rendah yang dihasilkan secara otomatis dan kelas kenyamanan berorientasi objek
http://jocl.org/ : Java bindings untuk OpenCL: binding tingkat rendah yang merupakan pemetaan 1: 1 dari API OpenCL asli
http://jcuda.org/ : Java bindings untuk CUDA: binding level rendah yang merupakan pemetaan 1: 1 dari API CUDA asli
Lain-lain
http://sourceforge.net/projects/jopencl/ : Java bindings untuk OpenCL. Tampaknya tidak lagi dipertahankan sejak 2010
http://www.hoopoe-cloud.com/ : Java bindings untuk CUDA. Tampaknya tidak lagi dipertahankan