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

グラフィックスにフォーカスするNVIDIAの第1世代GPU仮想化



●プリエンプションはまだサポートせず

 NVIDIAがKeplerで導入したGPU仮想化技術は、フタを開けたら、ごく単純な仕組みだった。タスクが完了した段階で、仮想マシンをスイッチする。そのため、第1世代のGPU仮想化は、フレーム描画単位で仮想マシンをスイッチできるグラフィックスタスクにフォーカスしている。GPUコンピューティングでの本格的な仮想化の利用は、この先、GPU自身の進化を待たなくてはならない。

 「VGXでのGPU仮想化の第1世代では、グラフィックスユーザーにフォーカスしている。CUDAフォーカスではない」とNVIDIAでVGX製品ラインを担当するWill Wade(ウィル・ウェイド)氏(Senior Product Manager, NVIDIA)は説明する。VGXは、NVIDIAのGPU仮想化に特化した製品ラインだ。

NVIDIAのWill Wade氏VGXボード

 なぜ仮想化がグラフィックスフォーカスなのか。それは、現在のGPU仮想化の仕組みが、グラフィックスタスクでないと効率的に働かないからだ。Wade氏は次のように語る。

 「シングル(命令)ストリーム、(言い換えれば)シングルスレッドは、スイッチする前に完了していなければならない。Keplerではプリエンプションがないためだ。スレッドは実行が完全に終わるまでストップすることができない。長時間走るスレッドでは難しい」。

 GPU仮想化と言っても、現段階のNVIDIAの実装では、プリエンプティブなスイッチができない。CPU的な表現をすれば、1つのスレッドの実行を始めたら、そのスレッドが終了するまで仮想マシンを切り替えることができない。ちなみに、用語的な問題を言うと、NVIDIA GPUでは、通常はWarpの中の1ワークアイテムに対する命令ストリームをスレッドと呼んでいるが、Wade氏はここではCPU的な意味でのスレッドで、ワークアイテム群全体に対する処理の単位をスレッドと呼んでいる。

 スレッド実行中に切り替えができないGPUに対して、通常のCPUの場合、スレッドの実行中に他のスレッド/仮想マシンに切り替えることができる。例えば、すぐに実行する必要があるスレッド/仮想マシンを優先的に実行するために、実行中のスレッド/仮想マシンを中断させて、切り替えることが可能だ。そのため、実行時間が長いスレッドを複数走らせていても、それぞれのスレッドを、時分割で円滑に走らせることができる。これは、CPUのプリエンプティブマルチタスキングの仕組みの上に、仮想化が乗っているからだ。

 それに対して、KeplerのGPU仮想化の場合は、ノンプリエンプティブなスイッチングであるため、スレッド実行途中での切り替えができない。従来のGPUは、そもそも、プリエンプティブマルチタスキングもサポートしていないからだ。そのため、長時間走るカーネルプログラムを走らせる場合は、仮想化が難しい。長時間に渡って切り替えができなくなるため、他の仮想マシンのスレッドが遅延してしまう可能性があるからだ。

 CPU風の表現をすれば、KeplerのGPU仮想化は、プリエンプティブマルチタスキングができない状態で、仮想マシンをサポートしたような状態となっている。以前、このコラムでは、NVIDIAがプリエンプションを実現したと推測したが、そうではなかった。

