NVIDIA GPUの基本的な実行方式

NVIDIAのGPUは、頂点の座標計算や画面のピクセルのシェーディングなどの計算を32頂点、あるいは32ピクセル並列に計算するという考え方で作られている。座標変換やピクセルのシェーディングの計算は32頂点、あるいは32ピクセルでまったく同じ計算を行なう。

この場合、命令は1つで、入力は32頂点(やピクセル)のデータを並べた長いデータとして計算を行ない、結果を32スレッド分の長いレジスタに格納するという処理方式とすれば効率が良い。

図3-31 SIMDの命令は多数(この例では32)の要素をまとめたベクタ型のデータを演算し、ベクタ型の結果をレジスタに格納する

このような処理方式は、Single Instruction Multiple Data(SIMD)と呼ばれる。IntelのプロセサのSSE命令やAVX命令も複数のデータに同じ演算を並列に行っており、SIMD方式の処理である。

GPUもこのSIMD方式であったが、NVIDIAは2006年11月に発表した「G80 GPU(最初の製品はGeForce 8800)」から、SIMT(Single Instruction Multiple Threads)と呼ぶ新しい実行方式に変更した。1つの命令列を32の演算で共用するという点はSIMDと同じであるが、32ピクセルのベクトルデータをSIMDで並列に処理するというモデルでは無く、それぞれのデータ要素に対して、ある程度異なる命令列を実行することができ、スレッドごとに異なる処理ができるという方式である。図3-32に示すように、各スレッドが1頂点(あるいはピクセル)を担当して、32スレッドで32頂点(あるいはピクセル)を並列に処理するというモデルである。

それぞれのスレッドの命令はPredicateというビットを持ち、その値で、その命令を実行するかどうかを指定できるようになっている。このため、並列に実行される32スレッドはSIMDのように完全に同じ処理を行うのではなく、ある程度、異なる処理を行うことができる。NVIDIAは、この32スレッドのまとまりをWarp(ワープ)と呼んでいる。英語ではスレッドは縦糸、ワープは横糸で、宇宙船のワープとは関係無い命名である。

図3-32の例では、Predicateの制御により、スレッド1では命令1と命令4は実行されるが、命令2と3はスキップされて実行されない。そして、同時に実行されるスレッド2では命令1~4の全命令が実行され、スレッド32では命令2と3が実行され、命令1と4はスキップされる。

SIMDでは自動的に同じ演算が32個のデータに適用されてしまうが、SIMTでは個々の命令の適用の可否がPredicateで制御できるので、スレッドごとに異なる操作ができるという点が大きく異なる。

図3-32 SIMTでは1つの命令を多数(この例では32)のスレッドで使用するが、それぞれの命令を実行するか、しないかをPredicateで指定でき、Predが1の命令(黄色)だけが実行される

また、レジスタの内容をアドレスとしてメモリをアクセスするLoad/Store命令の場合、SIMDでは1つのレジスタがアドレスを指定するので1か所のメモリアドレスからベクトル型の32個のデータを読めばよい。しかし、図3-32に示すロード命令のアドレスはどのスレッドも、例えば、ロード命令で指定したR3レジスタから読まれるが、SIMTの場合はスレッドごとにレジスタは独立であり、R3レジスタの内容はスレッドごとに異なる。このため、SIMTのロードストアユニットは、最大32の異なるアドレスのアクセス要求が1つのロード命令から発生するので、これが処理できるようになっている必要がある。

図3-33 ロード命令はレジスタR3の内容をアドレスとしてメモリをアクセスする。この命令は32スレッドに共通であるが、SIMTの場合は、R3レジスタの内容はスレッドごとに異なる

これらの機能をハードウェアに持たせるSIMT方式を使うことにより、シングルスレッドの普通のプログラムを多数並列に実行させることができるようになる。つまり、SIMDの場合のようにデータをまとめたベクトル型の変数を扱うようにプログラムを書きなおす必要が無く、その分、SIMT方式のプログラミングは楽である。