特集

自作GeForce NOW?ゲーミングPCを複数人で共有、ゲームサーバーにする「EASY-GPU-PV」と「Parsec」

承前

 ある日、原稿を書いていると編集部の劉氏から突然「自作GeForce NOW的なサーバーの構築ノウハウお持ちですかね?」という、「なんじゃそりゃ」な相談を持ち掛けられた。

 一体何の話だろう?と思ったら、Linus Tech Tipsで紹介された動画である。一枚のGPUを最大4つのVMで共有することで、例えば同時に複数のゲームを1枚のGPUで実行するとか、1台のマシンで複数のユーザーがゲームを同時にプレイする、といったことが可能になる。

 「うん、それ、嬉しいかな?」

 「僕はFF14で子供はマイクラで妻は別のゲーム、それを1つのGPUでレンダリング、夢がありますよ(笑)。」

 なるほど、夢か(笑)。とは言いつつも、実はGPUを複数のVMで共有できるというのは、色々使い方が考えられる。別にゲームではなくOpenCLのアクセラレータとして使うこともできるからだ。

 ただ、これまでこうした使い方は不可能だった。理由は簡単で、GPU側で制限を掛けているからだ。例えばNVIDIAの場合で言えば、A100 Ampereは本来7つまでのインスタンスを同時に実行できることになっているが、コンシューマ向けのAmpereベースの製品は1インスタンスに限られている。要するにサーバー/HPC向け製品のみ、マルチインスタンスを利用可能にするという形で差別化要因にしているわけだ。

 さて、この回避策というか、普通のコンシューマ向けGPUでもマルチインスタンスを利用できるようにしよう、というツールとしてEasy-GPU-PVが配布されている。先のビデオでは、このEasy-GPU-PVからフォークしたEasy-GPU-Pを使って、4人のプレイヤーが同時に1つのマシンの上で「CS:GO」を遊んでいる様子が紹介されているが、試してみたら元々のEasy-GPU-PVでも特に問題なく同じことができたので、今回はこのEasy-GPU-PV+Parsecを使って、自宅マシンのマルチユーザーゲームサーバー構築の手順をご紹介したいと思う。

原理

 Easy-GPU-PVはWSL2(Windows Subsystem for Linux 2)とかWindows Sandboxと同じ仕組みを使い、GPUのリソースを複数のHyper-V VMに割り振るためのツール(というか、スクリプト)である。

Easy-GPU-PVの配布ページより

 もともとWindows 10で提供されたWDDM(Windows Display Driver Model) v2.5以降では、GPU-PV(GPU Paravirtualization:GPU準仮想化)という仕組みが新たに追加された。これはWindows上のVMやコンテナに対して、仮想化されたGPUを提供するという仕組みである。WDDM v2.9以降では、この仮想化されたGPUをWSL2やWindows Sandboxで利用することが可能になった。もちろんHyper-Vでも可能である。

 なので、GPUカードを入れたマシンの上でHyper-Vを使ってWindowsを立ち上げ、この上でゲームを動かすと、ちゃんとGPUを使ってくれることになる。だから、Hyper-Vで2つGuest OSを動かし、それぞれが別々にGPUを利用すれば、結果としてGPUのリソースを2人で分割できることになる。

 こちらは完全な意味での仮想化ではなく、GPU全体をWindows Kernel Mode Driverが完全に占有(するのでGPUから見るとインスタンスは1つ)し、そのKernel Mode Driverが複数のVMからのリクエストを受け付けて能力を分配するような格好になるので、端的に言えばVMの数はメモリとかリソースが許す限りまで増やせるし、それだけ同時に実行できるゲームの数も増やせることになる。

 ただHyper-Vの場合、画面出力は当然ローカルの画面になるし、複数のVMが稼働中であっても同時に操作できるVMは1つだけだから、このままでは全然意味がないことになる。いや無駄に3DMarkをすべてのVMで廻して遊ぶことはできるかもしれないが、少なくとも2つ以上のゲームを同時に操作することはできない。

 これに対する解決策がParsecである。Parsecは自分のローカルPCの画面や音声、キー入力などをリモートに飛ばしてくれるツールであり、ホスト/クライアントの環境を選ばない(Windows/Mac/Linux/Android/ChromeOS/Raspberry Pi)。

 もっともゲームとなるともう少し環境が厳しく、ホスト側は最低でもWindows 8.1、できればWindows 10以上になっているし、GPUも必須である。単にデスクトップ画面をリモート接続するだけならGPUは必要ないのだが、ゲームを使う場合はホスト側の画面をGPUのエンコーダを使ってH.264/H.265で圧縮して送り出すという形で帯域の節約と画面品質維持を図っており、このためにはハードウェアエンコーダが搭載されたGPUが必要になるためだ。

 このハードウェアエンコーダが、またボトルネックの要因の1つになる。NVIDIAのGPUの場合、同時に3ストリームまでしかエンコードができない仕様になっている。なので、クライアントはリモートだと同時に3VM(+ローカルで1VM)というのが事実上の上限である。AMDのGPUだと4ストリームのエンコードが可能だから、リモートで4VM+ローカル1VMとなるが、まぁこれは技術的にはともかく現実問題として可能か? というのはやや微妙なところだ。

 またキーボードやマウスに関しては問題なく使えるが、ゲームコントローラに制限があるのも難点の1つである。さすがにUSB接続のゲームコントローラが全て利用可能、というわけには行かないようだ。

 一応ParsecではViGEmBusというオープンソースのUSBゲームコントローラ対応エミュレーションドライバをサポートしており、なのでViGEmBusで対応しているデバイス(現在はXbox 360のコントローラと、SCEIのDualShock 4の2つをエミュレーションする)にゲームが対応していれば利用可能ではあるが、全てのゲームコントローラがそのまま使えるかどうかの保証はない。

