Ubuntu Weekly Recipe

第592回 QEMUでGPUの3Dアクセラレーションを利用する

この記事を読むのに必要な時間:およそ 5.5 分

広く使われているマシンエミュレーターであるQEMUには,3Dアクセラレーションに対応した仮想GPUを作る機能が存在します。そこで今回はこの機能を使って,ゲストマシン上でOpenGLベンチマークツールを動かしてみましょう。

QEMU/KVMと3D GPU

QEMU/KVMはLinux用に広く使われているマシンエミュレーターです。たとえば仮想マシン管理ツールであるlibvirt/virt-managerや,libvirtのGNOME製フロントエンドであり第572回「GNOME Boxesを使用する」でも紹介されている「GNOME Boxes」は,QEMU/KVMをバックエンドとして利用しています。同様に第590回「Windows/macOS/Linuxで使える仮想マシン管理ツール『multipass⁠⁠」で紹介したmultipassも,Linux版のバックエンドはQEMU/KVMです。

Virgil 3Dプロジェクトによって,このQEMU/KVM上で3Dアクセラレーションに対応した仮想GPUを作成・利用できるようになりました。Virgil 3Dでは準仮想化デバイスのフレームワークである「virtio」を利用して仮想GPUを構築し,ゲストOSはMesaのvirglドライバーを利用してこの仮想GPU向けに描画命令を送ります。それに対してホスト上のQEMUはvirtio-gpuで受け取った命令を,virglrendererというコンポーネントがホスト上のGPUに対してOpenGL命令として発行するわけです。

Virgil 3Dプロジェクトの成果はすでにQEMUに取り込まれています。そしてUbuntu 19.04のQEMUにおいて,ゲストOSにおける3D GPU機能が有効化されたのです※1⁠。これによりゲストOS上のUbuntuでも,それなりの速度で3Dアプリケーションが動作するようになりました。今回はその3D GPU機能を実際にQEMUのコマンドを実行しながら使ってみましょう。

※1
19.10のリリースノートを読むと,まるで19.10から使えるようになったように見えるかもしれません。実はこのQEMU関連の文言はそっくりそのまま19.04のリリースノートにも掲載されています。Ubuntuのリリースノートはそういうことがよくあるのです。いずれにせよ,3D GPU対応は19.04でも確認できますが,カーネルがより新しい方が安定しているので,今回は19.10を使うことにします。

図1 ゲスト上でも3Dアプリケーションが動く

画像

ちなみに性能はあくまで「それなり」です。完全なソフトウェアエミュレーションよりははるかにマシなので,Unity時代のUbuntuのような遅さは解消するものの※2⁠,ホストと同じぐらいの性能が出るわけでもありません。

※2
UbuntuのデスクトップUIであったUnityは,あるバージョンから3Dアクセラレーション機能を必須とし,対応していないマシン上ではCPUによるエミュレーションを実施していました。結果として仮想マシン上のような3Dアクセラレーションが無効化されていて,CPUもそこまで速くない環境では,GNOME端末を起動するだけでも数秒のアニメーションを眺めさせられるといった,時間の使い方が贅沢なユーザー体験を提供していたのです。ちなみにここで言う「Unity」は,ゲームエンジンと何も関係ありません。

性能にこだわるならマシン上のGPUデバイスをPCIパススルーによって特定のホストに専有させたり,Intel GVT-gを用いてホストとゲストでGPUを共有する方法などを検討してください※3⁠。今回紹介する方法は「ホスト側に特別な設定やハードウェアの準備を行うことなく,気軽にゲストOSでGPUアクセラレーションを動かせる」ことがメリットになります。

※3
ゲストOSにWindowsを使いたい場合も,Virgil 3Dは利用できません。これはWindows側のドライバーをvirtio-gpuに対応させる必要があるためです。

3D GPUを有効化する方法

