私は、GPUベースの処理を高レベルで可能にするC++のライブラリ/拡張機能を検討してきました。私はGPUプログラミングの専門家ではありません。深く掘り下げたくありません。仮想関数を持つクラスで構成されるニューラルネットワークがあります。基本的に、GPUの割り当てを高レベルで行うライブラリが必要です。 GPUのほとんどの処理を行うGPU ++というシステムで論文を書いた人がいます。私は彼の論文だけでどこにもコードを見つけることができません。
誰もが同様のライブラリを知っていますか、それともGPU ++のコードを持っていますか? CUDAのようなライブラリは低すぎるため、ほとんどの操作を処理できません(少なくとも、すべてのプロセスとアルゴリズムを書き直さずに-これはしたくない)。
Thrustライブラリは、コンテナ、並列プリミティブ、およびアルゴリズムを提供します。この機能はすべて、STLに似た構文でうまくまとめられています。そのため、STLに精通していれば、単一のCUDAカーネルを作成することなく、Thrustのみを使用して実際にCUDAプログラム全体を作成できます。 クイックスタートガイドの簡単な例を見て、使用して作成できる高レベルプログラムの種類を確認してください。スラスト。
GPGPUプログラミング専用の高レベルのライブラリが多数あります。 CUDAおよび/またはOpenCLに依存しているため、賢明に選択する必要があります(CUDAベースのプログラムは、AMDのGPUで実行されません。 gpuocelot )。
NVIDIA website でCUDAライブラリの例を見つけることができます。
Thrustは、C++標準テンプレートライブラリ(STL)に似た並列アルゴリズムライブラリです。 Thrustの高レベルインターフェイスは、プログラマの生産性を大幅に向上させ、GPUとマルチコアCPU間のパフォーマンスの移植性を実現します。確立されたテクノロジー(CUDA、TBB、OpenMPなど)との相互運用性により、既存のソフトウェアとの統合が容易になります。
@ Ashwin が指摘したように、ThrustのSTLに似た構文により、CUDAプログラムを開発する際に広く選択されたライブラリになります。サンプルをざっと見てみると、このライブラリを使用することにした場合に作成するコードの種類がわかります。 NVIDIAのWebサイトには、このライブラリの 主要機能 が記載されています。 ビデオプレゼンテーション (GTC 2012から)も利用できます。
CUBは、CUDAプログラミングモードのすべてのレイヤーに最新の再利用可能なソフトウェアコンポーネントを提供します。協調的なスレッドブロックプリミティブおよびCUDAカーネルプログラミング用のその他のユーティリティの柔軟なライブラリです。
並列ソート、プレフィックススキャン、リダクション、ヒストグラムなど、デバイス全体、ブロック全体、およびワープ全体の並列プリミティブを提供します。
オープンソースであり、 GitHub で利用できます。実装の観点からは高レベルではありません(CUDAカーネルで開発します)が、高レベルのアルゴリズムとルーチンを提供します。
このライブラリは主に機械学習に使用され、 式テンプレート に依存しています。
Eigen 3.3から、CUDAカーネル内でEigenのオブジェクトとアルゴリズムを使用できるようになりました。ただし、CUDAカーネル内で動的割り当てがトリガーされないようにするために、機能のサブセットのみがサポートされています。
OpenCL は、異種プラットフォーム(マルチコアCPU、GPUなど)をサポートするため、GPGPUコンピューティング以上のことを行うことに注意してください。
OpenACCアプリケーションプログラムインターフェイスは、ホストCPUから接続されたアクセラレータにオフロードされる標準C、C++、およびFortranのコードのループおよび領域を指定するコンパイラディレクティブのコレクションを記述し、オペレーティングシステム、ホストCPU、およびアクセラレータ間での移植性を提供します。
Boltは、異種コンピューティング向けに最適化されたC++テンプレートライブラリです。 Boltは、スキャン、リデュース、トランスフォーム、ソートなどの一般的なアルゴリズムの高性能ライブラリ実装を提供するように設計されています。 Boltインターフェースは、C++標準テンプレートライブラリ(STL)でモデル化されました。 STLに精通している開発者は、多くのBolt APIとカスタマイズ技術を認識しています。
Boost.Compute :as @ Kyle Lutz 前述のように、Boost.ComputeはSTLのような機能を提供しますOpenCLのインターフェース。これは公式のBoostライブラリではないことに注意してください(まだ)。
SkelCL 「最新の並列異種システムの軽減されたプログラミングのための高レベルの抽象化を提供するライブラリです」。このライブラリは skeleton programming に依存しており、詳細は research papers で見つけることができます。
これは実際にはこの質問の範囲内ではありませんが、他のプログラミング言語にも同じ種類のサポートがあります。
線形代数(たとえば)または他の特定の操作を行う必要がある場合、CUDAおよびOpenCL専用の数学ライブラリも利用できます(例 ViennaCL 、 [〜#〜] cublas [〜#〜] 、 [〜#〜] magma [〜#〜] など)。
また、これらのライブラリを使用しても、非常に具体的な計算を行う必要がある場合に低レベルの操作を行うことを妨げないことに注意してください。
最後に、C++標準ライブラリの将来について言及できます。並列処理のサポートを追加するための広範な作業がありました。これは まだ技術仕様 であり、GPUはAFAIK(Thrustの開発者であるNVIDIAのJared Hoberockが直接関与しているものの)に明示的に言及されていませんが、これを実現する意志は間違いなくそこにあります。
Boost.Compute を見てください。 _vector<T>
_ などのコンテナや transform()
や sort()
。
OpenCL に基づいて構築されており、NVIDIA、AMD、Intelを含むほとんどの最新のGPUおよびCPUで実行できます。
もう1つの高レベルライブラリは、 VexCL -OpenCL用のベクトル式テンプレートライブラリです。ベクトル操作の直感的な表記法を提供し、MIT license。
より高次元のコンテナと、カーネルコードでこれらのコンテナを渡して操作する機能を探している場合、私はここ数年、 ecuda APIを開発して自分の科学研究プロジェクトを支援しました(だから、それはペースを通過しました)。うまくいけば、必要なニッチを埋めることができます。使用方法の簡単な例(ここではC++ 11の機能を使用しますが、ecudaはC++ 11以前のコンパイラーでも問題なく動作します):
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <vector>
#include <ecuda/ecuda.hpp>
// kernel function
__global__
void calcColumnSums(
typename ecuda::matrix<double>::const_kernel_argument mat,
typename ecuda::vector<double>::kernel_argument vec
)
{
const std::size_t t = threadIdx.x;
auto col = mat.get_column(t);
vec[t] = ecuda::accumulate( col.begin(), col.end(), static_cast<double>(0) );
}
int main( int argc, char* argv[] )
{
// allocate 1000x1000 hardware-aligned device memory matrix
ecuda::matrix<double> deviceMatrix( 1000, 1000 );
// generate random values row-by-row and copy to matrix
std::vector<double> hostRow( 1000 );
for( std::size_t i = 0; i < 1000; ++i ) {
for( double& x : hostRow ) x = static_cast<double>(Rand())/static_cast<double>(Rand_MAX);
ecuda::copy( hostRow.begin(), hostRow.end(), deviceMatrix[i].begin() );
}
// allocate device memory for column sums
ecuda::vector<double> deviceSums( 1000 );
CUDA_CALL_KERNEL_AND_WAIT(
calcColumnSums<<<1,1000>>>( deviceMatrix, deviceSums )
);
// copy columns sums to Host and print
std::vector<double> hostSums( 1000 );
ecuda::copy( deviceSums.begin(), deviceSums.end(), hostSums.begin() );
std::cout << "SUMS =";
for( const double& x : hostSums ) std::cout << " " << std::fixed << x;
std::cout << std::endl;
return 0;
}
できるだけ直感的になるように書きました(通常はstd ::をecuda ::に置き換えるのと同じくらい簡単です)。 STLを知っている場合、ecudaはCUDAベースのC++拡張機能が論理的に期待することを行う必要があります。
Cpp-openclプロジェクトは、開発者がGPUを簡単にプログラミングできるようにする方法を提供します。 OpenCLを使用する代わりに、C++でGPUにデータ並列処理を直接実装できます。
http://dimitri-christodoulou.blogspot.com/2014/02/implement-data-parallelism-on-gpu.html をご覧ください
そしてソースコード: https://github.com/dimitrs/cpp-opencl
以下の例を参照してください。 parallel_for_eachラムダ関数のコードはGPUで実行され、残りはすべてCPUで実行されます。より具体的には、「square」関数は、CPU(std :: transformの呼び出しを介して)とGPU(compute :: parallel_for_eachの呼び出しを介して)の両方で実行されます。
#include <vector>
#include <stdio.h>
#include "ParallelForEach.h"
template<class T>
T square(T x)
{
return x * x;
}
void func() {
std::vector<int> In {1,2,3,4,5,6};
std::vector<int> OutGpu(6);
std::vector<int> OutCpu(6);
compute::parallel_for_each(In.begin(), In.end(), OutGpu.begin(), [](int x){
return square(x);
});
std::transform(In.begin(), In.end(), OutCpu.begin(), [](int x) {
return square(x);
});
//
// Do something with OutCpu and OutGpu …..........
//
}
int main() {
func();
return 0;
}
新しい OpenMP バージョン4には、アクセラレータオフロードのサポートが含まれています。
AFAIK GPUはアクセラレータと見なされます。
C++ AMPはあなたが探している答えです。