仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

KVMでGPUパススルーを使った仮想マシンを構築

最近のGPU性能は著しく向上しており、GPUのグラフィック処理以外での利用(GPGPU)が増えてきています。とくにディープラーニングやデータマイニングなど、人工知能分野での利用が大きな注目を集めております。

KVM仮想マシン上でGPUを利用する方法の一つとしてPCIパススルーを利用する方法があります。ここではUbuntu 16.04でKVMの構築方法と仮想マシンでUbuntu 16.04の環境を作成方法までを紹介いたします。

前提条件

KVMホストとなるサーバーへUbuntu 16.04 Serverと仮想マシンマネージャーをインストールしておいて下さい。仮想マシンマネージャのインストールは別のマシンでも構いません。仮想マシンマネージャの詳細については以下のサイトを参照して下さい。

環境構築手順

1. 事前準備

KVMホストとなるマシンへKVMとLinuxブリッジをインストールします。

$ sudo apt install libvirt0 qemu-kvm libvirt-bin virt-manager bridge-utils

Ubuntu server 16.04 のISOイメージをダウンロードします。

$ wget http://releases.ubuntu.com/16.04/ubuntu-16.04.3-server-amd64.img
$ sudo mv ./ubuntu-16.04.3-server-amd64.img /var/lib/libvirt/images

2. 仮想マシンの作成

仮想マシンを作成する前に、GPUに割り当てられているPCIアドレスと接続状況の確認します。

$ lspci | grep -i nvidia
03:00.0 3D controller: NVIDIA Corporation Device 1b38 (rev a1)

$ virsh nodedev-list --tree

<出力結果の一部>
  +- pci_0000_00_02_0
  |   |
  |   +- pci_0000_03_00_0
  |

virt-installコマンドを使って仮想マシンを作成します。

$ virt-install --accelerate --hvm \
    --connect qemu:///system \     # 接続先(ローカルの場合)
    --name gpuvm01 \               # 仮想マシン名
    --vcpus 1 \                    # 仮想CPU
    --ram 2048 \                   # メモリサイズ
    --file-size 24 \               # 仮想ディスク
    --network type=direct,source=eno1,model=virtio \ # ネットワーク
    --file "/var/lib/libvirt/images/gpuvm01.img" \
    --os-variant ubuntu16.04 \     # OSの種類
    --boot hd,cdrom,menu=on \
    --cdrom "/var/lib/libvirt/images/ubuntu-16.04.3-server-amd64.img" \
    --machine q35 \                # チップセットを Q35 に設定
    --host-device=pci_0000_03_00_0 # GPUを指定

3. 仮想マシンへUbuntu Server 16.04をインストール

仮想マシンマネージャを使って作成した仮想マシンへUbuntu Server 16.04をインストールします(仮想マシンマネージャの使用方法についてはここでは省略します)。

  • 仮想マシンマネージャを起動します。
  • [ファイル] - [新しい仮想マシン] を開き、KVMホストへ接続します。
  • 作成した仮想マシンを起動します。
  • 仮想マシンのコンソールを開きインストーラーを進めます。

4. 仮想マシンへNVIDIAドライバーをインストール

GPUが仮想マシン上で認識されていることを確認します

$ lspci | grep -i nvidia

aptへリポジトリを追加し、NVIDIAドライバーをインストールします。

$ sudo add-apt-repository ppa:graphics-drivers/ppa
$ sudo apt update
$ apt-cache search '^nvidia-[0-9]+'
$ sudo apt install nvidia-XXX
$ sudo reboot

再起動後、nvidia-smiコマンドでGPUのステータスが出力されることを確認します。

$ nvidia-smi -q

5. CUDAのインストール

NVIDIAのサイトへアクセスし、CUDAをダウンロードします https://developer.nvidia.com/cuda-downloads

CUDAをインストールします

$ dpkg -i cuda-repo-ubuntu1604-8-0-local-ga2_8.0.61-1_amd64.deb
$ sudo apt update
$ sudo apt install cuda

CUDAのインストールが正常に完了したら、サンプルプログラムをコンパイルします。

$ export PATH=/usr/local/cuda/bin${PATH:+:${PATH}}
$ export LD_LIBRARY_PATH=/usr/local/cuda/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
$ ./cuda-install-samples-8.0.sh ~
$ cd ~/NVIDIA_CUDA-8.0_Samples
$ make

Tips

サンプルプログラムの一つcudaDecodeGLのコンパイルは、インストールされているnvidiaドライバのバージョンと UBUNTU_PKG_NAME の値が合っていないとmakeに失敗します。 失敗した場合は正しい値に修正し、もう一度実行します。

$ vi 3_Imaging/cudaDecodeGL/findgllib.mk

<編集>
UBUNTU_PKG_NAME = "nvidia-384"

動作確認

サンプルプログラムの一つである bandwidthTest を実施してみます。プログラムが正しくコンパイルできたことと、バススピードが妥当な値であることを確認します。

$ ~/NVIDIA_CUDA-8.0_Samples/bin/x86_64/linux/release/bandwidthTest

<出力結果例>
[CUDA Bandwidth Test] - Starting...
Running on...

 Device 0: GeForce GTX TITAN
 Quick Mode

 Host to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)    Bandwidth(MB/s)
   33554432         11437.2

 Device to Host Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)    Bandwidth(MB/s)
   33554432         13225.2

 Device to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)    Bandwidth(MB/s)
   33554432         227939.5

Result = PASS

トラブルシューティング

うまく動作しなかった場合の対処法について、別エントリで紹介いたします。

tech.virtualtech.jp