virtio-nvgpuは実験的なオープンソースプロジェクトで、Linux仮想マシン(VM)に、ホスト上のNVIDIAグラフィックスプロセッサ(GPU)へかなり直接的にアクセスする能力を与える。VulkanやOpenGLの各コマンドを変換するのではなく、VMとホストの間でNVIDIAカーネルドライバに対する要求を転送する。そのため、ゲストはVMの外で使用する場合と同じVulkanおよびNVENCライブラリを含め、NVIDIA独自のユーザーモードドライバを実行できる。

KVM仮想マシンでほぼネイティブなNVIDIA GPUアクセスを実現するvirtio-nvgpuプロジェクトの画像
virtio-nvgpuプロジェクトの画像は、NVIDIA GPUをLinux VMと共有するための実験的なデバイスを示している。github.com

冒頭のパラグラフでは、virtio-nvgpuと、Linuxゲストとホストの間でNVIDIAカーネルドライバへの要求を転送する役割を紹介している。

この設計はヘッドレスストリーミングを対象としている。VM内部のコンポジターがGPU上で動画をレンダリングしてエンコードし、圧縮済みの動画ストリームだけをリモートクライアントへ送信する。1台のRTX 3060を使ったプロジェクトのベンチマークでは、処理に約2ミリ秒以上かかるフレームはベアメタル性能との差が2%以内だった。12秒間のテストでは、ゲストのCPU使用時間が0.37秒だったのに対し、ホストでは0.40秒だった。著者はさらに、720pのvkcubeを実行する4つのゲストを同時に動かし、それぞれでH.264を60Hzでエンコードしたところ、合計レートが1つのゲストのレートに近づくと報告している。

重要なのは、そうした数値そのものよりも仕組みのほうだ。ゲスト側のドライバは制御要求をvirtqueue経由で渡し、メモリマッピングにより、NVIDIAのユーザーモードドライバは描画呼び出しのたびにVM境界を越えることなくレンダリング作業を投入できる。ホスト側のデバイスがドライバ要求のパラメーターを変換し、ゲストのハンドルをホストのデバイスファイルに対応付ける。これは、多数のグラフィックス呼び出しを直列化して再実行しなければならないAPIレベルの変換とも、VMごとにGPU丸ごと1台を割り当てる方式とも異なる。

根拠は限定的で、プロジェクト自身のREADMEに基づくものだ。対象は主にドライバ595.99.02を搭載したRTX 3060による1種類の合成負荷で、RTX A2000は描画できたもののベンチマーク対象にはならなかった。著者は、列挙を超えたCUDAの利用は未検証で、4台を超えるゲストは試しておらず、8台の場合も不明だと述べている。実際のデバイスアクセスを担う、ゲストごとのサンドボックス化されたヘルパーは設計上のメモにとどまっており、現在のバックエンドは仮想マシンモニターのプロセス内で動作している。

ドライバの互換性ももう1つの制約だ。NVIDIAカーネルドライバのアプリケーション・バイナリ・インターフェース(ABI)、つまりドライバ要求に使われるバイナリ上の契約は、リリースごとに変わる。そのためvirtio-nvgpuは選択されたドライバ範囲ごとに明示的なプロファイルを提供し、未知の要求レイアウトを推測するのではなく、535.129.03より古いものを拒否する。実用上の期待は、ストリーミング向けにGPUを効率的に共有できることだが、READMEは本番環境向けの分離性、幅広いアプリケーションとの互換性、限られたテストの範囲を超える性能を証明していない。