読者です 読者をやめる 読者になる 読者になる

るくすの日記 ~ Out_Of_Range ~

主にプログラミング関係

Intel GVT-gにみるMediatedパススルーを用いたGPU仮想化

AdventCalendar OS 仮想化

この記事は システム系論文紹介 Advent Calendar 2015 - Adventar 17日目の記事です。


USENIX'14 ATCにてintelのKun Tian, Yaozu Dong,David Cowperthwaiteによって発表され、XenGTやKVMGTとしてごく最近に実装された新しいたGPU仮想化方式、GVT-gについて見ていく。

A Full GPU Virtualization Solution with Mediated Pass-Through
https://www.usenix.org/conference/atc14/technical-sessions/presentation/tian

昨今サーバー,クライアントサイド共にネィティブな速度のGPU仮想化が求められており、GPUに特化したインスタンスGPUリソースをサービスとしたクラウド業者もいるがこういった背景からもGPU仮想化は非常に需要のある技術である。

Intel GVT-gはブランド名であり論文内ではgVirtと呼ばれているため以降後者で呼ぶ。
gVirtはfull GPU virtualizationおよびmediated pass-throughを用いてネイティブパフォーマンスの95%の速度で仮想化を行うことができる代物だ。

Mediated Pass-Through
GPUの仮想化方式には様々な物があるがどれも一長一短でさまざまな実装例がある。

f:id:RKX1209:20151217212802p:plain

API Forwadingはゲストサイドの、OpenGLDirectXといったAPIをハイパーバイザ内のAPIに転送(フォワーディング)する技術でVMGL,Xen3Dなどで利用されている。
優れたパフォーマンスを発揮するが変換の対応が多く互換性維持が難しいなどの問題がある。

Direct Pass-Throughは名前の通りゲストから直接物理GPUへパススルーする物だがこれは各VM間でGPUを共有することが難しくなる。

Full GPU Virtualizationはハイパーバイザ上に実装されたデバイスモデルを用いた完全仮想化方式である。もし全てのアクセスをエミュレートした場合、これは非常にオーバーヘッドが大きくなり使い物にならない。
しかし図をよく見るとわかるが、今回本論文で提案されたMediated Pass-Throughはエミュレーションをごく一部(特権命令)のみにとどめ、パフォーマンスクリティカルなリソースへのアクセスは直接パススルーを行ってアクセスしている。


GPUプログラミングモデル
GPUの内部アーキテクチャは概ね以下のようになっている。

f:id:RKX1209:20151217212804p:plain

IntelGPUの場合Graphics memoryはPage Tablesを通してSystem memoryにマップされている。(つまりCPUと共有する仕組みになっている)
Graphics memoryにはピクセル情報などが格納されるFrame Bufferと、GPUが実行するべき命令が格納されるCommand Bufferがある。
Render Engineはcommand bufferからGPUコマンドをフェッチして実行し、また
Display Engineはframe bufferからピクセルデータを取り出しディスプレイなどに送信する役目を持つ。

またメモリのアドレス空間にはGPU,CPU共にアクセス可能なglobal graphics memoryと、
RenderEngineのみアクセス可能なlocal graphics memoryがある。

ゲストVMのグラフィックドライバはOpenGL(linuxならmesa)やDirectXAPIを通してGPU commandをcommand bufferに送信し、GPUがそれをフェッチして実行というのがGPUの基本的なプログラミングモデルである。

command bufferはprimary buffer(ring buffer)とbatch bufferで構成される。(head,tuple)というレジスタのセットでprimary bufferのringを表す。

GPUは主に

  • GPU Page Table Entries (PTEs)
  • I/O register(MMIO or PIO)
  • Command buffer
  • Frame buffer

から構成される。何らかの3Dアプリケーションを動かした際、当然ロード時は殆どFrame bufferへのアクセスが占め、実行時はCommand bufferが占める結果となる。PTEやI/O registerへのアクセスは相対的にかなり少ない。


gVirtの設計と実装

gVirtはMediated Pass-Throughを採用したXenベースのシステムである。現在はXenGT[1]としてXenのmainlineに統合されておりまたKVMにもKVMGTとしてごく最近に実装された。[2]
アーキテクチャは以下のようになる。

f:id:RKX1209:20151217212807p:plain

DomUからframe,command bufferへのアクセスは直接行う(パススルー)
PTEsやI/O registerといった特権リソースはトラップされDom0のmediator driverにフォワーディングされる。mediatorはハイパーコールを使って実際の物理GPUへアクセスする。上でも述べたがこの特権リソースへのアクセス回数は非常に少ないためパフォーマンスへの影響は小さい。
また複数VM間で物理GPUを共有するためのGPU schedulerもmediator内に実装されている。

gVirt stubはXenのvMMUモジュールを拡張し特定のアドレスへのアクセスをトラップするかパススルーするか選択できるようにした物でトラップされたアクセスはmediatorへフォワーディングされる。

MediatorはDom0内にカーネルモジュールとして実装。特権リソースへのアクセスを処理するためのvGPUおよびそれらvGPUのschedulerにより構成される。
コンテキストスイッチGPUはCPUの1000倍程度時間がかかり、またコア数も双方違うためCPU/GPUスケジューラは別々に実装している。
レガシーVGAおよびvirtual BIOSQEMUを用い、mediatorかVGA(QEMU)のどちらかにフォワーディングするような仕組みになっている。




物理GPUの共有