●フレーム単位で規則的に区切れたグラフィックスタスク

 KeplerのGPU仮想化は、CPUでの仮想化と比較すると単純だ。それでも、グラフィックス用途では、十分に有用だとNVIDIAは主張する。それは、グラフィックスのワークロードとGPUの仕組みが、仮想化に向いているからだ。

 具体的には、現在のNVIDIA GPU仮想化では、ある仮想マシンが1フレーム分の描画を終えると、次の仮想マシンに切り替えている。1画面のフレーム描画が基本単位となっており、n個の仮想マシンを立ち上げている場合は、n個のフレームを描画して、次のサイクルに移る。

 「GPUは非常にコンテクストスイッチが高速だ。サブフレームで複数のスイッチができると見ている。第1世代の仮想化でのゴールは、GPU当たり8仮想マシンだ」とWade氏は言う。

 NVIDIAは、1フレームの時間内に、1個のGPUで、8個の仮想マシンの切り替えを行なうことがゴールだと説明する。グラフィックス処理タスクの粒度は、秒間60フレームなど、描画のフレーム時間が目安となる。GPUに走らせることができるプログラムは、ターゲットのフレーム時間内に処理できるものが望ましい。処理に時間がかかれば、フレームレートが落ちてしまうからだ。

 NVIDIAが8仮想マシンと言っている意味は、1フレームの間に、8個の仮想マシンのフレーム描画を実行できることを示す。グラフィックス仮想化では、各仮想マシンそれぞれの1フレーム描画分のグラフィックスタスクの処理時間によって、1フレーム時間内に、どれだけの数の仮想マシンをサポートできるかが決まる。GPUが通常のフレームレートの8倍のフレームレートで描画できれば、8仮想マシンを実行できる計算になる。

 この関係を示したのが下の図だ。図は4仮想マシンの場合で、標準的な60fpsを基準に考えるなら、GPUがこのグラフィックスタスクを240fpsで描画できるなら、1仮想マシン当たり60フレームで描画できる計算になる。

GPU仮想化と仮想マシン(PDF版はこちら)

 NVIDIAは、最新世代のKepler系GPUなら、フレーム当たりの処理時間が短くなるため、複数の仮想マシンを1フレーム時間内で切り替えることが可能になると想定している。現バージョンでの目標は、8仮想マシンだが、これは単純にその程度の負荷のグラフィックスタスクを想定しているというだけの話だ。

●グラフィックスのコンテクストスイッチに特化したGPU

 ここで、出てくる疑問は、仮想マシン間の切り替えのレイテンシだ。CPU的な発想なら、通常のコンテクスト/仮想マシンの切り替え時にレイテンシが発生する。切り替えが増えると、切り替えオーバーヘッドでパフォーマンスが削がれてしまう。

 GPUはプロセッサ数が膨大であるため、アーキテクチャルステイトの量が非常に多く、一般的に考えればコンテクストスイッチングが極めて重いはずだ。しかし、NVIDIAがGPUはコンテクストスイッチが高速だと説明している。これは、仮想マシンの切り替え前に、必ずスレッドを終了するためだ。

 もともと、グラフィックス処理では、フレームの描画は1フレーム時間に収まるだけの短さになっている。グラフィックス処理では、必ず短サイクルでスレッドを終えて、次のフレームのグラフィックスコンテクストへと切り替える必要がある。「グラフィックス処理はコンテクストドリブンなので、GPUではコンテクストの切り替えを、できる限り速くする必要があった。GPUはそこに特化してきた」とNVIDIAはグラフィックス処理の特徴を説明する。

 グラフィックスでは1フレームの描画を終えると、GPU内のアーキテクチャルステイトは基本的に不要なデータになる。「フレーム描画を終えて(ピクセルを)メモリに描き込んだ後は、GPU内のコンテクストは不要になる。だから、GPUからコンテクストをメモリにセーブする必要がない」とNVIDIAは説明する。

 GPU内のアーキテクチャルステイトをメモリにセーブする必要がないため、ステイトセーブのレイテンシがない。ただし、フレーム毎に、次のスレッドをスタートしなければならないため、コンテクストデータのロードの遅延は生じる。しかし、このロードレイテンシも、グラフィックスパイプラインの中で、できる限り隠蔽する仕組みをGPUが備えていると言う。

