Windows11+WSL2+GPUでDeep Learning環境構築

この記事は[Future Advent Calender 2021](https://qiita.com/advent-calendar/2021/future) 14日目の記事です。

# はじめに
みなさんWindsows11使ってますか？僕は自作PCが趣味で、2021年11月に発売されたIntel第12世代CPUで1台組みました！
Intel第12世代CPUことAlder Lake-SはHeterogeneous Core（異種混合コア）と呼ばれるコアアーキテクチャが採用されており、これはWindows11で最適化されていることもあり、導入しました。

組んだパソコンはこちらです！
![IMG_2091.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/347208/fe4bd79f-907a-cf4d-9a8a-f5eab8042e4e.jpeg)

どでかいケースで最高に光ってます...！

主なスペックは以下です。

* CPU：Intel Core i9 12900KF
* GPU：GeForce RTX 3080Ti
* メモリ：DDR5 32GB

さて、こんなハイエンドPCを組んで何をするのかというと、PCゲームとディープラーニングです。
特にディープラーニングは強力なGPUが必要になりますし、最近はハイパーパラメータの探索を並列に行えるライブラリなども充実しているということで、CPUのコア数も重要になってきます。ちなみに12900KFは16コア24スレッドです。
このPCならその性能を存分に発揮してくれることでしょう！

それでは前置きはこの辺にして、環境構築していきたいと思います！

# 環境構築手順
Windows11で分散並列GPU深層学習環境を構築します。
今回導入するのもは以下になります。

1. WSL2
2. NVIDIAグラフィックドライバ
3. CUDA
4. NVIDIA Docker
5. cuDNN
6. Python3
7. PyTorch

## WSL2のインストール
まずはWindows11にWSL2をインストールしていきます。インストールはWindows Power Shellを使います。
WSL2にインストール可能なLinuxディストリビューションは以下のコマンドで確認できます。

```powershell
> wsl --list --online
インストールできる有効なディストリビューションの一覧を次に示します。
'wsl --install -d <Distro>' を使用してインストールします。

NAME            FRIENDLY NAME
Ubuntu          Ubuntu
Debian          Debian GNU/Linux
kali-linux      Kali Linux Rolling
openSUSE-42     openSUSE Leap 42
SLES-12         SUSE Linux Enterprise Server v12
Ubuntu-16.04    Ubuntu 16.04 LTS
Ubuntu-18.04    Ubuntu 18.04 LTS
Ubuntu-20.04    Ubuntu 20.04 LTS
```

今回は`Ubuntu20.04`をインストールします。

```powershell
> wsl --install -d Ubuntu-20.04
```

このコマンド一発でインストール完了です。

※以前はWSLのインストール前に`Windowsの機能の有効化または無効化`の設定が必要でした。しかし今回これを行ってからWSLをインストールしようとするとうまくいかなかったため、注意してください。

## NVIDIAグラフィックドライバのインストール
**グラフィックドライバはWindows側にインストールします。**僕のおすすめはGeForce Experienceによるインストールです。
GeForce Experienceとは、NVIDIAのGeForce製品群のグラフィックドライバの管理及び各種PCゲームへの最適化や録画機能などを提供するユーティリティです。
最新のドライバのチェックからインストールまで、GUIで手軽に行うことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/347208/be69eb22-6788-f154-e803-172ca11c43fb.png)

ダウンロードは以下のサイトです。

