私は、ViennaCLの開発過程で得られた経験を要約しようとします。ViennaCLでは、CUDAとOpenCLのバックエンドがあり、多くの計算カーネルのほぼ1対1の変換が行われています。あなたの質問から、ここでは主にGPUについて取り上げていると思います。
パフォーマンスの移植性。まず第一に、カーネルを一度書くだけですべてのハードウェアで効率的に実行されるという意味で、パフォーマンスポータブルカーネルのようなものはありません。OpenCLではサポートされていませんが、サポートされているハードウェアの範囲が広いため、CUDAでもそうではありません。CUDAでは、サポートされるハードウェアの範囲が狭いため、あまり明確ではありませんが、ここでも、少なくとも3つのハードウェアアーキテクチャ(フェルミ以前、フェルミ、ケプラー)を区別する必要があります。これらのパフォーマンスの変動により、カーネルがバッファコピーのように単純であっても、スレッドの編成方法や選択したワークグループサイズに応じて、20%のパフォーマンスの変動が容易に発生します。フェルミおよびフェルミ以前のGPUでは、CUDAで直接高速の行列-行列乗算カーネルを直接記述できることも言及する価値があるでしょう。一方、最新のKepler GPUの場合、CUBLASのパフォーマンスに近づけるためには、PTX擬似アセンブリ言語を使用する必要があります。したがって、CUDAのようなベンダーが管理する言語でさえ、ハードウェアの開発に対応するための問題があるようです。さらに、nvccを実行するとすべてのCUDAコードが静的にコンパイルされますが、これには-archフラグを介したバランス調整が多少必要ですが、OpenCLカーネルは実行時にジャストインタイムコンパイラからコンパイルされるため、原則的にカーネルを調整できます特定のコンピューティングデバイスの詳細まで。ただし、後者は非常に複雑であり、通常、コードが成熟し、経験が蓄積するにつれて、非常に魅力的なオプションになります。支払う価格は、ジャストインタイムコンパイルに必要なO(1)時間であり、特定の状況では問題になる可能性があります。OpenCL 2。
デバッグとプロファイリング。CUDAデバッグおよびプロファイリングツールは、GPGPUに最適です。AMDのツールも悪くありませんが、cuda-gdbやcuda-memcheckなどのgemは含まれていません。また、NVIDIAはGPGPU用の最も堅牢なドライバーとSDKを提供していますが、OpenCLとCUDAの両方で、バグではなく、システムのフリーズが例外であり、ルールではありません。おそらくここで説明する必要はないので、NVIDIAはCUDA 5.0以降を使用したOpenCLのデバッグとプロファイリングを提供しなくなりました。
アクセシビリティと利便性。特にCUDAコードはホストコードとかなりうまく統合されるため、最初のCUDAコードを起動して実行するのは非常に簡単です。(後で支払う価格については説明します。)Webには、最適化ガイドといくつかのライブラリーだけでなく、多くのチュートリアルがあります。OpenCLでは、かなりの初期化コードを調べてカーネルを文字列で記述する必要があるため、ソースをjit-compilerにフィードするときに実行中にコンパイルエラーを見つけるだけです。したがって、OpenCLで1つのコード/コンパイル/デバッグサイクルを実行するのに時間がかかるため、通常、この初期開発段階では生産性が低下します。
ソフトウェアライブラリの側面。前の項目はCUDAを支持していましたが、他のソフトウェアへの統合はOpenCLにとって大きなプラスです。共有OpenCLライブラリとリンクするだけでOpenCLを使用できます。CUDAでは、CUDAツールチェーン全体を使用可能にする必要があります。さらに悪いことに、nvccが機能するには正しいホストコンパイラを使用する必要があります。GCC 4.6以降でCUDA 4.2などを使用しようとしたことがある場合、機能させるのに苦労します。一般的に、CUDA SDKよりも新しいコンパイラを使用している場合、トラブルが発生する可能性があります。CMakeのようなビルドシステムへの統合は、頭痛の別の原因です(たとえば、PETScで十分な証拠を見つけることもできます)メーリングリスト)。これは、完全に制御できるマシンでは問題にならない場合がありますが、コードを配布するとすぐに、ソフトウェアスタックでユーザーが多少制限される状況に陥ります。つまり、CUDAを使用すると、お気に入りのホストコンパイラを自由に選択できなくなりますが、NVIDIAは、使用できるコンパイラを決定します。
その他の側面。CUDAはハードウェア(ワープなど)に少し近づいていますが、線形代数の私の経験では、それから大きな利益を得ることはめったにありません。CUDA用のソフトウェアライブラリは他にもいくつかありますが、より多くのライブラリが複数の計算バックエンドを使用しています。ViennaCL、VexCL、またはParalutionは、すべてOpenCLおよびCUDAバックエンドをサポートしていますが、他の分野のライブラリでも同様の傾向が見られます。
GPGPUはSilver Bulletではありません。GPGPUは、構造化された操作と計算が制限されたタスクに対して優れたパフォーマンスを提供することが示されています。ただし、逐次処理の割合が無視できないアルゴリズムの場合、GPGPUはAmdahlの法則を魔法のように克服することはできません。このような状況では、問題に対して適切ではない並列アルゴリズムをスローするのではなく、利用可能な最適なアルゴリズムの適切なCPU実装を使用する方が適切です。また、PCI-Expressは深刻なボトルネックであるため、GPUの節約がデータのやり取りのオーバーヘッドを補償できるかどうかを事前に確認する必要があります。
私の推薦。CUDAを検討してくださいと OpenCLのではなく、CUDA かをOpenCL。不必要に1つのプラットフォームに制限する必要はありませんが、代わりに両方の世界を最大限に活用します。私にとってうまくいくのは、CUDAで初期実装を設定し、デバッグし、プロファイリングしてから、単純な文字列置換によってOpenCLに移植することです。通常、この移植作業は時間の10%未満しか消費しませんが、他のハードウェアでも実行できるようになります。特定の状況でNVIDIA以外のハードウェアがどれだけ優れた性能を発揮できるか驚くかもしれません。何よりも、ライブラリ内の機能を可能な限り最大限に再利用することを検討してください。クイック&一部の機能のダーティな再実装は、CPUでのシングルスレッド実行で許容される場合が多く、大規模な並列ハードウェアではパフォーマンスが低下することがよくあります。理想的には、すべてをライブラリにオフロードでき、CUDA、OpenCL、またはその両方を内部で使用するかどうかを気にする必要はありません。個人的には、これから数年以内に依存したいもののためにベンダーロックコードを書くことを敢えてしないでしょうが、このイデオロギー的側面は別の議論に入るべきです。