VMは仮想GPUを持っていてこれらvGPUは物理GPUを共有する。各vGPUがどれだけの時間物理GPUを割り当てられるかはRender engineスケジューラーにより決定される。
スケジューラーが用いるタイムスライスは16msで、この間ゲストVMからcommand bufferへコマンドが送り続けられGPUが実行する。ただしGPUはnon-preemptiveであるためこれは非同期に行えない。つまりcommand bufferの処理が終わるまで待っておく必要がある。
そこでgVirtはcoarse-grain flow controlを使うことでタイムスライス内に終わるようなコマンド発行を行うよう最適化を行う。
またこれらvGPU間のコンテキスト切り替えすなわち、パイプライン状態やI/O registerの退避、復帰を行う必要がある。具体的なコンテキスト切り替え手順は
1) 現在のI/O状態を保存
2) 現在のコンテキストをflush
3) 現在のコンテキストを保存
4) 現在のコンテキストを復帰
5) 現在のI/O状態を復帰
となる。
コンテキスト保存を行うGPU commandはgVirtのring bufferを通して実行する。これは、ゲストのring bufferに直接挿入するとゲストの別のコマンドで上書きされてしまうためである。(ゲストとの競合を避ける事がハイパーバイザにとって難しいからだろう)
コンテキスト切り替え前にgVirt用のring bufferに切り替え、切り替えが終了したらゲストのring bufferに戻る。



GPUパススルー

frame bufferおよびcommand bufferへのアクセスは直接パススルーする。この際複数のゲストがアクセスするため物理アドレス空間をパーティショニングする必要がある。
Graphics memory resource partitioningはglobal graphics memoryをパーティショニングする機能だ。これによるパフォーマンスへの影響は比較的少ないがゲスト-ホスト間のアドレス変換を行う必要がありオーバーヘッドとなる。
そこでオーバーヘッドを解消するためにgVirtはAddress space ballooningも併用する。
Address space ballooningは、各ゲスト内のグラフィックドライバが他のVMアドレス空間をBalooned領域として予約することで、ホストのメモリ空間と全く同じメモリレイアウトを維持し、アドレス変換の必要性をなくす。command bufferが変換なしで使えるため、ゲストのコマンドを高速に実行できる。しかしこれは同時にゲストVMによるセキュリティ侵害が発生する可能性もあるがこれにはLazy ShadowingやWrite-Protectionを用いる(これについては後ほど説明する)


GPUページテーブル仮想化
GPUはCPUと同じくgrahics memoryの仮想アドレスからsystem memoryのアドレスに変換する二段ページ変換機構、GPT(Global Page Table)を持っている。これにより各VMのgaraphics memoryアドレスはゲストの物理メモリに変換される。
gVirtはこのページテーブルの仮想化にshadow pagingを用いており、shadow global page tableはゲスト内のgraphics memoryからhost memoryへ変換を行うshadowingされたページテーブルである。
ちなみにshadow pagingはPTEにwrite-protectをかけてフォルトを起こして書き換える典型的な方式を用いている。

VMの隔離
VM内のCPUのI/O registersやPTEsへのアクセスは、gVirt mediatorによりtrapされエミュレートされる。
またcommand bufferやframe bufferへの直接アクセスもEPTを使用することでブロックする。
これにより悪意を持ったVMによるGPU commandの実行から保護する。gVirtは
ゲストのcommand bufferを使用し、直接コマンドを実行するためgVirt側で保護を行う必要がある。
またGPUのアクセスにも制御をかける。
ゲストVMのlocal bufferにコマンドが送信されるとgVirtはコマンドを記録する。しかしその後実際のGPUに送信されて実行されるまで若干のインターバルがあるためこの間にlocal bufferを修正されてしまうと、次の記録が行われるまでに間にGPUに送信されてしまう。つまりlocal bufferへのポーリングの間に改竄されてしまう可能性がある。

f:id:RKX1209:20151217212809p:plain

このためそれぞれのbufferに対して保護機構を実装する必要がある。ring bufferにはLazy shadowing,殆どアクセスのないbatch bufferにはWrite-protectionを適用することでこれを実現する。

Lazy-shadowing(ring buffer)
gVirtはshadow ring bufferを作り、CPUからlocal bufferに送信されたcommandをオンデマンドにshadow bufferへコピーする。shadow bufferはゲストが新しいコマンドを発行したらlocal bufferと同期を行う。またshadow bufferはゲストからアクセス不能である。つまりVMからの悪意のあるbuffer修正はできない。

f:id:RKX1209:20151217212812p:plain

Write-Protection(batch buffer)

batch bufferはゲストからのcommandが発行されてから実際にGPUでの実行が完了するまで書き込み保護をかけることで変更不可能にする。これによりcommand送信前にlocal bufferが書き換えられる恐れがない。

f:id:RKX1209:20151217212814p:plain


おわりに
本論文におけるgVirtは、パフォーマンスと可用性のバランスが非常にとれたGPUの完全仮想化方式でありXenGTやKVMGTとして実際に実装されている。XenGTはgVirtに加えhybrid shadow page table[4]を用いてさらに高速化を図っている。また第5世代BroadwellよりGPU仮想化機構がさらに進化しており今後の発展に期待できるだろう。



参考文献
[1] Zhiyuan Lv, et al, [XenSummit2014]
XenGT: A Full GPU Virtualization Solution with Mediated Pass-Through
http://events.linuxfoundation.org/sites/events/files/slides/XenGT-LinuxCollaborationSummit-final_1.pdf

[2] Graphics Virtualization (XenGT)
https://01.org/xen/blogs/srclarkx/2013/graphics-virtualization-xengt

[3] KVMGT: a Full GPU Virtualization Solution
http://www.linux-kvm.org/images/f/f3/01x08b-KVMGT-a.pdf

[4] Yaozu Dong, et al. [USENIX'15 ATC]
Boosting GPU Virtualization Performance with Hybrid Shadow Page Tables
https://www.usenix.org/conference/atc15/technical-session/presentation/dong