準備

 理屈は以上で説明した通りである。ということで実際にEasy-GPU-PVとParsecを使ってサーバーを立ち上げてみよう。用意するものであるが

ハードウェア

  • ホスト用に高速なCPU(コア数が多いほど快適:今回はRyzen 9 5950Xを借用)
  • ホスト用に16GB以上のメモリ(32GB以上を推奨:今回は64GB構成で実験)
  • ホスト用にAMDないしNVIDIAのDiscrete GPU。一応Intelの内蔵GPUでも動作するが、そうでなくても非力な内蔵GPUを更に分割して共有したら使い物にならないので却下。また古い製品(例えばAMDのRadeon RX 5xxシリーズはビデオエンコーダが未搭載なので、Parsecで利用できない等)も不可である。GPU性能そのものも重要だが、搭載するメモリ量も多い程良い(今回はAMD Radeon RX 6900 XTを借用)
  • DisplayPort Headless ダミープラグ×2:これは後ほど説明。今回はRadeon RX 6900 XTを使う関係で、AmazonでEVanlakの4K対応DisplayPortダミープラグを購入したが、使う環境に合わせてHDMIなりDisplayPortなりのダミープラグを用意してほしい(写真01,02)
  • クライアント機数台:Parsecが動作すれば理論上はなんでもいいのだが、今回はDesktop×2、ノート×1(ThinkPad E495)を流用
  • 間を繋ぐネットワーク:Wi-Fi 6があれば必ずしも有線でなくても良いが、筆者宅はまだWi-Fi 5なので、今回は有線LAN(GbE)で統一した

といったところ。あとHyper-Vで仮想マシン(VM:Virtual Machine)を複数立ち上げると、当然それだけストレージも必要になるので注意されたい。

【写真01】ちなみに1個899円だった。なんでDisplayPortか?というと、Radeon RX 6900 XTはHDMI×1、DisplayPort×2の出力になっており、このうちHDMIは実際の表示で使うためにDisplayPort×2を用意
【写真02】装着の図。空いてるDisplayPortにダミープラグを装着することで、システムに「4K Monitorが繋がっている」と誤認識させる

ソフトウェア

  • Windows 10 20H1以降ないしWindows 11(Easy-GPU-PVでは、Hypervisorの互換性の良さからWindows 11を推奨)。ただしHome Editionは不可能で、ProかEnterprise、Education Editionが必要。これはHome EditionではHyper-Vが利用できないため。なお、ホスト用は日本語版でも行ける
  • ホストと同じバージョンと同じOSの、ただし『英語版』のDisk Image(ISOファイル)。これはHyper-Vで動くVMで利用する。これは日本語版では動作しない(というか、インストールができない)。Windows 11ならこちらからISOファイルをダウンロード可能なので、あらかじめダウンロードしておく。Windows 10の場合、既に直接のISOファイルのダウンロードが不可能である(Visual Studio Subscription、旧名MSDN Subscriptionの契約をしていれば入手できるが)。ただRufusを使ってダウンロードが可能(手順は英語で恐縮だがこちらに記されている。原稿執筆時点で最新版の3.18でもちゃんとダウンロードが可能なことは確認した)である。
  • Easy-GPU-PVそのもの。こちらからダウンロードして、適当なフォルダに展開しておく。
  • Parsec。こちらからダウンロード可能である。ちなみにParsecを利用する場合はユーザー登録が必要(無償)なので、もしまだParsecの登録をしていないのであれば、こちらで新規ユーザー登録も済ませておく。

