状態
- KVM PCIパススルー(VFIO)でVMにGPUをパススルーして使用していたがCUDA9.1ぐらいから動かなくなった
- CUDAドライバやライブラリの組み合わせは合っている
- 仮想化を使用せず、ベアメタルであれば問題なく動く
- nvidia-smiは通常通り動く
- deviceQueryなどRead系CUDA API?は動く
- 実際に計算等を行おうとすると以下のようなエラーが出る
code=46(cudaErrorDevicesUnavailable)
解決策
その1: ドライバのバージョンを下げる
調べた結果、特定のバージョン以降のドライバから上記のエラーが出て使えなくなっていた
この状況で手元で動作が確認できたドライバは下記
- CUDA 9.1
- 387.26
- CUDA 9.0
- 384.81
- CUDA 8.0
- 384.66
基盤に触れない場合は上記のバージョンのドライバを使う
その2: VMのcpu modeをhost-modelにする
ハイパーバイザーでlibvirtを使っていれば、XMLを下記のように書き換える
before
<cpu>
<topology sockets='40' cores='1' threads='1'/>
</cpu>
after
<cpu mode='host-model'>
<model fallback='allow'/>
<topology sockets='40' cores='1' threads='1'/>
</cpu>
上記を書き換えてdefineしなおして再起動することでVMのCPU modelがQEMU Virtual CPUからハイパーバイザと同じものになる
before
$ cat /proc/cpuinfo | grep -e model -e flags
model : 13
model name : QEMU Virtual CPU version 2.5+
flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pse36 clflush mmx fxsr sse sse2 syscall nx lm rep_good nopl pni vmx cx16 x2apic popcnt hypervisor lahf_lm vnmi ept
after
$ cat /proc/cpuinfo | grep -e model -e flags
model : 61
model name : Intel Core Processor (Broadwell)
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch tpr_shadow vnmi flexpriority ept vpid fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt arat
これで新しいドライバでも動くようになる
代わりにVMのCompatibilityが下がる(同じCPU modelでないとlive-migrationできないなど)がGPUをパススルーしているVMにはあまり関係ないだろう
原因(予想)
- Security Bulletin: NVIDIA Driver Security Updates for CPU Speculative Side Channel Vulnerabilities: https://nvidia.custhelp.com/app/answers/detail/a_id/4611/~/security-bulletin%3A-nvidia-driver-security-updates-for-cpu-speculative-side
VMでうまく動かなくなるあたりのドライバの更新でIntelの脆弱性対応がされている
これでドライバの仕様が変わったのではないかと考えている(PCID必須?)
おまけ
OpenStackを使っている場合はlibvirtのxmlが書き換えられてしまうので、該当Computeのnova.confを確認する
nova.conf
[libvirt]
cpu_mode = host-model