CUDAとは何ですか?GPUの並列プログラミング

CUDAは、独自のGPU(グラフィックスプロセッシングユニット)での一般的なコンピューティングのためにNvidiaによって開発された並列コンピューティングプラットフォームおよびプログラミングモデルです。CUDAを使用すると、開発者は、計算の並列化可能な部分にGPUの能力を利用することで、計算集約型のアプリケーションを高速化できます。

OpenCLなどの他のGPU用APIが提案されており、AMDなどの他の企業から競合するGPUがありますが、CUDAとNvidia GPUの組み合わせは、ディープラーニングを含むいくつかのアプリケーション領域を支配し、いくつかの基盤となっています。世界最速のコンピューター。

グラフィックカードは、ほぼ間違いなくPCと同じくらい古いものです。つまり、1981年のIBMモノクロディスプレイアダプタをグラフィックカードと見なす場合です。1988年までに、ATI(最終的にAMDに買収された会社)から16ビットの2D VGAWonderカードを入手できるようになりました。1996年までに、3dfx Interactiveから3Dグラフィックアクセラレータを購入して、一人称シューティングゲームのQuakeをフルスピードで実行できるようになりました。

また、1996年にNvidiaは弱い製品で3Dアクセラレータ市場で競争しようとし始めましたが、それが進むにつれて学び、1999年にGPUと呼ばれる最初のグラフィックカードである成功したGeForce256を発表しました。当時、GPUを使用する主な理由はゲームでした。人々が数学、科学、工学にGPUを使用するようになったのは、後になってからでした。

CUDAの起源

2003年、Ian Buckが率いる研究者チームは、データ並列構造でCを拡張する最初の広く採用されたプログラミングモデルであるBrookを発表しました。Buckは後にNvidiaに加わり、GPUでの汎用コンピューティングのための最初の商用ソリューションであるCUDAの立ち上げを2006年に主導しました。

OpenCLとCUDA

CUDAのライバルであるOpenCLは、NvidiaGPUを搭載したIntel / AMD CPUに限定されないヘテロジニアスコンピューティングの標準を提供することを目的として、2009年にAppleとKhronosGroupによって発売されました。OpenCLはその一般性のために魅力的に聞こえますが、Nvidia GPUでのCUDAほどのパフォーマンスはなく、多くのディープラーニングフレームワークはそれをサポートしていないか、CUDAサポートがリリースされた後の考えとしてのみサポートしています。

CUDAパフォーマンスの向上

CUDAは、改良されたNvidia GPUとほぼ歩調を合わせて、長年にわたってその範囲を改善および拡大してきました。CUDAバージョン9.2以降、複数のP100サーバーGPUを使用すると、CPUの最大50倍のパフォーマンス向上を実現できます。V100(この図には示されていません)は、一部の負荷に対してさらに3倍高速です。前世代のサーバーGPUであるK80は、CPUの5倍から12倍のパフォーマンス向上を提供しました。

Nvidia

GPUによる速度の向上は、ハイパフォーマンスコンピューティングの時代の刻み目です。ムーアの法則が18か月ごとに2倍になると示唆した、時間の経過に伴うCPUのシングルスレッドパフォーマンスの向上は、チップメーカーが製造プロセス中のチップマスク解像度やチップ歩留まりのサイズ制限などの物理的制限に直面したため、年間10%に減速しました。実行時のクロック周波数の熱制限。

Nvidia

CUDAアプリケーションドメイン

Nvidia

CUDAおよびNvidiaGPUは、上の画像に図で要約されているように、高い浮動小数点コンピューティングパフォーマンスを必要とする多くの分野で採用されています。より包括的なリストは次のとおりです。

  1. 金融工学
  2. 気候、天気、海洋のモデリング
  3. データサイエンスと分析
  4. ディープラーニングと機械学習
  5. 防衛とインテリジェンス
  6. 製造/ AEC(建築、エンジニアリング、および建設):CADおよびCAE(計算流体力学、計算構造力学、設計と視覚化、および電子設計自動化を含む)
  7. メディアとエンターテインメント(アニメーション、モデリング、レンダリング、色補正と粒子管理、合成、仕上げと効果、編集、エンコードとデジタル配信、オンエアグラフィック、オンセット、レビュー、ステレオツール、天気予報グラフィックを含む)
  8. 医療画像処理
  9. オイルとガス
  10. 研究:高等教育とスーパーコンピューティング(計算化学と生物学、数値分析、物理学、科学的可視化を含む)
  11. 安全性と保安
  12. ツールと管理

