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

Pascal世代で飛躍するNVIDIAのGPU仮想化技術「NVIDIA GRID」

NVIDIAのGPU仮想化技術

 NVIDIAはGPUリソースをリモートで利用するインフラストラクチャ「NVIDIA GRID」を進化させつつある。VDI(Virtual Desktop Infrastructure:仮想デスクトップ)では、サーバー上に仮想的に実現されたデスクトップ環境に、リモートアクセスすることで、あたかもローカルにあるリソースのようにサーバーリソースを使うことができるようにする。利点は、サーバー側でにリソースを集約することで、リソースの有効活用、TCO(Total Cost of Ownership)の低減、データの安全などを実現しやすいこと。

 VDI自体は以前から利用されているが、NVIDIA GRIDは、CPUだけでなくGPUも仮想化することで、GPUリソースも共有できるようにする。GPUで複数の仮想マシンを走らせるGPU仮想化を可能にし、サーバー側の1個のGPUを、複数のリモートユーザーで共有できるようにする。CPUエミュレーションでは得られないグラフィックスパフォーマンスで、アプリケーションもそのままVDIで利用できるようにする。そのため、GRIDではバーチャルGPU「vGPU」を実現できるソフトウェアインフラストラクチャを提供している。GRIDは現在、2世代目のバージョン GRID 2.0となっており、Maxwellアーキテクチャベースで最大8GBまでのメモリを使うことができる。

NVIDIAは右側のvGPUとGPUパススルーを提供している
シングルGPUでは8GBメモリで16ユーザー、デュアルGPUでは16GBメモリで32ユーザーをサポートする

 NVIDIAはGRID 2.0のデモとして、「流体(Fluid)シミュレーション」を使ったデモを公開した。デモではサーバー側で走るCUDAシミュレーションとその結果のグラフィックスともに、クライアント側でローカルで走っているように扱うことができていた。しかし、このデモには、実は、ちょっとした仕掛けがあった。それは、流体シミュレーションのデモでは、1個のサーバー側GPUを1ユーザーで占有しており、GRIDの売りであるGPUリソースの共有化は、実はなされていなかった。

限定されている現在のGRID 2.0でのGPUコンピューティング

 実は、現在のGRID 2.0では、CUDAを使うことができるプロファイルを限定している。8GBプロファイル、つまり、GPUを1個まるごと1つの仮想マシンが占有するプロファイルでのみCUDAを利用できる。言い換えれば、他の仮想マシンとのリソースの競合が発生しないプロファイルでのみ、GPUコンピューティングが許可される。

 現在のGRIDには複数のvGPUプロファイルがあり、1ユーザー当たりの割り当てのビデメモリ量と1GPU当たりのサポートユーザー数の関係で階層化されている。512MBメモリのプロファイルなら最大16ユーザーのサポートが可能だ。8GBのメモリを16ユーザーで分割するからだ。しかし、8GBメモリのプロファイルでは、当然ながら1ユーザーしかサポートできない。現状では、CUDAやOpenCLを使うGPUコンピューティングは、8GBメモリの1ユーザープロファイルに限定されている。

