Her şeyden önce, CUDA'nın otomatik olarak hesaplamaları daha hızlı hale getirmeyeceğinin farkında olmalısınız. GPU programlama bir sanattır çünkü bir taraftan, ve çok bunu elde etmek için zorlu, çok olabilir sağ . Öte yandan, GPU'lar sadece belirli hesaplama türleri için çok uygun olduğu için .
Bu kafa karıştırıcı gelebilir, çünkü temel olarak GPU'daki herhangi bir şeyi hesaplayabilirsiniz . Kilit nokta, elbette, iyi bir hızlanma elde edip etmeyeceğinizdir. Buradaki en önemli sınıflandırma, bir sorunun görev paralel veya veri paralel olup olmadığıdır . Birincisi, kabaca konuşmak gerekirse, birkaç iş parçacığının az çok bağımsız olarak kendi görevleri üzerinde çalıştığı sorunları ifade eder. İkincisi, birçok iş parçacığının aynı şeyi yaptığı, ancak verilerin farklı kısımlarındaki sorunları ifade eder .
İkincisi, GPU'ların iyi olduğu bir tür problemdir: Birçok çekirdeğe sahiptir ve tüm çekirdekler aynı şeyi yapar, ancak giriş verilerinin farklı bölümlerinde çalışır.
"Basit bir matematik ama büyük miktarda veri" olduğunu söyledi. Her ne kadar bu, mükemmel bir veri-paralel problemi gibi görünse de ve dolayısıyla bir GPU için uygun olduğu gibi, göz önünde bulundurulması gereken başka bir husus daha vardır: GPU'lar teorik hesaplama gücü (FLOPS, Saniyede Kayan Nokta İşlemleri) açısından gülünç derecede hızlıdır. Ancak bunlar genellikle bellek bant genişliği tarafından kısıtlanır.
Bu, sorunların başka bir sınıflandırmasına yol açar. Yani problemlerin hafızaya bağlı mı yoksa hesaplamalara mı bağlı olduğu .
Birincisi, her bir veri elemanı için yapılan talimat sayısının düşük olduğu problemleri ifade eder. Örneğin, paralel bir vektör eklemeyi düşünün: İki veri öğesini okumanız , ardından tek bir ekleme yapmanız ve toplamı sonuç vektörüne yazmanız gerekir. GPU'da bunu yaparken bir hızlanma görmezsiniz, çünkü tek bir ekleme belleği okuma / yazma çabalarını telafi etmez.
İkinci terim olan "hesaplama sınırı", okuma / yazma bellek sayısına kıyasla talimat sayısının yüksek olduğu problemleri ifade eder. Örneğin, bir matris çarpımı düşünün: n matrisin boyutu olduğunda, talimat sayısı O (n ^ 3) olacaktır. Bu durumda, GPU'nun belirli bir matris boyutunda bir CPU'dan daha iyi performans göstermesi beklenebilir. Başka bir örnek, "az" veri elemanları üzerinde birçok karmaşık trigonometrik hesaplamanın (sinüs / kosinüs vb.) Gerçekleştirilmesi olabilir.
Genel bir kural olarak: "Ana" GPU bellekten bir veri öğesi okumanın / yazmanın yaklaşık 500 komut gecikmesi olduğunu varsayabilirsiniz.
Bu nedenle, GPU'ların performansı için bir başka önemli nokta veri konumudur : Veri okumak veya yazmak zorundaysanız (ve çoğu durumda ;-) gerekir), o zaman verilerin yakın tutulduğundan emin olmalısınız GPU çekirdekleri için mümkün. Bu nedenle GPU'lar, genellikle yalnızca birkaç KB boyutunda olan, ancak özellikle bir hesaplamaya dahil olmak üzere olan veriler için etkili olan belirli bellek alanlarına ("yerel bellek" veya "paylaşılan bellek" olarak adlandırılır) sahiptir.
Bunu tekrar vurgulamak için: GPU programlama bir sanattır, bu sadece CPU'daki paralel programlamayla uzaktan ilgilidir. Java'daki Threads gibi şeyler, vb.Gibi eşzamanlılık altyapısı vb. ThreadPoolExecutors
, ForkJoinPools
İşinizi bir şekilde bölmeniz ve birkaç işlemci arasında dağıtmanız gerektiği izlenimini verebilir. GPU'da, çok daha düşük bir seviyede zorluklarla karşılaşabilirsiniz: Doluluk, kayıt baskısı, paylaşılan bellek basıncı, bellek birleştirme ... sadece birkaçını belirtmek için.
Bununla birlikte, çözülecek veri-paralel, bilgi işlemle ilgili bir sorununuz olduğunda, GPU gitmenin yoludur.
Genel bir açıklama: Özellikle CUDA'yı istediniz. Ancak OpenCL'ye de göz atmanızı şiddetle tavsiye ederim. Birkaç avantajı vardır. Her şeyden önce, satıcıdan bağımsız, açık endüstri standardıdır ve AMD, Apple, Intel ve NVIDIA tarafından OpenCL uygulamaları vardır. Ayrıca, Java dünyasında OpenCL için çok daha geniş bir destek var. CUDA'ya yerleşmeyi tercih ettiğim tek durum, FFT için CUFFT veya BLAS için CUBLAS (Matris / Vektör işlemleri) gibi CUDA çalışma zamanı kitaplıklarını kullanmak istediğinizde. Her ne kadar OpenCL için benzer kütüphaneler sağlamaya yönelik yaklaşımlar olsa da, bu kütüphaneler için kendi JNI bağlarınızı oluşturmadığınız sürece bunlar doğrudan Java tarafından kullanılamaz.
Ekim 2012'de OpenJDK HotSpot grubunun "Sumatra" projesini başlattığını duymak da ilginç olabilir: http://openjdk.java.net/projects/sumatra/ . Bu projenin amacı , JIT desteği ile doğrudan JVM'de GPU desteği sağlamaktır . Mevcut durum ve ilk sonuçlar http://mail.openjdk.java.net/mailman/listinfo/sumatra-dev adresindeki posta listelerinde görülebilir.
Ancak, bir süre önce, genel olarak "GPU'da Java" ile ilgili bazı kaynaklar topladım. Bunları burada tekrar, belirli bir sırayla özetleyeceğim.
( Feragatname : http://jcuda.org/ ve http://jocl.org/ yazarıyım )
(Byte) kod çevirisi ve OpenCL kod üretimi:
https://github.com/aparapi/aparapi : AMD tarafından oluşturulan ve aktif olarak bakımı yapılan açık kaynaklı bir kütüphane. Özel bir "Çekirdek" sınıfında, paralel olarak yürütülmesi gereken belirli bir yöntemi geçersiz kılabilir. Bu yöntemin bayt kodu çalışma zamanında kendi bayt kodu okuyucu kullanılarak yüklenir. Kod, daha sonra OpenCL derleyicisi kullanılarak derlenen OpenCL koduna çevrilir. Sonuç daha sonra GPU veya CPU olabilecek OpenCL cihazında yürütülebilir. OpenCL derlemesi mümkün değilse (veya OpenCL mevcut değilse), kod yine de bir Thread Pool kullanılarak paralel olarak yürütülür.
https://github.com/pcpratts/rootbeer1 : Java'nın parçalarını CUDA programlarına dönüştürmek için açık kaynaklı bir kütüphane. GPU'da belirli bir sınıfın yürütülmesi gerektiğini belirtmek için uygulanabilecek özel arayüzler sunar. Aparapi'nin aksine, "ilgili" verileri (yani, nesne grafiğinin tüm ilgili kısmını!) GPU için uygun bir gösterime otomatik olarak serileştirmeye çalışır.
https://code.google.com/archive/p/java-gpu/ : Ek açıklamalı Java kodunu (bazı sınırlamalarla) CUDA koduna çevirmek için kullanılan ve daha sonra GPU'daki kodu çalıştıran bir kütüphaneye derlenen bir kütüphane. Kütüphane, çeviri süreci hakkında derinlemesine bilgi içeren bir doktora tezi bağlamında geliştirilmiştir.
https://github.com/ochafik/ScalaCL : OpenCL için Scala bağlamaları. Özel Scala koleksiyonlarının OpenCL ile paralel işlenmesini sağlar. Koleksiyon öğelerinde çağrılan işlevler, daha sonra OpenCL çekirdeklerine çevrilen olağan Scala işlevleri (bazı sınırlamalarla) olabilir.
Dil uzantıları
http://www.ateji.com/px/index.html : Java için, daha sonra OpenCL ile GPU'da yürütülen paralel yapılara (ör. döngüler için paralel, OpenMP stili) izin veren bir dil uzantısı. Ne yazık ki, bu çok umut verici proje artık sürdürülmüyor.
http://www.habanero.rice.edu/Publications.html (JCUDA): Özel Java Kodunu (JCUDA kodu olarak adlandırılır) Java ve CUDA-C koduna çevirebilen ve daha sonra derlenip yürütülebilen bir kütüphane GPU. Ancak, kütüphane kamuya açık görünmüyor.
https://www2.informatik.uni-erlangen.de/EN/research/JavaOpenMP/index.html : CUDA arka ucuna sahip OpenMP yapıları için Java dili uzantısı
Java OpenCL / CUDA bağlama kitaplıkları
https://github.com/ochafik/JavaCL : OpenCL için Java bağlamaları: Otomatik oluşturulan düşük düzeyli bağlamaları temel alan nesne tabanlı bir OpenCL kütüphanesi
http://jogamp.org/jocl/www/ : OpenCL için Java bağları: Otomatik oluşturulan düşük düzeyli bağlamaları temel alan nesne tabanlı bir OpenCL kütüphanesi
http://www.lwjgl.org/ : OpenCL için Java bağları: Otomatik oluşturulan düşük düzey bağlamaları ve nesneye yönelik uygunluk sınıfları
http://jocl.org/ : OpenCL için Java ciltleri: Orijinal OpenCL API'sinin 1: 1 eşlemesi olan düşük düzeyli ciltlemeler
http://jcuda.org/ : CUDA için Java ciltleri: Orijinal CUDA API'sinin 1: 1 eşlemesi olan düşük düzeyli ciltlemeler
Çeşitli
http://sourceforge.net/projects/jopencl/ : OpenCL için Java bağlamaları. 2010'dan beri artık bakım yapılmıyor gibi görünüyor
http://www.hoopoe-cloud.com/ : CUDA için Java bağları. Artık bakım yapılmıyor gibi görünüyor