ディープラーニングにおけるCUDA

ディープラーニングには、コンピューティング速度に対する大きなニーズがあります。たとえば、2016年にGoogle翻訳のモデルをトレーニングするために、GoogleBrainチームとGoogle翻訳チームはGPUを使用して1週間に数百回のTensorFlowを実行しました。彼らはその目的のためにNvidiaから2,000台のサーバーグレードGPUを購入しました。GPUがなければ、これらのトレーニングの実行は収束するのに1週間ではなく数ヶ月かかりました。これらのTensorFlow変換モデルの本番展開では、Googleは新しいカスタム処理チップであるTPU(テンソルプロセッシングユニット)を使用しました。

TensorFlowに加えて、Caffe2、CNTK、Databricks、H2O.ai、Keras、MXNet、PyTorch、Theano、Torchなど、他の多くのDLフレームワークがGPUサポートをCUDAに依存しています。ほとんどの場合、ディープニューラルネットワークの計算にはcuDNNライブラリを使用します。このライブラリは、ディープラーニングフレームワークのトレーニングにとって非常に重要であるため、特定のバージョンのcuDNNを使用するすべてのフレームワークは、同等のユースケースで基本的に同じパフォーマンス数値を示します。CUDAとcuDNNがバージョンごとに改善されると、新しいバージョンに更新されるすべてのディープラーニングフレームワークでパフォーマンスが向上します。フレームワークごとにパフォーマンスが異なる傾向があるのは、それらが複数のGPUおよび複数のノードにどれだけ適切に拡張できるかです。

CUDAプログラミング

Nvidia

CUDAツールキット

CUDA Toolkitには、ライブラリ、デバッグおよび最適化ツール、コンパイラ、ドキュメント、およびアプリケーションをデプロイするためのランタイムライブラリが含まれています。ディープラーニング、線形代数、信号処理、並列アルゴリズムをサポートするコンポーネントがあります。一般に、CUDAライブラリはNvidia GPUのすべてのファミリをサポートしますが、ディープラーニングトレーニングワークロードのP100よりも3倍高速なV100などの最新世代で最高のパフォーマンスを発揮します。必要なアルゴリズムが適切なライブラリに実装されている限り、1つ以上のライブラリを使用するのがGPUを利用する最も簡単な方法です。

Nvidia

CUDAディープラーニングライブラリ

ディープラーニングの分野には、3つの主要なGPUアクセラレーションライブラリがあります。cuDNNは、ほとんどのオープンソースディープラーニングフレームワークのGPUコンポーネントとして前述しました。Nvidiaの高性能ディープラーニング推論オプティマイザーおよびランタイムであるTensorRT。そして、DeepStream、ビデオ推論ライブラリ。TensorRTは、ニューラルネットワークモデルを最適化し、低精度で高精度に調整し、トレーニング済みモデルをクラウド、データセンター、組み込みシステム、または自動車製品プラットフォームに展開するのに役立ちます。

Nvidia

CUDA線形代数と数学ライブラリ

線形代数はテンソル計算、したがって深層学習を支えます。1989年にFortranで実装された行列アルゴリズムのコレクションであるBLAS(Basic Linear Algebra Subprograms)は、それ以来、科学者やエンジニアによって使用されてきました。cuBLASは、GPUで高速化されたバージョンのBLASであり、GPUを使用して行列演算を実行するための最高のパフォーマンスの方法です。cuBLASは、行列が密であると想定しています。cuSPARSEはスパース行列を処理します。

Nvidia

CUDA信号処理ライブラリ

