後藤弘茂のWeekly海外ニュース

基本アーキテクチャの柔軟さが産んだGeForce GTX 460



●IPC(Instruction-per-Clock)を高めたアーキテクチャ

 NVIDIAがパフォーマンスGPU「GeForce GTX 460(GF104)」を投入した時、多くの人が驚いたのは、NVIDIAがGPUコアのマイクロアーキテクチャを革新したことだった。GF104では、NVIDIA GPUのコアに当たる「SM(Streaming Multiprocessor)」のアーキテクチャが大きく変わっていた。「普通は、1番小さな単位(=SM:Streaming Multiprocessor)の中はいじらない」とあるハイパフォーマンスコンピューティング(HPC)業界関係者は言う。

 GeForce GTX 460世代では、各SM(Streaming Multiprocessor)の中の実行パイプラインが大幅に増やされた。それだけではない、実行パイプラインに対する命令発行も強化された。ハイエンドGPUのGeForce GTX 480(GF100)では、1個のSMの中で最大2命令(@2サイクル)しか発行できなかった。それがパフォーマンスGPUのGeForce GTX 460では最大4命令も発行できる。つまり、ピークのIPC(Instruction-per-Clock)はGF100が2 IPCであるのに、GF104は4 IPCと、ピークレートだけを見ると倍増している(GF104のターゲットは3 IPC)。

GF104のStreaming Multiprocessor(SM)
PDF版はこちら
GF100のStreaming Multiprocessor(SM)
PDF版はこちら

 命令発行を2から4に倍増。CPU的な発想では、これはとても大きな変化に見える。例えば、2命令発行のCPU(Atom)と、4命令発行のCPU(Core iなど)では、内部アーキテクチャは大きく異なる。CPUの場合は、4命令発行を可能にするためには、命令間の依存性をチェックして並列実行するための高度なスケジューリング機構を備える必要がある。そのため、CPUの場合、命令発行数の変化は、マイクロアーキテクチャのメジャーチェンジの時しか起こらない。

 ところがNVIDIA GPUは、FermiアーキテクチャのマイナーチェンジのはずのGeForce GTX 460(GF104)で、ピークの命令発行数を4に拡張した。どうやって、こんなことが可能になったのか。その秘密は、GeForce 8800(G80)から始まるNVIDIAの基本アーキテクチャにある。

GF100ファミリーの派生
PDF版はこちら
GF104、GF100の概要
PDF版はこちら

●柔軟性の高いNVIDIAのWARPスケジューリング

 そもそもG80を作った時から、NVIDIAアーキテクチャは命令発行数を自由に拡張できるスケーラビリティを備えていた。なぜなら、G80で導入した「WARPスケジューリング」が、命令発行数を比較的容易に変更することを可能にしているからだ。G80世代では、命令発行数は2サイクル毎に1命令と限られていたが、スケーラビリティ自体は最初から備えていた。

 G80以降のNVIDIA GPUは、WARPと呼ばれるスレッドバッチ単位で命令を実行する。WARPは「SIMT(Single Instruction, Multiple Thread)」実行、つまり同じ命令を実行するスレッドの束で、一般的なベクターマシンのベクター長にあたる。G80以来、NVIDIA GPUのWARPサイズは32スレッドで固定されている。WARP内のスレッドは、プログラムカウンタ(PC)を共有しており、原則として1つのカーネルプログラムの中の同じ命令を実行する。

G80のWARPスケジューリングの仕組み
PDF版はこちら

 NVIDIA GPUはSMの中で複数のWARPを立ち上げることが可能となっている。立ち上げ可能なWARP数の上限は、GPUアーキテクチャによって決まっている。GeForce GTX 460と480は最大48 WARPまで立ち上げることができる。命令スケジューラは48個のWARPから、実行可能なWARPを選んで実行パイプに発行する。

 個々のWARPに対する命令ストリームは、命令順に実行するインオーダ実行となる。しかし、それぞれのWARPの実行順序は、アウトオブオーダにできる。WARP間の依存性は簡単な方法で解決されているため、WARPスケジューリング自体は相対的に容易となる。CPUのように、1つの命令ストリームの中で、個々の命令の依存性をチェックして命令順序を並べ替えて並列実行する必要がない。

 それまでのGPUも、マルチスレッディングを行なっていたが、NVIDIA GPUのWARPスケジューリングはよりスマートだ。従来のGPUは、1つのスレッドバッチ(NVIDIA用語でWARP)の命令をインオーダで実行し続けて、ストールすると初めて他のスレッドバッチ(WARP)に切り替えていた。1つのスレッドバッチ(WARP)の命令を複数サイクルに渡って実行することで命令実行レイテンシを隠蔽し、スレッドバッチ(WARP)の切り替えによってメモリレイテンシを隠蔽する仕組みだ。

 例えば、AMDアーキテクチャでは、1つのスレッドバッチ(AMD用語ではWavefrontでベクター幅は64)を4サイクルに渡って実行する。命令シーケンサを2つ用意する(物理的には同じ命令ユニット)ことで、2スレッドバッチを交替に実行。合計8サイクルで実行レイテンシを隠蔽する。8サイクルスループットで2つのWavefrontの命令を実行し続けて、どちらかがストールするとスレッドバッチ(Wavefront)を切り替えて、メモリアクセスレイテンシを隠蔽している。

 それに対して、NVIDIAのWARPスケジューリングは、よりダイナミックだ。WARPスケジューリングで、実行とメモリの両方のレイテンシを隠蔽する。そして、NVIDIA WARPスケジューリングは、命令発行を容易に拡張できるという利点も持っている。

