WindowsでCUDAが有効なWSL2でdockerコンテナでGoogleColaboratoryのローカルランタイムを用意

このドキュメントは、WindowsでWSL+dockerを使って、GoogleColaboratoryのローカルランタイム環境を用意する手順を列挙したものです。WSL+dockerについては、参考にさせていただいた、「[待ってました CUDA on WSL2](https://qiita.com/ksasaki/items/ee864abd74f95fea1efa)」とほぼおなじです。もともとはWindows11用に書きましたが、Windows10 21H2でもほぼ同様の手順でできそうです。（Windows10の場合、21H2まで上がっているか確認を忘れずに。）

# Windowsでの作業
## ドライバインストール
Windowsで[cuda on WSL用ドライバ](https://developer.nvidia.com/cuda/wsl)をインストール。GeForce用とQuadro用とあるので、自分の環境に併せて選ぶ。

* 再起動

## WSL上にUbuntu-20.04をインストール

* 管理権限PowerShell起動

Windowsアイコンを右クリックして「Windowsターミナル（管理者）」から起動

* 以下のコマンドでWSLをインストールする。

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

windows10ではコマンドプロンプトのメッセージで再起動をしろと言われるので、一度再起動。

* Ubuntu-20.04が自動起動

Ubuntu上でのユーザ名、パスワードを設定

#WSLのUbuntu20.04での作業
## dockerのインストール
* 以下のコマンドでインストール

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

## NVIDIA Container Toolkitのインストール

以下のシェルスクリプトファイル(nvidia-container-toolkit-installer.sh)を作成（待ってましたCUDA on WSL2より）

```nvidia-container-toolkit-installer.sh
#!/bin/sh

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
curl -s -L https://nvidia.github.io/libnvidia-container/experimental/$distribution/libnvidia-container-experimental.list | sudo tee /etc/apt/sources.list.d/libnvidia-container-experimental.list

sudo apt update
sudo apt install -y nvidia-docker2
sudo usermod -aG docker $USER
```
補足：Linuxで簡単なテキストファイルを作るには、viコマンドを使う。

以下のコマンドでファイルを生成しつつ開く。
* 上記をコピーしておく。
* [i]キーで入力モードにして、
* マウスを右クリックしてコピーしておいたテキストがペーストされる。
* ペースト後、[Esc]キーで入力モードから抜けてコマンドモードに戻る。
* [:]キーに続いて、wqと入力してエンターキーを押すと、保存してviを抜ける。

```
vi nvidia-container-toolkit-installer.sh
```

保存後、スクリプトを実行

```
sh nvidia-container-toolkit-installer.sh
```

## docker起動
以下のコマンドで起動。一度起動すれば、裏側でずっと動いている。Windowsを再起動したときは、起動しなおす必要がある。

```
sudo service docker start
```

dockerが裏で動いているかどうかは、以下のコマンドで確認。

```
docker ps
```

動いていないときは、エラーが出るはず。
エラーがunix:///var/run/docker.sockにアクセスできないてきなもののときは、sudo docker psを試してみる。これでちゃんとできる場合、以下のコマンドで、今のユーザからアクセスできるように設定する。その場合、一度、ubuntuプロンプトは閉じて上げなおす。

```
sudo usermod -a -G docker `whoami`
```


## 必要なライブラリが導入済みのdockerコンテナを持ってきて起動

* コンテナpull & run	

最新版がどれになるかは、[nvidiaのこのサイト](https://docs.nvidia.com/deeplearning/frameworks/tensorflow-release-notes/running.html)で確認。自身の環境に合わせて末尾の方の数字は変更するとよい。

```
docker run --gpus all --name tmpnvenv -it --rm nvcr.io/nvidia/tensorflow:21.10-tf2-py3
```

# nvcr.ioコンテナでの作業

## jupyter http ovber wsインストール

```
pip install jupyter_http_over_ws
```

## torchインストール	
tourchを使うなら。ファイルがでかいのでとっても時間がかかる。
[ダウンロード先](https://download.pytorch.org/whl/torch_stable.html)でバージョンがマッチする一番良いのを探すとよいかも。


```
pip install torch==1.10.0+cu113 torchvision==0.11.1+cu113 -f https://download.pytorch.org/whl/torch_stable.html
```

## /contentフォルダをリンク

colabでは、/contentが起動環境なので、それに合わせる。

```
mv /workspace /content
ln -s /content /workspace
```

## jupyterを動かすユーザを追加

```
useradd -m jupyter -s /bin/bash
```

## 実行ユーザになる

```
su - jupyter
```

## 必要なディレクトリ作成

```
mkdir -p .local/bin
```

## matplotlib,sklearnインストール

```
pip install matplotlib sklearn
```

他にも必要なものがあれば入れる。あとで、Colabからも入れられるので、あまり気にしなくてもよいかも。

## jupyter http ovber ws有効化

Colaboからローカルランタイムでjupyterにつなぐために必要。

```
jupyter serverextension enable --py jupyter_http_over_ws
```

## コンテナイメージをcommit
毎回、これらの作業をするのは面倒なので、ここまでの作業を終えたイメージを保存しておく。
別の、WSL端末を開き（Windowsのタスクバーにあるubuntuアイコンを右クリックして一番上のUbuntu...から開く）、そこから以下のコマンドを実行

```
docker commit tmpnvenv local/nvidia_tf_colab:1.0
```

一番右はイメージの名前なので、何でもよい。自分でバージョン管理してもよいよね。

## コンテナの終了処理
コンテナに入っている端末で、exitコマンドを2回実行。一般ユーザから抜ける分と、コンテナから抜ける分

```
exit
exit
```

#WSLのUbuntu20.04での作業

## コンテナを起動してjupyterを動かす

```
docker run --gpus all --rm -v /mnt/c/Users/ユーザ名/どっかのフォルダ:/content -p 8888:8888 -p 6006:6006 -p 4040:4040 -u jupyter -it local/nvidia_tf_colab:1.0 /bin/sh -c "jupyter notebook --NotebookApp.allow_origin='https://colab.research.google.com' --allow-root --port 8888 --NotebookApp.port_retries=0 --ip 0.0.0.0"
```

なぜか、生成されるURLはおかしいので、tokenをメモしてコピーしておく。

#GoogleColaboratoryからローカルランタイムとして使う

Colabで右上にある「接続」、「再接続」あるいは（すでに接続済みの場合は）「RAM...ディスク...」の右側にある▼をクリックして、「ローカルランタイムに接続」を選ぶ。「ローカル接続の設定」ダイアログのバックエンドURLに、起動したJupyter notebookのURLを入れる。

```
http://localhost:8888/?token=コピーしたtokenをペースト
```

「URL 全体をコピー」と出てきますが、この方法だと正しいURLが出力されないので、上記をコピーして、token=のみぎがわだけ、コピペする。

# 参考記事

* [待ってました CUDA on WSL 2](https://qiita.com/ksasaki/items/ee864abd74f95fea1efa)