まず第一に、CUDAが自動的に計算を高速化しないという事実に注意する必要があります。一方では、GPUプログラミングは芸術であり、正しく理解することは非常に困難です。一方、GPUは特定の種類の計算にのみ適しているためです。
基本的にGPUで何でも計算できるので、これは混乱するように聞こえるかもしれません。もちろん、重要なポイントは、十分なスピードアップを達成できるかどうかです。ここで最も重要な分類は、問題がタスク並列かデータ並列かです。最初の問題は、おおまかに言って、複数のスレッドが多かれ少なかれ独立して独自のタスクに取り組んでいる問題を指します。2番目の問題は、多くのスレッドがすべて同じことを行っているが、データの異なる部分で発生する問題を示しています。
後者は、GPUが得意とする種類の問題です。GPUには多くのコアがあり、すべてのコアは同じように動作しますが、入力データの異なる部分で動作します。
「単純な数学ですが、大量のデータがある」とのことですが、これは完全にデータ並列の問題のように聞こえるため、GPUに適しているように思われますが、考慮すべきもう1つの側面があります。ただし、メモリ帯域幅によって抑制されることがよくあります。
これは問題の別の分類につながります。つまり、問題がメモリに制限されているか、計算に制限されているか。
最初の問題は、各データ要素に対して実行される命令の数が少ないという問題に関係しています。たとえば、並列ベクトルの加算を考えてみましょう。2つのデータ要素を読み取ってから、1つの加算を実行し、その合計を結果のベクトルに書き込む必要があります。GPUでこれを行うと、メモリの読み取り/書き込みの労力が1回の追加で補正されないため、スピードアップは見られません。
2番目の用語である「計算限界」は、メモリの読み取り/書き込みの数と比較して、命令の数が多い問題を指します。たとえば、行列の乗算を考えます。nが行列のサイズの場合、命令の数はO(n ^ 3)になります。この場合、GPUは特定のマトリックスサイズでCPUよりも優れた性能を発揮することが期待できます。別の例としては、「少数の」データ要素に対して多くの複雑な三角関数計算(サイン/コサインなど)が実行される場合があります。
目安として、「メイン」GPUメモリからの1つのデータ要素の読み取り/書き込みには、約500命令のレイテンシがあると想定できます。
したがって、GPUのパフォーマンスのもう1つの重要なポイントはデータの局所性です。データの読み取りまたは書き込みが必要な場合(ほとんどの場合、;-)が必要になります)、データができるだけ近くに保たれていることを確認する必要があります。 GPUコアで可能です。したがって、GPUには特定のメモリ領域(「ローカルメモリ」または「共有メモリ」と呼ばれます)があり、通常はサイズが数KBですが、計算に関与するデータに対して特に効率的です。
したがって、これを強調しておきます。GPUプログラミングは芸術であり、CPUでの並列プログラミングにリモートでのみ関連しています。以下のようなすべての並行処理インフラストラクチャを使用してJavaのスレッド、のようなものThreadPoolExecutors
、ForkJoinPools
などはあなただけ何とか自分の仕事を分割し、複数のプロセッサ間でそれを分配しなければならないという印象を与えるかもしれません。GPUでは、占有率、レジスターのプレッシャー、共有メモリーのプレッシャー、メモリーの結合など、はるかに低いレベルの課題が発生する場合があります。
ただし、解決すべきデータ並列の計算限界の問題がある場合は、GPUが適しています。
総論:あなたは特にCUDAを求めました。ただし、OpenCLも確認することを強くお勧めします。これにはいくつかの利点があります。まず第一に、これはベンダーに依存しないオープンな業界標準であり、AMD、Apple、Intel、NVIDIAによるOpenCLの実装があります。さらに、Javaの世界ではOpenCLのサポートが大幅に拡大しています。CUDAに落ち着く唯一のケースは、FFTのCUFFTやBLAS(行列/ベクトル演算)のCUBLASなどのCUDAランタイムライブラリを使用する場合です。OpenCLに同様のライブラリーを提供するためのアプローチはありますが、これらのライブラリーに対して独自のJNIバインディングを作成しない限り、Java側から直接使用することはできません。
また、2012年10月にOpenJDK HotSpotグループがプロジェクト「Sumatra」を開始したと聞いて興味深いかもしれません:http : //openjdk.java.net/projects/sumatra/。このプロジェクトの目標は、JITのサポートにより、JVMでGPUサポートを直接提供することです。現在のステータスと最初の結果は、http://mail.openjdk.java.net/mailman/listinfo/sumatra-devのメーリングリストで確認できます。
しかし、少し前に、「GPU上のJava」全般に関連するいくつかのリソースを収集しました。これらをここでもう一度まとめますが、順不同です。
(免責事項:私はhttp://jcuda.org/およびhttp://jocl.org/の作成者です)
(バイト)コード変換とOpenCLコード生成:
https://github.com/aparapi/aparapi:AMDによって作成され、積極的に維持されているオープンソースライブラリ。特別な「カーネル」クラスでは、並行して実行する必要がある特定のメソッドをオーバーライドできます。このメソッドのバイトコードは、独自のバイトコードリーダーを使用して実行時に読み込まれます。コードはOpenCLコードに変換され、OpenCLコンパイラを使用してコンパイルされます。その後、結果はOpenCLデバイス(GPUまたはCPU)で実行できます。OpenCLへのコンパイルができない(またはOpenCLが利用できない)場合でも、コードはスレッドプールを使用して並行して実行されます。
https://github.com/pcpratts/rootbeer1:Javaの一部をCUDAプログラムに変換するためのオープンソースライブラリ。特定のクラスをGPUで実行する必要があることを示すために実装できる専用インターフェースを提供します。Aparapiとは対照的に、「関連する」データ(つまり、オブジェクトグラフの完全な関連部分!)をGPUに適した表現に自動的にシリアル化しようとします。
https://code.google.com/archive/p/java-gpu/:注釈付きのJavaコード(いくつかの制限付き)をCUDAコードに変換するためのライブラリ。CUDAコードは、GPUでコードを実行するライブラリにコンパイルされます。ライブラリは、翻訳プロセスに関する深い背景情報が含まれている博士論文のコンテキストで開発されました。
https://github.com/ochafik/ScalaCL:OpenCLの Scalaバインディング。特別なScalaコレクションをOpenCLと並行して処理できるようにします。コレクションの要素で呼び出される関数は、通常のScala関数(いくつかの制限付き)であり、OpenCLカーネルに変換されます。
言語拡張
http://www.ateji.com/px/index.html:Java用の言語拡張機能であり、並列構造(たとえば、並列forループ、OpenMPスタイル)をOpenCLを使用してGPUで実行できます。残念ながら、この非常に有望なプロジェクトはもはや維持されていません。
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:OpenMPコンストラクト用のJava言語拡張、CUDAバックエンドを使用
Java OpenCL / CUDAバインディングライブラリ
https://github.com/ochafik/JavaCL:OpenCLの Javaバインディング:自動生成された低レベルのバインディングに基づくオブジェクト指向のOpenCLライブラリ
http://jogamp.org/jocl/www/:OpenCLの Javaバインディング:自動生成された低レベルのバインディングに基づくオブジェクト指向のOpenCLライブラリ
http://www.lwjgl.org/:OpenCLの Javaバインディング:自動生成された低レベルのバインディングとオブジェクト指向の便利なクラス
http://jocl.org/:OpenCLの Javaバインディング:元のOpenCL APIの1:1マッピングである低レベルのバインディング
http://jcuda.org/:CUDAの Javaバインディング:元のCUDA APIの1:1マッピングである低レベルのバインディング
雑多
http://sourceforge.net/projects/jopencl/:OpenCLの Javaバインディング。2010年以降、保守されていないようです
http://www.hoopoe-cloud.com/:CUDAの Javaバインディング。もうメンテナンスされていないようです