WSL2 + Docker Desktop + GPU で快適開発生活


本記事は著者である私、山田が人柱になるために記したレポートです。使用する環境のWindows10やDocker Destopはプレビュー版であることから必ずしも安定したパフォーマンスを提供できるとは限りません。しかし、プレビュー版へ参加していただける人が多ければ多いほどより多くのフィードバックが得られると思います。推奨することはできませんが、本記事を参考にお試しください。(矛盾)

#はじめに
今までもWSL2上のDockerでGPUを認識することはできました。(参考記事:[ついにWSL2+docker+GPUを動かせるようになったらしいので試してみる](https://qiita.com/yamatia/items/a70cbb7d8f5101dc76e9))
しかし、WSL2で動かしているLinux上にDockerやNvdia Container Toolkitをインストールしなければならず、そのひと手間が少し面倒でした。
なんとかDocker DesktopでGPUを使う方法を探していたところつい先日、2020年12月21日にDocker Desktopの[公式blog](https://www.docker.com/blog/wsl-2-gpu-support-is-here/)にてWSL2でのGPUをサポートするDocker Desktopのプレビュー版がリリースされたことを知りました。

公式の手順によると

- Windows10 Insider Preview Build Devチャンネルをインストールする
- Docker Desktopのプレビューバージョンをインストール 
- WSL 2 GPU paravirtualizationをサポートしてるNvidiaドライバーのベータ版をインストール
- Docker DesktopでWSL2 backendを有効にする

と手順はとても簡単だったので試してみることに

#環境構築
以下の作業は前述した従来のWSL2上のDockerでGPUを認識する手順にも必要です。

- Docker Desktopのプレビューバージョンをインストール 
- WSL 2 GPU paravirtualizationをサポートしてるNvidiaドライバーのベータ版をインストール

先人達が書かれた記事も多くあるので、そちらも参考にしてみてください。(参考記事:[待ってました CUDA on WSL 2](https://qiita.com/ksasaki/items/ee864abd74f95fea1efa))

## Windows10 Insider Preview Buildのインストール

Windowsの設定から更新とセキュリティ→Windows Insider Programを選択します Dev/ベータ/リリースプレビューとチャンネルがありますが
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598135/5b8dd7e5-9334-c700-7a30-18717f1954a4.png" width=60%>
**Devチャンネル**を選択してインストールしてください。(インストールには時間がかかります。)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598135/5e795881-e7a9-fe4c-d97c-01b72f796fa4.png" width=60%>
インストールされたらバージョンとビルドが変わってることを確認してください。(12/24 12時時点でのOSビルド)

## Docker Desktopのプレビューバージョンのインストール
[公式blog](https://www.docker.com/blog/wsl-2-gpu-support-is-here/)にて

>To get started with Docker Desktop with Nvidia GPU support on WSL 2, you will need to download our technical preview build from [here.](https://desktop.docker.com/win/preview/50723/Docker%20Desktop%20Installer.exe)

とあるので*here*をクリックしてDownload & install

## Nvidiaドライバーのベータ版をインストール
以下のリンクから、NVIDIA Driverをインストールします。
https://developer.nvidia.com/cuda/wsl
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598135/c17ad317-d533-775d-f1ee-3e0f79724c8b.png" width=60%>
使用しているGPUに合わせてDriverを選択してください。
私はGTX 1070(貧弱)なので左を選択しました。

NVIDIA Developer Program Membershipに登録(無料)していない場合登録してログインしないとダウンロードできないので注意してください.

## Docker DesktopでWSL2 backendを有効にする
Docker Desktop の設定から
Use the WSL 2 based engineにチェックを入れます
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598135/6bfeafde-805b-a686-982c-525d6a571a15.png" width=60%>

設定は以上！はいおしまい！
ね？簡単でしょ？？？？？？

# 動作確認
こんなに簡単で本当に動くのか心配になる方も多いと思います。
ですので一応テストしてみます。
wsl2のターミナル上で以下のコマンドを入力

```
docker run --gpus all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark
```

以下が出力

```
Run "nbody -benchmark [-numbodies=<numBodies>]" to measure performance.
        -fullscreen       (run n-body simulation in fullscreen mode)
        -fp64             (use double precision floating point values for simulation)
        -hostmem          (stores simulation data in host memory)
        -benchmark        (run benchmark to measure performance) 
        -numbodies=<N>    (number of bodies (>= 1) to run in simulation) 
        -device=<d>       (where d=0,1,2.... for the CUDA device to use)
        -numdevices=<i>   (where i=(number of CUDA devices > 0) to use for simulation)
        -compare          (compares simulation results running once on the default GPU and once on the CPU)
        -cpu              (run n-body simulation on the CPU)
        -tipsy=<file.bin> (load a tipsy model file for simulation)

NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.

> Windowed mode
> Simulation data stored in video memory
> Single precision floating point simulation
> 1 Devices used for simulation
GPU Device 0: "GeForce GTX 1070" with compute capability 6.1

> Compute 6.1 CUDA device: [GeForce GTX 1070]
15360 bodies, total time for 10 iterations: 11.862 ms
= 198.895 billion interactions per second
= 3977.901 single-precision GFLOP/s at 20 flops per interaction
```

ちゃんと読み込めてますね！
Tensorflowも一応確認

```
docker run -it --rm \
    --gpus all \
    --user root \
    --name tensorflow \
    -v $(pwd):/work/ \
    -w /work \
    tensorflow/tensorflow:latest-gpu-py3
```
--gpus all はつけないとGPUを読み込みません

pythonを起動して以下のコマンドを入力

```
from tensorflow.python.client import device_lib
device_lib.list_local_devices()
```

以下が出力

```
root@107eb1201f59:/work# python
Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from tensorflow.python.client import device_lib
vice_lib.list_local_devices()
2020-12-24 02:47:13.959067: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libnvinfer.so.6

~~~(中略)~~~

2020-12-24 02:47:15.627128: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1241] Created TensorFlow device (/device:GPU:0 with 6835 MB memory) -> physical GPU (device: 0, name: GeForce GTX 1070, pci bus id: 0000:02:00.0, compute capability: 6.1)
[name: "/device:CPU:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 7571817354991796130
, name: "/device:XLA_CPU:0"
device_type: "XLA_CPU"
memory_limit: 17179869184
locality {
}
incarnation: 1853203790404720057
physical_device_desc: "device: XLA_CPU device"
, name: "/device:XLA_GPU:0"
device_type: "XLA_GPU"
memory_limit: 17179869184
locality {
}
incarnation: 15262914756957364681
physical_device_desc: "device: XLA_GPU device"
, name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 7167590400
locality {
  bus_id: 1
  links {
  }
}
incarnation: 16971010008119807580
physical_device_desc: "device: 0, name: GeForce GTX 1070, pci bus id: 0000:02:00.0, compute capability: 6.1"
]
>>> 
```

device: 0, name: GeForce GTX 1070 という文字がありますね、ちゃんとGPUを読み込めてます。

#おわりに
これでWindowsでも快適開発生活がおくれます！すばら！

#参照記事
- [ついにWSL2+docker+GPUを動かせるようになったらしいので試してみる](https://qiita.com/yamatia/items/a70cbb7d8f5101dc76e9)
- [待ってました CUDA on WSL 2](https://qiita.com/ksasaki/items/ee864abd74f95fea1efa)
- [TensorFlowからGPUが認識できているかを2行コードで確認する](https://thr3a.hatenablog.com/entry/20180113/1515820265)
- https://www.docker.com/blog/wsl-2-gpu-support-is-here/