Hyper-V上のUbuntuでCUDAを導入する 準備編

（追記）Windows 10でこれを行うことは無理だということがわかりました。Windows Server 2016なら可能のようですが、手元にないので諦めます。

UbuntuでCUDAを利用する機会が多いのですが、ハードウェア関連の設定に失敗すると、最悪再インストールなど非常に時間を取られてしまいます。GPU、CUDAとも非常に進化が速く、少しバージョンアップするだけで動かなくなったりと、なるべく出来上がった環境を使いたいところです。
Windows環境をメインに、Linuxをサブでという場合でもGPUはシェアしたい、となり、Windows環境を壊したくないとなると安全策は仮想化でしょうか。Hyper-Vを使って手ごろにそのような、CUDA on Ubuntu on Hyper-V on Windowsの環境を作れないか、先人の知恵を参考にやってみたいと思います。

ハードウェア、Linux関連とも、間違いがあると思うので、ご指摘ください。
まず、目標と前提となる環境についてです。

# やりたいこと

とりあえず、現状の最新環境で使ってみようと思いました。

ホストOS：Windows 10 Pro (Creators Update) 15063.608
Hyper-V マネージャ：バージョン 10.0.15063.0
ゲストOS：Ubuntu 16.04
CUDAバージョン : 9.0

## システム要件

GPUドライバ、CUDAを仮想環境で動かすには、ハードウェア、ソフトウェアの対応が必要です。それぞれ、以下の情報が役に立つでしょうか？

[TensorFlow + CUDA > 実行環境の検討 / PCIパススルー対応かどうか](https://qiita.com/7of9/items/1208811c5a466e189b10)


### PCIパススルー/IOMMU 対応

IOメモリマッピングを仮想化できるように、[IOMMU](https://en.wikipedia.org/wiki/Input%E2%80%93output_memory_management_unit)をサポートするCPUが必要なようです。
もともとはグラフィックメモリのメインメモリへの拡張とかDMA経由のアタックとかに対処するためのもののようでしたが、仮想化に利用されるようです。ホストOSのIOをゲストOSにもIOMMU経由で見えるようにするものです。
[List of IOMMU-supporting hardware](https://en.wikipedia.org/wiki/List_of_IOMMU-supporting_hardware)

Intel でいうVT-dに相当し、対応リストを見るとCore2時代のCPUやチップセットから導入されているので、今時のPCなら大丈夫でしょう。

### RemoteFX 対応

RemoteFXはもともとVDIを用いたリモートグラフィックの規格ですが、これに対応するためには、[こちら](https://technet.microsoft.com/en-us/library/ff817602(WS.10).aspx)のようにCPU,GPUの対応が必要です。

CPUは Second-Level Address Translation (SLAT)対応が必要です。IntelCPUでは Extended Page Tables (EPT), AMD CPUでは Nested Page Tables (NPT)と呼ばれます。昨今のCPUではほぼ対応しています。

GPUは、DirectX 9.0c と DirectX 10.0のサポートが必要です。

ここまで書くと、何かLinuxには関係ないんじゃないかとも思えますが、いくつかLinux上での記述があるので、利用していると思われます。

### ※DDA?

最新のWindows Server 2016などでは、これに代わって、[DDA(Discrete Device Assignment)](https://docs.microsoft.com/en-us/windows-server/virtualization/hyper-v/plan/plan-for-deploying-devices-using-discrete-device-assignment)というものが導入されており、Windows/Linuxで仮想デバイスを実現するようです。NVMeデバイスなどのサポートも行われ、より高速なアクセスを実現するものだと思われます。

## GPUの仮想化とは

ところで、そもそもハイパバイザでの仮想GPU対応って、どこまで進んでいるんでしょうか？

仮想環境でのGPUの利用について、以下のようにまとめられています。従来は一度抽象化されたジェネリックなGPUドライバを利用していた（Shared GPU）が、ハードウェアのマッピングによりアクセラレーションの恩恵を受けられるようになるのがGPUパススルーやvGPUなどの機能です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/a441b287-bbef-ad78-ce67-0a7202e19712.png)

詳しくはわかりませんが、GPU Pass thruというのは1台のGPUを1つのVMに割り当てるシンプルな構成である一方、vGPUは1台のGPUをタイムシェアリングなどで複数のVMでシェアができるようです。クライアントで異なるゲストOSでもGPUを使いたいというような需要にはパススルーで十分です。

またことVDIに限っては、以下のようにパフォーマンスを考えるとパススルーの方が有利であるとも言えます。

[CAD on VDIを最大限に活用するための仮想化GPUガイド](http://www.cadjapan.com/topics/hard/150403_gpu.html)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/49cdfdde-4cfe-70d0-42f9-2db05698954e.png)

### 各ハイパバイザ、OSの対応

[こちら"State of GPU Virtualization for CUDA Applications 2014"](http://acceleware.com/blog/state-gpu-virtualization-cuda-applications-2014)のページに、整理されています。ですが、2014年なのでHyper-Vの状況はかなり変わっているようです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/a0c9bf28-01e2-f4a3-b0ba-cdc02cce4828.png)

Hyper-Vの弱点がこのPCIパススルーであるといわれている時期があったようですが、以下のように現在は対応しています。

[Windows Server 2016 Hyper-V on PCI-E パススルー](http://fanblogs.jp/formerse/archive/71/0)

GRIDなど仮想化用のハードウェアを使うとか、様々なソリューションがありますが、手元のPCでいろいろなOSでGPGPUをやりたいなどの向きにはHyper-Vを入れるだけで試せるのはいいですね。

（追記）調べたところ、上記パススルーは、Windows Server 2016固有のDDA機能を利用しており、Windows 10では無理でした。インストールもUbuntuにドライバを入れた時点で起動しなくなるという現象でした。