さっそくQEMUを使って3D GPUを有効化してみましょう。まずあらかじめ,QEMU関連のパッケージをインストールしておきます。実施するホストマシンはUbuntu 19.04以上であればどれでも問題ありません。Ubuntu 19.10だとカーネルの更新により仮想化まわりの修正がいくつか入っているようなので,19.10のほうが良いでしょう。Ubuntu 18.04 LTSでUbuntu Cloud ArchiveのSteinかTrainを有効化するという手もあります。

$ sudo apt install qemu-system-x86 qemu-utils

またデスクトップ版のインストールイメージもダウンロードしておきます。

$ wget http://jp.releases.ubuntu.com/eoan/ubuntu-19.10-desktop-amd64.iso

こちらもUbuntu 19.10を使っていますが,少なくともvirtio-gpuに対応したMesa 11.1以降とLinux Kernel 4.4以降であれば,どのディストリビューションでも動くはずではあります。ただしUbuntuの場合,条件を満たす16.04(Kernel 4.4,Mesa 11.2)では起動の途中でエラーとなり,16.04.2(Kernel 4.8,Mesa 12.0)では若干不安定で,16.04.3(Kernel 4.10,Mesa 17.0)以降で安定するという状況でした。

次に仮想マシン用のイメージを作成しておいてください。ここではサイズを20GBにしていますが,Ubuntuをインストールできるならどのサイズでもかまいません。

$ qemu-img create -f qcow2 ubuntu.qcow2 20G

では,さっそく仮想の3D GPUを有効化した仮想マシンを立ち上げてみましょう。

$ qemu-system-x86_64 \
    -enable-kvm -M q35 -smp 2 -m 4G \
    -drive format=qcow2,file=ubuntu.qcow2,if=virtio \
    -net nic,model=virtio \
    -net user,hostfwd=tcp::2222-:22 \
    -vga virtio \
    -display gtk,grab-on-hover=on,gl=on \
    -boot once=d -no-reboot -cdrom ubuntu-19.10-desktop-amd64.iso

それぞれのオプションは次のとおりです。

  • -enable-kvm:CPUの仮想化支援機能を有効化します。
  • -M q35:マシンタイプをICH9なQ35チップセットにします。
  • -smp 2:CPUの数を2にしています。いくつでもかまいません。
  • -m 4G:メモリのサイズを4GBにしています。Ubuntuデスクトップが動くならいくつでもかまいません。
  • -drive format=qcow2,file=ubuntu.qcow2,if=virtio:ディスクイメージを指定しています。こちらもvirtioフレームワークを利用しています。
  • -net nic,model=virtio:NICもvirtioを利用します。ディスクも含めて,使用しなくても3D GPUの利用には問題ありません。
  • -net user,hostfwd=tcp::2222-:22:ホストの2222番ポートがゲストの22番ポートに転送されるための設定です。SSHでホストからゲストにアクセスしたい際に便利です。
  • -vga virtio:VGAカードのエミュレーションとしてvirtioを指定しています。今回のキモその1です
  • -display gtk,grab-on-hover=on,gl=on:仮想マシンの画面を表示するウィンドウとしてGTKを指定しています。今回のキモその2です
  • -boot once=d:1度だけCD-ROMドライブから起動するよう指定しています。
  • -no-reboot:ゲストを再起動した時,再起動せずに終了します。インストール時に便利なオプションです。
  • -cdrom ubuntu-19.10-desktop-amd64.iso:CD-ROMドライブ用イメージを指定しています。

上記を読めばわかるように,今回のポイントは-vga virtio -display gtk,grab-on-hover=on,gl=onの部分です。

-vgaにてvirtioを指定します。結果としてQXLは使えません。一応SPICEでvirtio-gpuにアクセスできるようですが,あくまでローカルマシン内部に完結する必要があります。リモートデスクトップでVirgil 3Dをサポートする案もあるものの,現状どうなっているかは不明です。