●世代とともに命令発行が拡充されるNVIDIA GPU

 NVIDIAのWARPスケジューリングは、WARPの並列発行が比較的容易であるため、原理的には簡単に命令発行(=WARP発行)の幅を広げることができる。実際、NVIDIAはGeForce 8800(G80)/GeForce GTX 280(GT200)系からGeForce GTX 480(GF100)系へと拡張する際に、WARPスケジューリングの拡張を行なっている。

 G80/GT200系では、各SM(Streaming Multiprocessor)毎に1個の命令発行ユニットしかなかった。GF100では2命令発行ユニットとなり、GF104では4命令発行ユニットとなった。命令発行ユニット数は、アーキテクチャの改革とともに倍増している。

 ここで、「G80/GT200系も2命令発行とNVIDIAは言っていなかったか?」と疑問に思ったかもしれない。これにはトリックがある。まず、NVIDIA GPUの命令発行ユニットは、2サイクル毎に1命令を発行する。命令発行自体が2サイクルスループットだ。

 それに対して、G80/GT200アーキテクチャでは、メインの実行ユニットクラスタでの命令実行は4サイクルスループットとなっている。8個の実行ユニットでクラスタを構成しているからだ。32スレッドのWARPを8ユニットクラスタで実行するため、4サイクルスループットとなる。G80/GT200では論理ベクター長が32で、物理ベクター長が8と言い換えてもいい。

G80の2命令発行の仕組み
PDF版はこちら

 そのため、1個の命令発行ユニットが2サイクルスループットで命令発行を行なうと、ピークで2つの実行ユニットクラスタをフルに充填することができる。2つの実行ユニットクラスタは、命令発行サイクルから見ると2サイクルずれた形で命令を実行する。並列実行はピークでも16スレッドとなる。32スレッドのWARPを2サイクルスループットで発行しているからだ。

 一方、GF100ではメインの実行ユニットクラスタでの命令実行は2サイクルスループットとなっている。メインの実行ユニットクラスタの最大構成が16ユニット/クラスタだからだ。16ユニットで32スレッドのWARPを実行するため、2サイクルスループットとなる。論理ベクター長が32のままで、物理ベクター長が16になった。そのため、2個の命令発行ユニットが2サイクルスループットで命令を発行すると、2つの実行ユニットクラスタを充填することができる。32スレッドのWARPを2サイクルスループットで2つずつ発行するため、並列実行は32スレッドだ。

FermiのWarpスケジューリング
PDF版はこちら

 GF104では命令発行ユニットはさらに2個増えた。ピークで4命令発行となり、最大4個の実行ユニットクラスタを充填できる。GF100と同様にメインの実行ユニットクラスタの構成は16ユニット/クラスタとなっている。16ユニットで32スレッドのWARPを実行するため、2サイクルスループットとなる。4個の命令発行ユニットが2サイクルスループットで命令を発行するため、並列実行はピークで64スレッドとなる。

GF104のWarpスケジューリング
PDF版はこちら

●NVIDIAの設計思想の変化が見えるGF104アーキテクチャ

 このように、命令発行の仕組みとIPC(Instruction-per-Clock)を見ると、GeForce GTX 460(GF104)はGeForce GTX 480(GF100)から大きく拡張されている。G80/GT200→GF100の変化に匹敵するほどの大きな改革だ。

WARPスケジューリングの変遷
PDF版はこちら

 シングル命令ストリームを実行することに最適化された従来CPUでこれをやろうとすると、命令スケジューリングに大きな拡張が必要となる。しかし、NVIDIA GPUの場合は、基本的なWARPスケジューリングの仕組みはそのままで、こうした一連の拡張が可能だ。依存性の解決が相対的に容易なWARP同士のスケジューリングで並列化しているからだ。このスケーラビリティは、NVIDIAがG80の時に開発したベースアーキテクチャ自体が備えているものだ。

 しかし、NVIDIAも自由に命令発行の度合いを増やすことができるわけではない。なぜなら、WARPスケジューリングが、メモリレイテンシの隠蔽と密接に連携しているからだ。NVIDIAアーキテクチャで隠蔽できるメモリアクセスサイクルは、単純化すると、命令スループット×立ち上がっているWarp数÷IPC(Instruction-per-Clock)×依存命令間隔となる。そのため、スケジューリングするWARP数が同じままで、SM(Streaming Multiprocessor)内の命令発行数を増やすと、隠蔽できるメモリレインテンシが下がってしまう。

 もし、メモリレイテンシ隠蔽の度合いを同等に保とうとするなら、命令発行数の増加とともに、インフライトで制御できるWARP数を増やさなければならない。しかし、レジスタ数が同じままで、WARP数を増やすと、1スレッド当たりのレジスタ数が減ってしまう。そのため、レジスタも増やす必要が出る。このように、命令発行数を増やすとドミノ式に他の要素も増やす必要が出てくるはずだった。

 しかし、NVIDIAはそうしなかった。GF104でも、インフライトで制御できるWARP数はSM当たり48でGF100と同じ。また、レジスタ量も128KBと据え置きだ。これが意味していることはただ1つ。NVIDIA GPUは、マルチスレッディングによるメモリレイテンシの隠蔽から、オンチップメモリによるメモリレイテンシの短縮へとシフトしつつあるということだ。これまで、GPUはキャッシュミスに最適化され、CPUはキャッシュヒットに最適化されたアーキテクチャをとってきた。この基本姿勢は今も変わらないが、GPUも多少、キャッシュヒットを期待するアーキテクチャへと変わってきたように見える。

 NVIDIAのこの選択は、半導体チップの現状では、必然と言えるものだ。なぜなら、オンチップのトランジスタ数はどんどん増やすことができるのに、オフチップのI/O帯域は容易に広げることができないからだ。消費電力的にも、オンチップメモリによるメモリレイテンシの短縮の方が利点がある。

GF104、GF100、GT200、G80のメモリ量
PDF版はこちら