GRIDのプロファイルとサポートする機能の関係

 なぜ、GPUコンピューティングが、現在のGRIDの仮想化では制約されるのか。理由は簡単で、現在のNVIDIA GPUがプリエンプションをサポートしていないためだ。プリエンプション、つまり、実行中のタスクを中断して、別なタスクを実行、終了後に再び元のタスクの実行を再開することが、NVIDIA GPUではできない。プリエンプティブなコンテキストスイッチングのハードウェア支援機能を備えていないためだ。

 現代的なCPUなら、実行中のタスクのコンテキストをプロセッサ外に保存(ストア)して、別なタスクのコンテキストをロードして実行、その後、元のタスクのコンテキストをプロセッサに復元(リストア)して実行を再開するコンテキストスイッチングが可能だ。ここで言うコンテキストは、レジスタ内容やプログラムカウンタ値など、プロセッサの内部状態として保持しなければならない値だ。コンテキストスイッチによって、OSがタスクを自由にスケジュールすることが可能になり、割り込み処理もできる。

 仮想化でも同様で、仮想マシンを切り替える際に、ゲストOSのコンテキストをいったんストアして、別のゲストOSのコンテキストをロードする必要がある。元のゲストOSに戻す時には、ストアしてあるコンテキストをリストアする。柔軟な仮想マシンの切り替えには、プリエンプティブなコンテキストスイッチングが必要となる。

 しかし、プリエンプティティブなコンテキストスイッチングをサポートしていない現在のNVIDIA GPUでは、原則として、実行中のタスクが終わるまで、他のタスクに切り替えることができない。そのため、ある仮想マシン上で、実行に時間がかかるタスクをGPUが実行している間は、他の仮想マシンに切り替えられない。長時間のタスクが終わるまで、他の仮想マシン上のタスクは待たされる。

 なぜ、GPUではプリエンプティブなコンテキストスイッチのサポートが遅れているのか。それは、GPUのコンテキストが膨大だからだ。GPUには膨大な演算プロセッサとレジスタがあり、汎用レジスタの待避だけでも大変だ。また、GPUでは、タスクを論理ベクタ長のサイズwarpに分割して実行しており、各warp毎にプログラムカウンタや分岐のプレディケーションのためのマスクレジスタがある。GPUのコンテキストのサイズは膨大で、CPUのように簡単にはストア/リストアができない。そのため、NVIDIAではコンテキストスイッチをサポートして来なかった。また、AMD(ATI) GPUでも、最近までサポートできなかった。

グラフィックスタスクではプリエンプションが不要

 こうした技術上の理由から、現在のNVIDIA GRIDでは、複数ユーザーの仮想マシンを1つのGPUで走らせる場合、制約が発生する。時間のかかるタスクの走る仮想マシンのために、共有するほかのユーザーのグラフィックスタスクの描画が遅くなるなどの問題が発生してしまう可能性がある。CPUならコンテキストスイッチで切り替えることができるため問題にならないことが、GPUでは問題になる。これが、現在のNVIDIA GPUで、CUDAコンピューティングを使う場合に、複数仮想マシンでの共有ができない理由だ。

 ところが、この問題は、グラフィックスアプリだけを使っている場合は、制約にならない。グラフィックスタスクでは、GPU側がプリエンプションに対応していなくても、複数ユーザーが仮想マシンでGPUを円滑に共有できる。なぜなら、グラフィックスでは、タスクをスイッチする際に、コンテキストを保存(ストア)する必要がないからだ。

 グラフィックスでは、1画面を描画し終えた段階で、そのグラフィックスタスクのコンテキストは維持する必要がなくなる。言い換えれば、タスクは画面描画の小さな単位で独立している。そして、グラフィックスタスクは、必ず1フレームの描画時間の間に終える必要があり、一定のフレームレートを維持しようとするとタスクの所要時間が短い。

 そのため、グラフィックスタスクの場合は、複数のタスクを切り替える場合も、コンテキストをストアする必要がない。1つのグラフィックスタスクの画面描画が終わってから、別なグラフィックスタスクをロードすればいいからだ。ストア/リストアのコンテキストスイッチングが必要ない。コンテキストを保存する必要がないという意味で、「GPUはコンテキストスイッチングが高速」という言い方もをするGPU関係者までいる。

グラフィックスタスクでは、コンテキストの保存や復元が必要ない
PDF版はこちら

 グラフィックスタスクの場合は、制約は、描画のフレームレートと1画面の描画に必要となるGPUの処理時間の関係だけとなる。例えば、60fpsで描画する場合に、各ユーザーのタスクのGPUの処理時間がフレームレートの4分の1の時間で済むなら、4人のユーザーがGPUを共有しても60fpsで描画できることになる。そのため、グラフィックスタスクの負荷に応じて、プロファイルを使ってGPUを共有するユーザー数を調整すれば1フレームのサイクルに収まる。