-displayはgtkがsdlのいずれかを指定します。ただしUbuntuのパッケージリポジトリにあるQEMUの場合,古くなったSDL1.xがアーカイブから削除されたものの,SDL2がまだ安定していなかったためにSDLのサポートを切っています。よって使えるのは事実上GTKだけです※4⁠。

※4
この判断が下されたのがおおよそ2018年ぐらいなので,20.04では状況が変わるかもしれません。ただし,まずはSDL2をmainコンポーネントに格上げする必要があります。どうしてもSDLを使いたいなら,snap版のqemu-virgilを使うという手もあります。

しかしながらGTKディスプレイにはマウスカーソルが表示されないという不具合が存在します。これは要するに「Alt-Ctrl-G」でマウスイベントをゲストウィンドウ内部に「つかんだ」時に,カーソルが表示されなくなるという話です。実際にはマウスイベントは届いていますので,クリック等は動作します。この不具合に対する回避策として指定しているのがgrab-on-hover=onです。このオプションを指定すると「Alt-Ctrl-G」で明示的につかむ状態にしなくても,ホストのマウスカーソルをQEMUのウィンドウ上にもってくるだけで,つかんだ場合と同じ状態にできます。このときのマウスカーソルの描画はホストが担当するので,消えることもありません。もちろんつかんだ状態なので,Alt-Tabのようなキーイベントもゲスト内部にのみ届きます。

最後に指定しているgl=onが3Dアクセラレーションの有効化です。これを指定した場合のみ,ゲスト内部で3D GPUを利用できます。

オプションを把握したところで,とりあえずUbuntuをインストールしましょう。Ubuntuのインストールが完了したら再起動します。-no-rebootオプションを指定していたらQEMUプロセスが終了しますので,次のようにインストール用に指定していたオプションを外して「再起動」してください。

$ qemu-system-x86_64 \
    -enable-kvm -M q35 -smp 2 -m 4G \
    -drive format=qcow2,file=ubuntu.qcow2,if=virtio \
    -net nic,model=virtio \
    -net user,hostfwd=tcp::2222-:22 \
    -vga virtio \
    -display gtk,grab-on-hover=on,gl=on

ちなみに上記はBIOSモードで起動しています。第441回「QEMU/KVMでUEFIファームウェアを使う」で詳しく紹介したOVMFを利用したUEFIモードで起動した場合も,3D GPUを利用可能です。ただし,Ubuntu 19.10のOVMFイメージはVGAを利用できない問題が存在します。具体的には起動時にディスプレイ画面に「Guest has not initialized the display (yet).」と表示されるのです。問題となるのは「/usr/share/ovmf/OVMF.fd」だけです。⁠/usr/share/OVMF/OVMF_CODE.fd」「/usr/share/OVMF/OVMF_VARS.fd」は問題ありませんので,そちらを使うようにしてください。2020年4月にリリース予定のUbuntu 20.04 LTSでは修正されている見込みです。

実際にUEFIモードで起動するには,たとえばインストール時は次のように-driveオプションをpflash用に2行追加します。なお,BIOSモードでインストールした仮想マシンイメージをUEFIモードで起動することはできませんので,UEFIで利用したいならあらためてインストールし直しましょう。

$ cp /usr/share/OVMF/OVMF_VARS.fd vars.fd
$ qemu-system-x86_64 \
    -enable-kvm -M q35 -smp 2 -m 4G \
    -drive if=pflash,format=raw,readonly,file=/usr/share/OVMF/OVMF_CODE.fd \
    -drive if=pflash,format=raw,file=vars.fd \
    -drive format=qcow2,file=ubuntu.qcow2,if=virtio \
    -net nic,model=virtio \
    -net user,hostfwd=tcp::2222-:22 \
    -vga virtio \
    -display gtk,grab-on-hover=on,gl=on \
    -boot once=d -no-reboot -cdrom ubuntu-19.10-desktop-amd64.iso

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member株式会社 創夢所属。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。