前回は、KVM環境でGPUパススルーをする方法について構築手順を紹介しました。
しかしながら、環境によってはいくつかの要因が重なり手順どおりにはいかないことがあります。
ここでは、KVM仮想マシンでGPUパススルーが動作しない または 不安定なときの確認ポイントを紹介いたします。
BIOSのバージョン確認
BIOSの不具合等により最新のGPUカードが正しく認識しないことがあります。メーカーのリリースノート等を確認し、該当しそうな不具合が見つかったら最新版のBIOSへアップデートします。
BIOSの設定確認
複数のGPUを利用する場合、4GB以上のMemory mapped I/O addressがサポートされていないとホストシステム上でGPUカードが正しく認識されないことがあります。
BIOSの設定にabove 4G decodingという項目がある場合は設定を有効にします。
KVM仮想マシンのチップセット設定
仮想マシンのOSがLinuxでGPUパススルーを利用する場合はQ35が安定すると言われています。仮想マシンを作成するとき、特別な理由がない限りチップセットはQ35を選択することを推奨します。
(参考:https://wiki.lime-technology.com/UnRAID_Manual_6#Creating_Your_Own_Virtual_Machines)
KVM仮想マシンのCPUモード設定
仮想マシンのCPUモードが適切なものに設定されていないと仮想マシン上でGPUが正しくに動作しない場合があります。ライブマイグレーション機能を利用しない場合は "host-model" にすることを推奨します。
$ virsh edit [仮想マシン名] ### CPU Mode 設定例 ### <cpu mode='host-model'> <model fallback='allow'/> </cpu>
KVMホスト側の設定
PCI Expressでのデータ破損を防止するACS(Access Control Service)が有効になっていると、KVM環境では逆に不具合の要因となる場合があります。動作が不安定なときは /etc/libvirt/qemu.conf (Ubuntu 16.04の場合)を開き、以下の設定を加えてACSを無効化してみます。
relaxed_acs_check = 1
認識されているPCI Expressの世代の確認
GPUが想定していたほど性能を出していないときは、ホスト上でPCI Expressの世代が低く認識されていたり、何らかの理由でPCI Expressの転送速度が落ちている場合があります。まずは PCI Express の世代が正しく認識されているか確認します。
$ nvidia-smi -q --- コマンド結果から抜粋 --- GPU Link Info PCIe Generation Max : 3 Current : 3 Link Width Max : 16x Current : 16x Bridge Chip Type : N/A Firmware : N/A Replays since reset : 0 Tx Throughput : 0 KB/s Rx Throughput : 0 KB/s
ここで仮想マシン上の環境では結果がGen1となっていた場合でも、物理マシン上では本来の世代で認識されていて、転送スピードを測定するとGen1の規定値以上になることがあります。次項を参考にバススピードも測ってみます。
GPUバススピードの確認方法
バススピードの実測値を測定して適切な値となるか確認します。 前回も軽く触れましたが、バススピード測定ツールはCUDAに添付されているサンプルプログラムに含まれているので、それを実行してみます。
### サンプルプログラムをまだコンパイルしていない場合は make を実行 $ cd ~/NVIDIA_CUDA-8.0_Sample $ make ### バススピードの測定 $ cd ~/NVIDIA_CUDA-8.0_Samples/bin/x86_64/linux/release/ $ ./bandwidthTest <出力例> [CUDA Bandwidth Test] - Starting... Running on... Device 0: Tesla P40 Quick Mode Host to Device Bandwidth, 1 Device(s) PINNED Memory Transfers Transfer Size (Bytes) Bandwidth(MB/s) 33554432 11537.8 Device to Host Bandwidth, 1 Device(s) PINNED Memory Transfers Transfer Size (Bytes) Bandwidth(MB/s) 33554432 12961.7 Device to Device Bandwidth, 1 Device(s) PINNED Memory Transfers Transfer Size (Bytes) Bandwidth(MB/s) 33554432 240433.7 Result = PASS NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.
実測値が1世代前の制限値より低い場合は、ハードウェアやソフトウェアに何らかの問題が起きている可能性があります(ハードウェアの相性問題であることもあります)。
各世代の制限値(一方向)
- Gen1: 4.0 GB/sec
- Gen2: 8.0 GB/sec
- Gen3: 16.0 GB/sec
- Gen4: 32.0 GB/sec
(参考:https://ja.wikipedia.org/wiki/PCI_Express)
ベンチマーク
バススピードに問題がない場合は、GPUへ直接負荷をかけてみます。ベンチマークを長時間稼働させたとき、処理数が一定量で増えない場合はなんらかの問題が発生していると考えられます。ベンチマークツールの一つとして、GPU Burnを紹介します。
なお、実行する際にはGPUの温度の変化に注意して下さい。
<実行例> $ ./gpu_burn 60 GPU 0: Tesla P40 (UUID: GPU-1f4d9f28-51e7-065d-2db9-af4397809c49) Initialized device 0 with 22912 MB of memory (22552 MB available, using 20297 MB of it), using FLOATS 13.3% proc'd: 3798 (9453 Gflop/s) errors: 0 temps: 51 C Summary at: Tue Dec 19 11:47:57 JST 2017 25.0% proc'd: 7596 (9443 Gflop/s) errors: 0 temps: 54 C Summary at: Tue Dec 19 11:48:04 JST 2017 40.0% proc'd: 12660 (9438 Gflop/s) errors: 0 temps: 58 C Summary at: Tue Dec 19 11:48:13 JST 2017 51.7% proc'd: 16458 (9444 Gflop/s) errors: 0 temps: 60 C Summary at: Tue Dec 19 11:48:20 JST 2017 63.3% proc'd: 20256 (9451 Gflop/s) errors: 0 temps: 60 C Summary at: Tue Dec 19 11:48:27 JST 2017 75.0% proc'd: 24054 (9441 Gflop/s) errors: 0 temps: 61 C Summary at: Tue Dec 19 11:48:34 JST 2017 90.0% proc'd: 29118 (9446 Gflop/s) errors: 0 temps: 63 C Summary at: Tue Dec 19 11:48:43 JST 2017 100.0% proc'd: 32916 (9440 Gflop/s) errors: 0 temps: 64 C Killing processes.. done Tested 1 GPUs: GPU 0: OK
Kernelログの調査
NVIDIAドライバでなんらかしらの問題が発生したとき、syslogへXidメッセージが出力されることがあります。XidメッセージにはIDが振られており、そのIDを元に公式ドキュメントを調べることでメッセージの詳細を得ることができます。
<出力例> NVRM: Xid (PCI:0000:00:09): 32, Channel ID 0000000e intr 00008000
上記の場合、Xidは32になります。
モジュールパラメーターの設定・確認
環境によってはNVIDIAドライバのモジュールパラメータを指定することで改善される場合があります。パラメーターの項目はNVIDIAドライバのヘッダーファイル内にドキュメントがあります。
現在のパラメータの設定は以下のコマンドで確認することができます
$ cat /proc/driver/nvidia/params
パラメータを任意の値に設定するにはUbuntuの場合、以下の手順で設定します。
1. パラメーターの指定
nvidiaモジュールの設定ファイルを新たに作成します。
- ここでは、パラメータ NVreg_CheckPCIConfigSpace=0 と NVreg_EnableMSI=1 を設定しています。
- XXXにはNVIDIAドライバーのバージョンが入ります。
$ vi /etc/modprobe.d/nvidia-params.conf # ←ファイルは新規に作成します --- ファイル内容 --- options nvidia_XXX NVreg_CheckPCIConfigSpace=0 NVreg_EnableMSI=1 --- ここまで ---
2. Initramfsの更新
$ update-initramfs -u
3. VMの再起動
$ sudo shutdown -r now