* [GeForce Experienceダウンロードページ](https://www.nvidia.com/ja-jp/geforce/geforce-experience/)

GeForce Experienceをインストールすると同時にグラフィックドライバもインストールされます。


## CUDAのインストール
グラフィックドライバがインストールできたらCUDAをインストールします。
以下のサイトから手元のシステムに合わせて項目を選択していくと、それに合わせてコマンドをサジェストしてくれます。

* [CUDA Toolkitダウンロードページ](https://developer.nvidia.com/cuda-downloads)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/347208/d1e6defb-43b5-2d3e-116f-0742f91b929b.png)

出てきたコマンドを実行していきます。

```bash
$ wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin
$ sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600
$ wget https://developer.download.nvidia.com/compute/cuda/11.5.1/local_installers/cuda-repo-wsl-ubuntu-11-5-$ local_11.5.1-1_amd64.deb
$ sudo dpkg -i cuda-repo-wsl-ubuntu-11-5-local_11.5.1-1_amd64.deb
$ sudo apt-key add /var/cuda-repo-wsl-ubuntu-11-5-local/7fa2af80.pub
$ sudo apt-get update
$ sudo apt-get -y install cuda
```

インストールが完了したらCUDAのサンプルプログラムを実行して動作確認します。

```bash
$ cd /usr/local/cuda-11.5/samples/4_Finance/BlackScholes
$ make BlackScholes
$ ./BlackScholes

Initializing data...
...allocating CPU memory for options.
...allocating GPU memory for options.
...generating input data in CPU mem.
...copying input data to GPU mem.
Data init done.

Executing Black-Scholes GPU kernel (131072 iterations)...
Options count             : 8000000
BlackScholesGPU() time    : 0.207633 msec
Effective memory bandwidth: 385.295561 GB/s
Gigaoptions per second    : 38.529556
```

無事に終了すればCUDAの動作は問題ありません。

## NVIDIA Dockerのインストール
NVIDIA DockerはGPUの分散並列処理を行うために必要になります。
DockerでGPUが使えるように設定していきます。

まずはDockerをインストールします。

```bash
$ curl https://get.docker.com | sh 
```

次にNVIDIA Dockerをインストールします。

```bash
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

$ sudo apt-get update
$ sudo apt-get install -y nvidia-docker2    
```

インストールが完了したらDockerを再起動します。

```bash
$ sudo service docker stop
$ sudo service docker start
```

最後にサンプルプログラムを実行して動作確認します。

```bash
$ 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: "Turing" with compute capability 7.5

> Compute 7.5 CUDA device: [NVIDIA GeForce RTX 2080]
47104 bodies, total time for 10 iterations: 68.445 ms
= 324.169 billion interactions per second
= 6483.371 single-precision GFLOP/s at 20 flops per interaction
```

無事に終了すればNVIDIA Dockerの動作は問題ありません。
これでDockerコンテナ内でGPUが使えるようになりました。

## cuDNNのインストール
cuDNNはNVIDIAが提供しているディープラーニング用のライブラリです。
ニューラルネットワークの計算が高速化されるため、ディープラーニングをする方は必須のライブラリです。以下のサイトからダウンロードします。

* [cuDNNダウンロードページ](https://developer.nvidia.com/cudnn)

なお、ダウンロードするにはNVIDIA Developer Programに参加する必要があります。

ダウンロードが完了したら下記のコマンドを実行していきます。
ダウンロードファイルはLinux側のホームディレクトリに配置するとわかりやすいと思います。
`x, X, Y`については手元のバージョンに合わせてください。

まずはアーカイブファイルの解凍と配置を行います。

```bash
$ tar -xvf cudnn-linux-x86_64-8.x.x.x_cudaX.Y-archive.tar.xz
$ sudo cp cudnn-*-archive/include/cudnn*.h /usr/local/cuda/include 
$ sudo cp -P cudnn-*-archive/lib/libcudnn* /usr/local/cuda/lib64 
$ sudo chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*
```

次にインストールを行っていきます。

```bash
$ sudo dpkg -i cudnn-local-repo-${OS}-8.x.x.x_1.0-1_amd64.deb
$ sudo apt-key add /var/cudnn-local-repo-*/7fa2af80.pub
$ sudo apt-get update
$ sudo apt-get install libcudnn8=8.x.x.x-1+cudaX.Y
$ sudo apt-get install libcudnn8-dev=8.x.x.x-1+cudaX.Y
$ sudo apt-get install libcudnn8-samples=8.x.x.x-1+cudaX.Y
```

最後にcuDNNの動作確認を行います。

```bash
$ cp -r /usr/src/cudnn_samples_v8/ $HOME
$ cd  $HOME/cudnn_samples_v8/mnistCUDNN
$ make clean && make
$ ./mnistCUDNN
```

MNISTデータセットの分類問題を解くサンプルプログラムが動きます。
`Test passed!`と表示されればインストール完了です。

## Pythonのインストール
LinuxにはデフォルトでPython2がインストールされています。
今回はpyenvを使ってPython3.9.8をインストールします。※PyTorchはまだPython3.10に未対応でした。

まずはpyenvをインストールします。
インストールするにはあらかじめLinuxの依存パッケージをインストールする必要があります。

```bash
$ sudo apt-get update; sudo apt-get install make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
```

次にpyenvを任意のディレクトリにcloneします。

```bash
 git clone https://github.com/pyenv/pyenv.git ~/.pyenv
```

環境変数を設定します。

```bash
$ sed -Ei -e '/^([^#]|$)/ {a \
export PYENV_ROOT="$HOME/.pyenv"
a \
export PATH="$PYENV_ROOT/bin:$PATH"
a \
' -e ':a' -e '$!{n;ba};}' ~/.profile

$ echo 'eval "$(pyenv init --path)"' >>~/.profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc
```

これでpyenvの設定は完了です。

続いてpyenvでPythonをインストールします。
インストール可能なPythonのバージョンは次のコマンドで確認することができます。

```bash
$ pyenv install --list
```

今回はPython3.9.8をインストールします。

```bash
$ pyenv install 3.9.8
$ pyenv global 3.9.8
```

これでPython3.9.8のインストールが完了し、pyenv上のデフォルトバージョンの設定も完了しました。

## PyTorchのインストール
続いてPyTorchをインストールします。以下のサイトにアクセスし、手元の環境に合った項目を選択していくことで、インストールコマンドをサジェストしてくれます。

* [PyTorchダウンロードページ](https://pytorch.org/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/347208/6664af36-7fbc-516a-faf2-fc24721dc1f3.png)

出てきたコマンドを実行すればPyTorchがインストールされます。

最後にPyTorchがGPUとその関連パッケージを利用可能かを確認します。
Pythonで以下のスクリプトを実行します。

```python
import torch

# PCのGPUの個数が表示されればOK
print(torch.cuda.device_count())

# Trueと表示されればOK
print(torch.cuda.is_available())

# Trueと表示されればOK
print(torch.backends.cudnn.enabled)
```

全てOKであればインストール完了です。

# おわりに
今回は最新のハードウェアと最新のOSでGPU深層学習環境を構築しました。
組み立ててから1か月ほど経ちますが、PCゲームもディープラーニングも今のところ安定して稼働しています。
これからWindows11でGPU機械学習環境を構築する方の参考になれば幸いです！

最後までご覧いただきありがとうございました！