GPUグラフィックス仮想化(PDF版はこちら)

 このように、そもそもコンテクストのストアが必要なく、コンテクストのロード時間も短いため、グラフィクスタスクではコンテクストスイッチが高速に行なわれる。さらに、NVIDIAはKepler世代では、仮想マシンのサポートのために、いくつかの機能を加えたことを説明した。

 米国でのGPU Technology Conferenceでは、Jen-Hsun Huang氏のキーノートスピーチで下のスライドが示された。これは、NVIDIAが1997~98年頃に申請した一連の特許(US5638535、US5696990、US5740406、US5805930、US5924126、US6081854)のものだ。これらの特許は、GPUのようなプロセッサでマルチアプリケーションを走らせる場合の、I/Oやメモリ回りの設計の拡張に関するものだ。

 まず、図中の31の「First-In First-Out (FIFO)」が複数のプロセスに対応するように多重化されている。プログラムのインプットのためのFIFOバッファを、プロセス毎に備えることで切り替えを高速化する。また、Keplerのメモリマネージメントユニット(MMU)は、CPUのMMUのように、仮想メモリアドレスを物理メモリアドレスに変換する。複数の仮想マシンのメモリ空間がマップされ、36番のメモリアドレストランスレーションテーブルで保持される。

 ソフトウェア層との対応は次のスライドのようになる。HypervisorがのリソースマネージャがMMUを制御してアドレススペースの切り替えを管理する。各仮想マシンは、仮想マシン毎に設けられたチャネルに直接アクセスする。チャネルの厳密な内容はわからないが、前出のFIFOもその一部に含まれることは間違いがない。

 ハードウェア支援によって、グラフィックスでは、仮想マシンはフレーム描画速度が許す限りの数を立ち上げることができる。「ゲームであっても、原理的には最高25仮想マシンをシングルGPUでシングルフレームでサポートすることが可能だ」とNVIDIAは説明する。もちろん、サポートできる仮想マシンの数は、グラフィックスタスクの負荷に依存する。ヘビーなゲームでは、フレームレートから考えて、それほど多くの仮想マシンをサポートはできない。

●コンピュートに最適化した仮想化は次のステップ

 グラフィックスでは処理の粒度がフレーム単位であるため、有効なGPU仮想化だが、問題はグラフィックス以外のGPUコンピューティング時だ。

 NVIDIA GPUは、Kepler世代でも、まだプリエンプティブなコンテクストスイッチングはサポートしていない。膨大なGPUのアーキテクチャルステイトを短時間に切り替えることが難しいためだ。汎用レジスタだけで数MBもあるGPUのステイトをセーブ/リストアするだけで、かなり時間がかかり、新アプローチが必要となる。

GPU仮想化の次のステップ(PDF版はこちら)

 現状ではノンプリエンプティブなスイッチしかできないため、グラフィックス以外のGPUコンピューティングに仮想化を使うには制約がある。NVIDIAのWill Wade氏は「スレッドの途中でスイッチできるようにすることは、現状では、非常に難しい。そのため、CUDAワークロードを仮想化する場合は、ワークロードの中身を注意深く検討する必要がある」と説明する。

 コンピューティングタスクの場合は、長時間走るスレッドも発生する。現在のノンプリエンプティブなKeplerのGPU仮想化では、汎用に使うには難しい。現実的には、NVIDIAが説明するように、グラフィックスワークロード中心となる。

 GPUコンテクストのプリエンプティブな切り替えができない点はAMD GPUでも同じで、「現在のGPUでは、カーネル実行中に切り替えることはできない」とAMDは説明している。AMDは、次のフェイズで、GPUでのグラフィックスプリエンプションと、コンピュートのコンテクストスイッチングをサポートするとしている。AMDが用語を分けているのは、すでに説明したように、グラフィックスとコンピュートではコンテクストの切り替えの意味合いが違ってくるからだ。また、AMDは、コンピュート時には、グラフィックスコンテクストを除いたコンピュートに関連するステイトだけをスイッチする方法を取る。固定機能のグラフィックスユニット内のステイトは、コンピュートの切り替え時に触れない。また、コンピュート時には、GPU内部をパーティションで仕切ってスイッチする方法を取ると推測される。

NVIDIAのSteve Scott氏

 グラフィックスプリエンプションは、もともとWindowsのドライバモデルで要求されている仕様だ。おそらく、NVIDIAもほぼ同じタイミングでプリエンプションをサポートして来るだろう。NVIDIAのGPUコンピューティング部門であるTesla business unitのCTOを務めるSteve Scott(スティーブ・スコット)氏は、「それ(プリエンプション)は我々が社内で実現を模索しているところだ」と語っている。

 その世代になれば、GPU仮想化は汎用性をさらに広げるだろう。GPUのマルチタスク機能も、飛躍的に向上するため、GPUの汎用コンピューティング利用も進展する可能性がある。