といったところになる。以上の用意ができたら、インストールの開始である。

インストール

 インストール手順であるが、以下のようになる。

(1) ホストマシンでは、BIOS Setupの中でVirtualizationを有効にしておく。

【写真03】これはAMDの場合。Intelのマザーボードなら、"Intel (VMX) Virtualization Technology"などと示された項目をEnableにする

(2) Windowsのインストールを普通に行なう。今回はWindows 11 Proでインストールを行なった。ちなみに(3)に進む前に、Windows Updateを掛けて最新の状態にすると共に、GPUの最新のドライバをインストールすること。WindowsのInbox Driverでは必ずしも正しく動作しない場合があるとされる。

(3) "Windowsの機能の有効化または無効化"画面で、Hyper-Vを有効化する(写真04,05)。

【写真04】Windows 11の場合、"スタートメニュー"→"Windowsツール"→"コントロールパネル"→"プログラムの機能"→"Windowsの機能の有効化または無効化"でやっと出現する。ちなみに標準状態ではHyper-V関連が一切インストールされていない
【写真05】Hyper-V関連に全てチェックを入れる。ここで"OK"を押すと、インストール後に再起動が要求されるので、再起動する

(4) Easy-GPU-PVのインストールを開始する。筆者の環境では、Easy-GPU-PVからmain.zipをダウンロードし、これをDesktopの"Easy-GPU-PV-main"というフォルダの下に展開している。まずこの状態で、Windows PowerShell ISEを『管理者権限で』起動し(写真06)、まず"PreCheck.ps1"をファイルメニューから開いた上で、実行する(メニューバーの緑の"▶"ボタンを押す)。環境に問題がなければ、GPUの名前(写真07の赤枠で囲った部分)が表示されるので、これをメモっておく。

【写真06】PowerShell ISEは"スタートメニュー"→"Windowsツール"の中にある。なんでPowerShellを必要とするかというと、Easy-GPU-PVがPowerShell用のシェルスクリプトで記述されているためだ
【写真07】まぁここは直接PreCeheck.ps1をコマンドラインから実行しても構わないのだが

(5) 次に、同じように"CopyFilesToVM.ps1"をPowerShell ISEで開く。この冒頭にパラメータがあるので、これを必要に応じて書き換える。変更箇所はList1の通り。

List

 ここで、VMNameとかVHDPathとかはまぁ好きなようにすればよいが、CPUCoresとかMemoryAmountなどのパラメータは、同時にいくつのVMを走らせるかによって大きく変わってくる。例えば4つVMを立ち上げるとすると、このパラメータのままだとCPUコアを16個、メモリを32GB、ストレージを160GB消費することになるし、GPUの占有率は200%になってしまう。ここでの設定は以下のようにしておこう。

CPU数:トータルのCPUコア数を超えると、VM同士でCPUの奪い合いになる。勿論ここで言っているコア数は物理コア数ではなく論理コア数だし、VMで占有するコアの数が実際の論理コア数を超えても動作はする(写真08)が、この状態で個々のVMをフル稼働させるとCPUリソースの奪い合いになるので、むしろ性能が落ちかねない。なので、VMで稼働させるコア数の合計<実際の論理コア数にすることをお勧めしたい。

【写真08】とりあえずホスト上で4つのVMをコア数10で立ち上げてみた。一応問題なく起動はする

メモリ:こちらは個々のVMで指定したメモリをそのまま占有する関係で、VMで予約したメモリの合計+ホストで使うメモリ<システムのメモリ量にしないと、そもそもVMがメモリ不足で立ち上がらない。実際、4つのVMをメモリ量指定8GBで立ち上げた場合、システム全体では37.3GBを占有する(写真09)。試してみたところ、

0VM1VM2VM4VM
VMあたり4GB4.8GB9.0GB13.3GB21.9GB
VMあたり6GB4.7GB11.1GB17.5GB32.7GB
VMあたり8GB4.8GB13.3GB21.6GB38.3GB

