Ubuntu で docker, GPU, PyTorch の設定 (2019年度版)

## 環境
Ubuntu 18.04.3 LTS

```shell
$ lspci | grep -i nvidia
01:00.0 VGA compatible controller: NVIDIA Corporation GP106 [GeForce GTX 1060 6GB] (rev a1)
01:00.1 Audio device: NVIDIA Corporation GP106 High Definition Audio Controller (rev a1)
```

## 手順
* docker install
* GPU driver install
* CUDA driver install
* nvidia-docker install
* pytorch


#### docker install
docker 関連では基本公式 (Dockerfile, compose ファイルの検索も公式がよい -> [公式]((https://docs.docker.com/install/linux/docker-ce/ubuntu/))
ついでにcomposeもインストール -> [参照](https://docs.docker.com/compose/install/)
`docker info`でエラーが出るとき -> [参照](https://qiita.com/naomichi-y/items/93819573a5a51ae8cc07)

```shell
$ sudo apt-get remove docker docker-engine docker.io containerd runc
$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
pub   rsa4096 2017-02-22 [SCEA]
      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid           [ unknown] Docker Release (CE deb) <docker@docker.com>
sub   rsa4096 2017-02-22 [S]

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
$ docker info
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
```

#### GPU, CUDA driver install
搭載GPU確認
(google compute engine 上では以下の手順でインストール可能: [参考](https://cloud.google.com/compute/docs/gpus/install-drivers-gpu?hl=ja#ubuntu-driver-steps))

```shell
$ lspci | grep -i nvidia
```


GPU ドライバのインストール
```shell
$ ubuntu-drivers devices
$ sudo apt install nvidia-driver-"version"
```


CUDA バージョン確認
(表になっているところ)
https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html

CUDA レポジトリの検索
https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/
`cuda-repo-*`

```shell
$ wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-repo-ubuntu1804_10.1.243-1_amd64.deb
$ sudo apt install ./cuda-repo-ubuntu1804_10.1.243-1_amd64.deb
$ sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
```

機械学習リポジトリの検索
http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/
`nvidia-machine-learning-repo-ubuntu1804*`

```shell
$ wget http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb
$ sudo apt install ./nvidia-machine-learning-repo-ubuntu1804_1.0.0-1_amd64.deb
$ sudo apt update
```

#### nvidia-docker install
```shell
$ 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-container-toolkit
$ sudo systemctl restart docker
```

#### docker-compose の runtime 追加
```shell
$ sudo apt-get install nvidia-container-runtime
$ sudo mkdir -p /etc/systemd/system/docker.service.d
$ sudo tee /etc/systemd/system/docker.service.d/override.conf <<EOF
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --host=fd:// --add-runtime=nvidia=/usr/bin/nvidia-container-runtime
EOF
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
$ sudo tee /etc/docker/daemon.json <<EOF
{
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}
EOF
$ sudo pkill -SIGHUP dockerd
```


#### GPU 使用可能か確認
```python:torch.py
import torch

print(torch.cuda.device_count(), "GPUs available")
```

```python:tensorflow.py
from tensorflow.python.client import device_lib

device_lib.list_local_devices()
```

```shell
$ nvidia-smi
$ docker run --rm --gpus all pytorch/pytorch:1.3-cuda10.1-cudnn7-runtime nvidia-smi
$ docker run --rm --gpus all pytorch/pytorch:1.3-cuda10.1-cudnn7-runtime python --version
$ docker run --rm --gpus all -v $(pwd):/workspace pytorch/pytorch:1.3-cuda10.1-cudnn7-runtime python ./test.py
```

#### docker-compose.yml の書き方サンプル
```yaml:docker-compose.yml
version: "2.4"

services:
  pytorch:
    image: pytorch/pytorch:1.3-cuda10.1-cudnn7-runtime
    runtime: nvidia
```


## トラブルシュート

##### Cuda ダウングレード
```shell
$ sudo apt-get --purge remove "*cublas*" "cuda*" "libcudnn7*" "*nvidia*"
$ sudo apt autoremove
# 以下で検索し、残っているパッケージを削除
$ dpkg -l | grep nvidia
$ dpkg -l | grep cuda
# ここまで
$ sudo reboot
```
この後 GPU, CUDA driver install と同じ手順で再ダウンロード 


##### libcudnn7 の CUDA バージョンが違う場合

```shell
$ dpkg -l | grep -i cudnn
$ sudo apt-cache policy libcudnn7
$ sudo apt-get --purge remove "libcudnn7*"
$ sudo apt install libcudnn7=7.6.5.32-1+cuda10.1
$ sudo apt install libcudnn7-dev=7.6.5.32-1+cuda10.1
$ sudo apt-mark hold libcudnn7 libcudnn7-dev
```

##### nvidia-smi の CUDA バージョンが一致しない
https://stackoverflow.com/questions/53422407/different-cuda-versions-shown-by-nvcc-and-nvidia-smi
ランタイムAPIとドライバAPIでバージョンが二重管理されているので `nvidia-smi`　で表示されるバージョンとインストールしたバージョンが必ずしも一致するわけではない
問題がある場合は、GPUドライバーのバージョンを下げるか、ライブラリのCUDAのバージョンアップの対応を待つ

# 参考
https://www.nemotos.net/?p=3176
https://github.com/NVIDIA/nvidia-docker
https://qiita.com/bohemian916/items/7637b9b0b3494f447c03
https://github.com/nvidia/nvidia-container-runtime
https://chadrick-kwag.net/downgrading-cudnn-version-to-match-cuda-version/