高速フーリエ変換(FFT)は、信号処理に使用される基本的なアルゴリズムの1つです。信号(オーディオ波形など)を周波数のスペクトルに変換します。cuFFTはGPUで高速化されたFFTです。

コーデックは、H.264などの標準を使用して、送信および表示用にビデオをエンコード/圧縮およびデコード/解凍します。Nvidia Video Codec SDKは、GPUを使用してこのプロセスを高速化します。

Nvidia

CUDA並列アルゴリズムライブラリ

並列アルゴリズム用の3つのライブラリは、すべて異なる目的を持っています。NCCL(Nvidia Collective Communications Library)は、複数のGPUおよびノー​​ド間でアプリをスケーリングするためのものです。nvGRAPHは、並列グラフ分析用です。Thrustは、C ++標準テンプレートライブラリに基づくCUDA用のC ++テンプレートライブラリです。Thrustは、スキャン、ソート、リデュースなどのデータ並列プリミティブの豊富なコレクションを提供します。

Nvidia

CUDAとCPUのパフォーマンス

場合によっては、同等のCPU関数の代わりにドロップインCUDA関数を使用できます。たとえば、BLASのGEMM行列乗算ルーチンは、NVBLASライブラリにリンクするだけでGPUバージョンに置き換えることができます。

Nvidia

CUDAプログラミングの基本

プログラムを高速化するためのCUDAライブラリルーチンが見つからない場合は、低レベルのCUDAプログラミングを試してみる必要があります。これは、2000年代後半に最初に試したときよりもはるかに簡単になりました。他の理由の中でも、構文が簡単で、より優れた開発ツールが利用可能です。私の唯一の疑問は、MacOSでは最新のCUDAコンパイラと(Xcodeの)最新のC ++コンパイラが同期することはめったにないということです。Appleから古いコマンドラインツールをダウンロードしxcode-select、CUDAコードをコンパイルしてリンクするために使用してそれらに切り替える必要があります。

たとえば、次の2つの配列を追加する単純なC / C ++ルーチンについて考えてみます。

void add(int n、float * x、float * y)

{{  

       for(int i = 0; i <n; i ++)      

             y [i] = x [i] + y [i];

}

__global__宣言にキーワードを追加することでGPUで実行されるカーネルに変換し、トリプルブラケット構文を使用してカーネルを呼び出すことができます。

追加<< >>(N、x、y);

また、GPUにスペースを割り当てるように、malloc/newおよびfree/delete呼び出しをcudaMallocManagedとに変更するcudaFree必要があります。最後に、GPUの計算が完了するのを待ってから、CPUで結果を使用する必要がありますcudaDeviceSynchronize。これは、で実行できます。

上記のトリプルブラケットは、1つのスレッドブロックと1つのスレッドを使用します。現在のNvidiaGPUは、多くのブロックとスレッドを処理できます。たとえば、PascalGPUアーキテクチャに基づくTeslaP100 GPUには、56個のストリーミングマルチプロセッサ(SM)があり、それぞれが最大2048個のアクティブスレッドをサポートできます。

カーネルコードは、渡された配列へのオフセットを見つけるために、ブロックとスレッドインデックスを知る必要があります。並列化されたカーネルは、多くの場合、次のようなグリッドストライドループを使用します。

__グローバル__

void add(int n、float * x、float * y)

{{

   int index = blockIdx.x * blockDim.x + threadIdx.x;

   int stride = blockDim.x * gridDim.x;

   for(int i = index; i <n; i + = stride)

     y [i] = x [i] + y [i];

}

CUDA Toolkitのサンプルを見ると、上記で説明した基本よりも考慮すべきことがたくさんあることがわかります。たとえば、一部のCUDA関数呼び出しは呼び出しでラップする必要がありcheckCudaErrors()ます。また、多くの場合、最速のコードはcuBLAS、ホストとデバイスのメモリの割り当てや行列のコピーなどのライブラリを使用します。

要約すると、GPUを使用してさまざまなレベルでアプリを高速化できます。CUDAコードを書くことができます。CUDAライブラリを呼び出すことができます。すでにCUDAをサポートしているアプリケーションを使用できます。