といった感じ。32GBメモリの場合で4VMを立ち上げる場合、VMあたり6GBだと4つ目のVMが立ち上がらない感じだ。かといって、あまりメモリをケチると今度はVMの上でゲームが満足に走らない。32GBの場合は3VM程度で諦めるか、もしくはメモリの増設を考えるべきだろう。

【写真09】VMを一切動かさない状態で5GB程を消費しており、これにVMの32GBが加わる計算

GPU:GPUの占有率は、CPUやMemoryと異なり「目安」でしかなく、割といい加減である。例えば4VMということで各々25%の占有率にして一斉にFFXIV Official Benchmarkを実行してみると(写真10)、1VMで30%前後、2VMで60%程度なのが4VMだと70%そこそこだったり、という面白い結果になっている。なので、これは純粋に立ち上げるVMの数で均等割りするのが良いかと思う。

 といったあたりだ。後のパラメータの説明は不要かと思う。ちなみにストレージ容量やメモリ量/CPUの数は、後でHyper-Vマネージャ(写真11)で個々のVMの設定(写真12)。

【写真10】ちなみにこの状態だとまともに画面が表示されない(そもそも画面が1,024×720pixelだから当然である)。このあたりはParsecを使って、3つのVMはほかのマシンに飛ばしてやる必要がある
【写真11】これもPowerShell ISE同様に“スタートメニュー”→“Windowsツール”から呼び出せる。現在は4VM向けのGPUPVA~GPUPVDを起動中
【写真12】CPUの数とメモリはここで直接変更ができる。ストレージに関しては、SCSIコントローラ→ハードドライブ→仮想ハードディスクの編集で、容量を増やしたり減らしたりできる(増減させた後は、それぞれのVM上からストレージ管理を呼び出して、それを反映させる手間が掛かるのがちょっと面倒だが)

(6) 編集し終わったら保存をした後、先ほど同様に実行する(メニューバーの緑の“▶”ボタンを押す)。問題がなければ、数分でVMの構築が完了し、そのままVMが自動的に起動れる(写真13)。ちなみに英語版のDisk Imageではなく日本語版のDisk Imageを使うとどうなるか?というのがこちら(写真14)。これを解決すべく色々調べたのだが、とりあえず現状は英語版のDisk Imageを使うのが一番手っ取り早いという結論に達した。

【写真13】正常にインストールできた例。パラメータは筆者の環境にあわせてちょっといじってある
【写真14】スクリプトの中で、一旦ISOイメージをマウントしたうえで、必要なファイルを転送する作業を行っているのだが、日本語版だとinstall.wimというファイルが見つからないと怒られて終わる

(7) VMが立ち上がると、もうParsecがインストーラされているので、先に登録しておいたアカウントでParsecにログインする(写真15)。すると、自身のDesktopを公開するか、それとも他のマシンの画面をアクセスするかの設定になるので、「自分のDesktopを公開」を選ぶ(写真16)。

【写真15】左上の上から3番目がParsecである
【写真16】一番左を押すと“Share”で、自分の画面を他のマシンに公開する形になる

(8) クライアント側にもParsecをインストールしてからログインすると、先ほど(7)で立ち上げたVMが見えるので、そこに"Connect"することでリモートからそのVMを使えるようになる(写真17)。

【写真17】ここだと右から2番目に、今立ち上げたVMが見えているので、これを"Connect"で繋げば完了

(9) 以後、(5)~(8)の作業をVMの数だけ繰り返せば良い。もっともこの状態では各VMはParsec以外まっさらな状態なわけで、ここから各VMにゲームなりアプリケーションなりをインストールする、という作業は別途発生することになる。

 ところでParsecで飛ばした場合のクライアントだが、 準備するもののところで出て来たHeadless ダミープラグを装着すると、こんな具合に4Kまでの解像度をちゃんと選択できる(写真18)。ダミープラグなしだと最大解像度が2Kに限られてしまうので、これへの回避策という話である(逆に言えば、画面解像度は2K止まりで良いというのであれば、ダミープラグは要らない)。

【写真18】4,096×2,160ピクセルとかいう謎の解像度も表示されている

実際に使ってみる

 ということで、どの程度これが使い物になるかを最後にご紹介したい。

 まずわりやすいところで3DMarkのFireStrikeを。VMを使わない、直接ホスト上で行なうとスコアは38890といったところ(写真19)。これを4つのVMで実施すると、14226/11368/13010/15327と多少バラつきはあるが、平均13483といったあたり(写真20)。

