GPUのマルチスレッド処理
GPUでは多数の頂点やピクセルの処理を、それぞれのスレッドで並列に実行する。つまり、演算器の数だけの、100~数1000スレッドを並列に、SIMT方式で実行する。これに加えて、歴史的なマルチスレッドマシンのところで紹介したHEPのように、多数のスレッドのグループを切り替えて順番に処理すると、同じスレッドに戻ってくるまでの時間が長くなるので、Out-of-Order実行などの複雑な制御を使わなくても、演算器のレーテンシやメモリアクセスのレーテンシを隠すことができる。
GPUでは、この両者の効果を有効に利用しており、演算器数の数10倍のオーダのスレッドを同時並列的に実行する。こうすると、各演算器は数10スレッドを切り替えて実行することになり、同じスレッドの次の命令を実行するのは数10サイクル後となり、演算やロード/ストア(キャッシュヒットの場合)のレーテンシを隠すことができる。
しかし、このような実行を行うためには、数1000個の演算器を持つハイエンドGPUの場合は、数万個以上のスレッドを並列に実行する必要がある。このような実行を行うハードウェアの基本的な構造は、図3.2のようになる。
しかし、すべてのスレッドが頂点の座標変換や同じアルゴリズムを使うピクセルシェーディングを行う場合は、それぞれの実行ユニット(PE)に数10スレッドをサイクルごとに切り替えながら命令を供給する機構を付けるのは無駄が多い。このため、NVIDIAのGPUでは32PEのグループに同じ命令を供給している。一方、AMDのGPUでは64PEのグループに同じ命令を供給している。
図3.3に示すように、命令発行機構を32PEで共通にすると、命令発行に必要なハードウェアが大幅に減少し、多数の実行ユニットをチップに詰め込むことが可能になる。これが、GPUが高い演算性能を持つことができる大きな理由である。
チップ上の数1000個のPEが全く同じ命令列を実行する場合は、32PEごとに命令発行機能を付ける必要もなく、数1000PEまとめて、1つの命令発行機構でも良い。しかし、ある程度、命令の発行にフレキシビリティを持たせた方が良い場合がある。
例えば、if文がある場合は、SIMT実行では、それぞれのスレッドで条件判定を行い、次の命令を実行するかどうかを決めるが、図3.3の構造で一組の32PE全部が、条件が不成立の場合は、演算結果を書き込まない命令を全部のPEが実行するのは無駄で、if文の次の文にジャンプしてしまえばよい。しかし、隣の32PEのグループでは条件が成立するPEがあるとすると、そのグループでは同じようにif文の次の文にジャンプしてしまうわけには行かない。数1000個のPE全部に命令供給が共通の場合は、その中のどれか一つのPEでも条件が成立する場合は、全てのPEがif文の命令を実行する(ただし、結果の書き込みは条件ビットで制御する)必要があるが、32PE単位で命令を供給する場合は、そのグループ内のすべてのPEで条件が不成立ならジャンプしてしまえるので、無駄な命令の実行を抑えることができる。
また、一画面の中でも、重要な部分には高度なアルゴリズムを使って綺麗な絵を作り、背景の部分は簡単なアルゴリズムで済まして、描画時間を短縮するという場合は、全てのPEが同じ命令を実行するのではなく、PEのグループごとに異なる命令を実行する必要がある。
さらに、最近では迫真の動きを表現するため、破壊されて砕け飛ぶ瓦礫の動きや、波立つ水の動きなどを、アーティストの描画ではなく、物理的に動きをシミュレーションして求めるということも行われている。このような場合も、一部のPEを物理シミュレーション用に割り当て、別のプログラムを実行させることが必要になる。
これらの使い方を考えると、1つのチップ上の数1000のPEに1つの命令供給機構ではなく、ある程度のPEのグループ単位で命令供給機構を設けて置く方がよい。このため、NVIDIAのGPUでは32PEを単位としており、これをワープ(Warp)と呼んでいる。なお、ワープはSFの宇宙船が行う空間ジャンプではなく、命令列を織物の縦糸(スレッド)に見立てて、それと直交するする横糸(ワープ)という意味である。また、AMDは64PEを単位としており、これをWavefrontと呼んでいる。
ここではワープを処理するためには32個のPEが必要と書いてきたが、NVIDIAのFermi GPUでは、図3.4に示すように、サイクル0ではワープ0の命令1を使って論理PE0 のレジスタを読み出し、サイクル1でこの命令を実行するのであるが、次のサイクル1でも同じ命令を使って論理PE1のレジスタを読み出し、サイクル2でその命令を実行するという形で、1つの物理PEに2サイクル連続して同じ命令を実行させて、論理的には2つのPEに見せている。
このため、Fermi GPUでは、ワープを実行する資源は16個の演算ユニットからなっている。このようにすると、2サイクルに1命令を実行ユニットに発行すれば良いので、命令発行ユニットの設計は楽になる。
しかし、32論理PEの演算の実行には1つの命令が必要であるという点は変わらず、1ワープの実行に2サイクル掛かるので、命令の発行も2サイクルに1回で良いことになっているだけで、このような構造が、必ずしも得とは言えない。
このためか、昔のNVIDIAのTesla GPUは4サイクル連続して、同じ命令を実行していたのであるが、Fermi GPUでは2サイクルとなり、現在のKepler GPUや最新のMaxwell GPUでは、遂に1サイクルになってしまった。ただし、Maxwellでも演算器に比べて使用頻度の低いSFU(Special Function Unit:三角関数などの計算ユニット)とロード/ストアユニットは4サイクル実行となっており、使用頻度の低いユニットでは物量を減らす設計になっている。
なお、AMDのGCN(Graphic Core Next) GPUは16個の演算器が4サイクル同じ命令を実行することにより64要素のWavefrontを処理する構造となっている。