Win11上のUbuntu on WSL2 + dockerでGPUを使う

# 初めに

WindowsのPCでGPUが使える環境をなんとか仮想環境で実現しようといろいろ考えた結果タイトルのような構成になりました。

スペックは以下の通りです。
CPU: Corei7 (11th gen)
GPU: GeForce RTX3080
RAM: 16GB

ただし、動かしてみたところメモリは正直増設したほうがいいかもです。。。


手順はざっと以下の通りです。

1. Win11にアップデート
2. NVIDIAドライバーの導入
3. WSL2、Ubuntuのセットアップ
4. UbuntuにCUDA導入
5. Ubuntuにdocker導入
6. NVIDIAのdockerイメージを動かす

では早速行きます。

## 1. Win11にアップデート

この部分は調べれば色々出てくると思いますので、端折ります。
やることとしては

1. Win11入れるための要件のチェックと必要機能の有効化
2. Win11のインストール

となります。1でBIOSいじる必要性などが出てくるの可能性があり少々厄介ですが、頑張りましょう。

## 2. NVIDIAドライバーの導入

ゲーミングPCなら導入済みかと思います。
参考までに僕のバージョンはGeForce Game Ready Driver 496.76です。

## 3. WSL2、Ubuntuのセットアップ

以下のコマンドを管理者権限で実行したPowershellに打ち込むだけで導入可能だと思います。

```
wsl --install -d Ubuntu-20.04
```

Ubuntuが自動で起動するので、ユーザー名とパスワードを設定しましょう。

![ubuntu20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454070/feeee4be-c720-a313-929f-cb35fede2057.png)


一応、ちゃんと導入できているかPowershellのほうで下記コマンドで確認しましょう。

```
wsl -l -v
```
下記のように出力されれば大丈夫です。

```
  NAME            STATE           VERSION
* Ubuntu-20.04    Running         2
```

もし、表示が違っている場合は今インストールしたUbuntuをアプリと機能から探して一度アンインストールし、下記手順でWSL2にアップデートしたうえでUbuntu導入してみてください。

https://docs.microsoft.com/ja-jp/windows/wsl/install-manual

Ubuntuが導入できたら、後続の作業でいろいろ導入する際にエラーが起きないよう、少しだけ下準備をします。

まず、Ubuntuを起動します。exitなど打ち込んで閉じちゃった場合はタスクバーのアプリ検索をすれば出てきます。

![search.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454070/36d63fac-4ef8-3880-33f7-8d4bf79b77b2.png)

起動したら下記コマンドを入力しましょう

```bash
sudo vim /etc/wsl.conf
```

vimというエディタが起動するので```i```を打ち込むとINSERTモード（書き込むモード）に移行できます。左下がINSERTになっていることを確認しましょう。

![insert.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454070/cf17d4cf-ecc1-6f3c-b1ab-6497451df75d.png)

下記のような記述を追加します。余談ですが、ctrl+vでの貼り付けは受け付けてくれないので、コピーしたらubuntuのターミナル画面で右クリすればペーストできます。

```conf:/etc/wsl.conf
[network]
generateResolvConf = false

[boot]
command = "sudo echo 'nameserver 8.8.8.8' > /etc/resolv.conf"
```

追加したら、Escキーを押してINSERTモードから抜け出します。（左下からINSERTの文字が消えます）
その後`:wq`と入力（左下に入力が見えると思います）してEnterを押して保存、終了しましょう。wが保存、qが終了を意味します。

できたら、`exit`と打ち込んで一度閉じ、もっかいアプリを開きましょう。
下記のように打ち込むと、ちゃんとresolv.confが生成されていることを確認できると思います。

```bash
sudo cat /etc/resolv.conf
```

## 4. UbuntuにCUDA導入

先ほど導入したUbuntuにCUDAを導入します。ここで、一点留意してほしいのが
**WSL用のCUDAを導入する**ということです。

[ここ](https://developer.nvidia.com/cuda-toolkit-archive)からCudaを選んでインストールします。今回は11.3.0を入れます。

https://developer.nvidia.com/cuda-11.3.0-download-archive?target_os=Linux&target_arch=x86_64&Distribution=WSL-Ubuntu&target_version=2.0&target_type=deb_local

![スクリーンショット 2021-12-03 184423.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454070/d7a57c0c-be2e-c2be-eb41-3691dd31bd76.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.3.0/local_installers/cuda-repo-wsl-ubuntu-11-3-local_11.3.0-1_amd64.deb
sudo dpkg -i cuda-repo-wsl-ubuntu-11-3-local_11.3.0-1_amd64.deb
sudo apt-key add /var/cuda-repo-wsl-ubuntu-11-3-local/7fa2af80.pub
sudo apt-get update
sudo apt-get -y install cuda
```


## 5. Ubuntuにdocker導入

次に、dockerというアプリの導入を行います。簡単に言うと、dockerさえ入っていればどんなマシンで構築した環境でもすぐにほかのマシンでも再現できるというものです。

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グループに追加（ユーザーがdockerコマンドを使えるようにする）

```bash
sudo usermod -aG docker $USER
```

dockerの再起動を行いましょう

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


## 6. 実際にdockerイメージを動かす

下記を試しに動かしましょう。

```bash
sudo nvidia-docker run --rm -it --gpus all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark -numbodies=512000
```

GPUで計算が回りますので、下記のような表示ができれば完了です。あとはdockerに少し慣れるだけでいろんなことができるようになります。

![スクリーンショット 2021-12-03 190648.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454070/d1ee4744-7015-cfc1-ba9f-a1d429845b50.png)


ここで、じつはdockerはubuntu起動時に勝手に起動してくれないので、次回起動時にもdockerが自動で立ち上がるようにしましょう。
さっきの`wsl.conf`の内容が以下の通りになるように追記しましょう。

```bash
sudo vim /etc/wsl.conf
```


```conf:/etc/wsl.conf
[network]
generateResolvConf = false

[boot]
command = "sudo echo 'nameserver 8.8.8.8' > /etc/resolv.conf"
command = "sudo service docker start"
```

お疲れさまでした。