【写真19】Average 42191だからやや数字が低いのがドライバの問題なのか、ほかの要因なのかは不明。ちなみにVMは全て停めて実施したもの
【写真20】左上がRyzen 7 3800Xのマシン(Windows 11)、左下がホストの上でVMとは別にParsecを起動してVMと接続した状態、右上が原稿書き用のマシン(Ryzen Threadripper 2950X+Radeon RX 580×2、Windows 10)、右下はThinkPad E495(Windows 10)にHDMI経由でモバイル4Kモニターを接続したもの

 実際には各VMあたり論理4コアに制限した状態でやっており、Physics ScoreとかCombined Scoreが本来よりも低めになっている。そこでGraphics Testの結果を比較すると、直接ホストで実施すると52034なのに対し、4 VMでは25150/15028/18368/23046で平均20398。VMなしの場合の4分の1よりも少し高めだが、VMなしだとGPUの利用率が必ずしも100%に達しない時も多いのに対し、4VMだとほぼ100%に近い利用率になるあたりが、この性能差に繋がっていると思われる。

 同様に、FF XIV 暁月の終焉ベンチマークをやってみた。VMなしの単体だとScoreは26637(写真21)。これを4 VMで実施すると7305/7203/7323/7355とこちらは意外にバラつきがすくなく、平均7297といったところで、こちらも4分の1よりやや上回っているのは同じ理由だろう。

【写真21】経験則で言えば、このスコアの1/100がほぼ平均フレームレート。ちなみに設定は2Kフルスクリーンで、描画品質は高画質(Desktop用)
【写真22】さすがに4つのマウスのボタンを同時に押すことは不可能で、まず左の2台分のマウスを同時に押してスタートしてから、右の2台をスタートする格好になっている。なので、完全に同時というわけではないのだが、まぁスタート時間の差は数秒のオーダーである

 問題としては、結構GPUのメモリの容量が厳しいことだ。例えば今回で言えば、2VMであれば3DMark FireStrike Ultraとか3DMark PortRoyalを実施するのは問題なかったのだが、4VMでやろうとするとそもそも立ち上がらなかった。要するにGPUのメモリを4GB以上使おうとして、そこでテスト失敗となって終了するパターンだ。多分CPUとかメインメモリよりもシビアに効いてくるのがこのGPUのメモリであって、これは特に解像度を上げると必然的に顕著になりやすい。

 その意味では解像度は2Kに絞るとか、全てのVMで4Kを可能にするのではなく、4Kを利用可能なVM(これだけ、"GPUResourceAllocationPercentage"のパラメータの値を高めに設定しておく)と、2KのみのVM(同じくパラメータの値を低めに設定しておく)といった、メリハリを付けた設定が必要かもしれない。

 ちなみに冒頭で紹介したLinus Tech Tipsのプレイ動画であるが、もっと細かく手順を説明したものが下である。こちらの12:45あたりから、実際にEasy-GPU-PVを使って4人でプレイしている様子が出てくるが、こちらはGeForce RTX 3080 Tiを4VMで使っているので、VMあたり3GBのビデオメモリとなる。プレイしているのが軽めのCS:GOなのは、それだけリソースが厳しいことの裏返しとも言える。より大容量の、例えば32GBのメモリを積んだRadeon RX 6900 XTとかに期待したいところだ。

ということで

 冒頭に劉氏から振られた「GPU仮想化」の構築手順をご紹介した。ちなみにここまで触れてこなかったが、ライセンスの問題が別途発生することにご注意いただきたい。ホスト用にWindowsが1つ、それとは別に各VMにもそれぞれWindowsのライセンスが1つずつ必要になる。

 また、今回Steamのゲームなどを試さなかったのは、複数のマシン上で同一のSteamアカウントを利用することができない(個別にSteamアカウントが必要)ことだ。先のLinus Tech Tipsの場合、4人のユーザーがそれぞれ自分のSteamアカウントでログインしてプレイをしていたものと思われる。ただ筆者はさすがに4人分のアカウントは持ち合わせておらず、それもあって今回はスタンドアロンのものを試すに留まっている。

 使い勝手というか使える用途は色々限られるとは思うが、無駄にハイエンドGPUを余らせているお宅では試してみるのは悪くないのではないかと思う(GeForce RTX 3070以下とかRadeon RX 6700以下なら最大2VMが限界だし、その下のグレードのGPUではそもそも分割が無茶な気はしなくもないが)。