CUDA (Compute Unified Device Architecture)

以上述べたようにGeForce 8800/9800シリーズGPUは、16コアのプロセサであり、各コアには8個の並列に動作する演算ユニットを持つプロセサチップである。従って、元々はグラフィック処理をメインに開発されたチップであるが、汎用の計算に使用することも可能である。

従来、GPUはGPUメーカーがドライバを開発するだけであり、プログラミングインタフェースを公開していなかったが、Unified Shader化によりGPUがこのように汎用的な計算にも使用できるようになったので、NVIDIAはCUDAというプログラミング環境を公開した。

CUDAのアーキテクチャを次の図に示す。

CUDAのソフトウェアアーキテクチャ(出典:NVIDIAのCUDAプログラミングガイド)

CUDAは、GPUのハードウェアを直接操作するCUDAドライバと、GPUの使用をサポートするランタイムライブラリ、そして数値計算などのライブラリから構成されている。また、プログラミングインタフェースとしてのCUDAは、C/C++言語をベースに、GPU側のメモリ領域を確保や、スレッド並列実行を行う機構を追加した言語であり、nvccと呼ぶコンパイラドライバが提供されている。

CUDAのプログラミングモデル

GPUはスレッドを超並列実行する構造となっているので、多数をスレッドをどのように管理するかが問題になる。CUDAでは、スレッドのまとまりをBlockと呼ぶ。この図では2次元のスレッドからなるブロックが書かれているが、CUDAでは最大3次元のスレッドの配列をブロックとすることができる。

そして、同じサイズのブロックをまとめたものをGridと呼び、グリッドは2次元のブロックの配列を含むことが出来る。このグリッドがホストから実行を指令する単位で、グリッド内の全スレッドは同じプログラム(Kernelと呼ぶ)を実行する。

CUDAのプログラミングモデル(出典:NVIDIAのCUDAプログラミングガイド)

一方、CUDAのメモリモデルは次の図のようになっており、各スレッドは占有のレジスタとローカルメモリを持ち、更に、同一ブロック内のスレッド間で共有のシェアードメモリを持っている。物理的には一つのマルチプロセサに含まれるSP間でシェアードメモリを共有しているので、同一ブロック内のスレッドは一つのマルチプロセサに割り当てられて実行されることになる。また、CUDAのメモリモデルとしてはスレッドに専属のローカルメモリがあるが、物理的にローカルメモリという実体があるわけでないので、シェアードメモリの一部をスレッド専用に割り付けることで実現していると考えられる。

CUDAのメモリモデル(出展:NVIDIAのCUDAプログラミングガイド)

そして、同一グリッドに属するブロック間でGlobal MemoryとConstant Memory、Texture Memoryを共有しているというメモリモデルである。物理的には、グローバルメモリはグラフィックDRAMで構成されるデバイスメモリに割り当てられ、コンスタントとテクスチャメモリは、チップ上の読み出しオンリーのメモリに割り当てられる。