GPUコンピューティングの仮想化ではプリエンプションが必須に

 グラフィックスタスクは、このように短い処理で、コンテキストのストア/リストアが不要であるため、GPUはコンテキストスイッチをハードウェアでサポートする必要がなかった。しかし、GPUコンピューティングのタスクとなると話が異なる。GPUコンピューティングでは、タスクによって処理時間が大きく異なる。1つのカーネルが延々と走っている場合がありうる。

 そのため、GPUコンピューティングを絡めた瞬間に、GPUでの仮想化でもプリエンプティブなコンテキストスイッチングが必要となる。グラフィックスのような処理時間が一定のタスクばかりではないため、処理の長い仮想マシンを途中で止めて、他の仮想マシンをロード/ストアできなければ、円滑な仮想マシンの稼働ができない。

上がグラフィックスタスクのスイッチング、下がGPUコンピューティングタスクのスイッチング
PDF版はこちら

 こうした制約から、現在のNVIDIA GRID 2.0では、CUDAのサポートはコンテキストスイッチが必要のないプロファイルに限定している。仮想化でシェアして使えるのは、グラフィックスタスクという限定になっている。このことが、NVIDIAが現在のGRIDをVDI(Virtual Desktop Infrastructure)の進化形として位置づけている理由となっている。

 しかし、分散型のコンピューティングの聖杯は、蛇口をひねると水が出るように、コンピューティングパワーをリモートで簡単に取り出すことができることにある。GPUコンピューティングについても、ローカルのアプリケーションを使っている感覚で、リモートのリソースを使えるようにすることは明確な目標だ。NVIDIAは、この課題をどうしようとしているのか。

今年のPascal世代でさらに進化するNVIDIA GRID

 NVIDIAはごく近い将来に、この問題を解決する。2016年のGPUでは、プリエンプションをサポートするからだ。「現在はプリエンプションをサポートしていないが、Pascalからはサポートする。カーネル実行途中でのスイッチが可能になる」とNVIDIAのMarc Hamilton氏(Solution Architecture & Engineering, VP, NVIDIA)は昨年(2015年)9月のGPU Technology Conference(GTC) Japan時に説明している。

NVIDIAのMarc Hamilton氏(Solution Architecture & Engineering, VP, NVIDIA)
NVIDIAのPascal

 2016年のNVIDIA GPUアーキテクチャのPascalからは、カーネルを実行途中で中断し、コンテキストをストアしてほかのカーネルをロード、その後、再び元のカーネルのコンテキストをリストアすることができるようになる。そのため、GRIDもPascal世代で次のステップへと進化、CUDAを自由に使うことができるようになると予測される。複数のユーザーの仮想マシンが1個のPascal GPU上で走っていても、各仮想マシンでCUDAを走らせることができるようになるだろう。時間のかかるCUDAカーネルは、途中でプリエンプションにより切り替えが可能になり、他の仮想マシンに影響を及ぼさなくなる。

 この段階になると、シミュレーションもGPUリソース活用が自由にできるようになり、GRIDの利用がさらに高度化する。より上位のユーザーにもGRIDが使いやすいものになる。

NVIDIAが見るGPU仮想化の市場

 このように、NVIDIAのGRIDは継続的に進化しており、GRID 2.0移行の展望も見えている。GPU側のハードウェアの進化とともに、GPUの仮想化も進化して行く。GPUの仮想化の最終的なゴールは、CPUと同様の使い勝手を実現することだと見られる。

 GRIDのその先のステップは、GPUの大きな難関である、マルチGPUにまたがる仮想化となる。現在のGPUは、CPUのように仮想化で、複数チップを1つのリソースとして扱うことができない。もちろん、分散化のフレームワークを使えばマルチGPUを使うことができるのだが、アプリケーションをそのまま仮想化したマルチGPUに持って行くことができない。これについても、NVIDIAはNVLinkのような布石を打っており、将来的には対応する可能性がある。

 いずれにせよ明確なことは、NVIDIAがGPUの仮想化を重視しており、ロードマップで革新して行くつもりでいることだ。GRID 3.0以降になると、GPUをコンピューティングリソースとして共有できるようになり、さらに一歩進む。

(後藤 弘茂 (Hiroshige Goto) E-mail