Deep Learning 環境の構築 RTX 3000シリーズ 2021/02 更新

# RTX 3000シリーズ での Deep Learning環境の構築

Ubuntu 20.04 系でも以下のような手順で概ね環境構築が問題なく行えるが、
https://qiita.com/k_ikasumipowder/items/5e88ec45f958c35e05ed

RTX 3080, 3090 などの最新GPUでは、
NVIDIA-Driverが 455 以上しか対応していない、
CUDA が 11.1 系など、
一筋縄では行かなかったため、記録用として執筆

# 利用可能なライブラリ
TensorFlow, PyTorchともに、最新バージョンであれば、CUDA 11系、RTX 3000シリーズをサポートしています。

動作確認ライブラリ

```
tensorflow >= 2.4
PyTorch >= 1.7.1
```

# BIOSの設定

必ず、 Secure Boot を Disableにする。

# インストール時

必要ないドライバーなどがインストールされることを避けるため、
最小構成でインストールすることをおすすめします。

# 環境構築

主要なライブラリ等をインストール

```
sudo apt-get update
sudo apt-get upgrade
```

```
sudo apt-get install -y vim csh flex gfortran g++ \
                 cmake xorg-dev patch zlib1g-dev libbz2-dev \
                 libboost-all-dev openssh-server libcairo2 \
                 libcairo2-dev libeigen3-dev lsb-core \
                 lsb-base net-tools network-manager \
                 git-core git-gui git-doc xclip gdebi-core libffi-dev \
                 make build-essential libssl-dev zlib1g-dev libbz2-dev \
                 libreadline-dev libsqlite3-dev wget curl llvm \
                 libncurses5-dev libncursesw5-dev \
                 xz-utils tk-dev libffi-dev liblzma-dev python-openssl
```

# nvidia-driver, CUDA 11のイントール (10系では無いことに注意)

nvidia-driver-455 以降のバージョンをインストールすることが必要

```
# Add NVIDIA package repositories
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
sudo add-apt-repository "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /"
sudo apt-get update

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-get update


# Install NVIDIA driver
sudo apt-get install --no-install-recommends nvidia-driver-460
# ここで再起動し、 nvidia-smi が通るか確認。通らない場合は、BIOSのSecure Bootの設定などを見直す。


wget https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64/libnvinfer7_7.1.3-1+cuda11.0_amd64.deb
sudo apt install ./libnvinfer7_7.1.3-1+cuda11.0_amd64.deb
sudo apt-get update

sudo apt-get install -y --no-install-recommends \
    cuda-11-0 \
    libcudnn8=8.0.4.30-1+cuda11.0  \
    libcudnn8-dev=8.0.4.30-1+cuda11.0


# Install TensorRT. Requires that libcudnn7 is installed above.
sudo apt-get install -y --no-install-recommends libnvinfer7=7.1.3-1+cuda11.0 \
    libnvinfer-dev=7.1.3-1+cuda11.0 \
    libnvinfer-plugin7=7.1.3-1+cuda11.0
```


~/.bashrc に以下を記載

```
export PATH="/usr/local/cuda/bin:$PATH"
export LD_LIBRARY_PATH="/usr/local/cuda/lib64:$LD_LIBRARY_PATH"
```


# Docker を使わずに 環境構築をする場合
現状、 CUDA 11.1 系に対応しているライブラリが
nightly-build のものしかないため、動作しないプログラムが多いと思いますが、
そのまま動作すると便利なので、ダメ元で設定を行います。
（ダメ元の設定を避けたい方は飛ばしてください。）

## Pythonのインストール
Ubuntu18.04では、デフォルトで以下のpythonが入っています。
複数バージョンを使い分ける必要がある場合、ここでpyenvを入れておくと良いでしょう。

```
$ python -V
Python 2.7.15rc1
$ python3 -V
Python 3.6.12
```

## pyenvのインストール
```
git clone https://github.com/yyuu/pyenv.git ~/.pyenv
```

パスを通します。

```
$ vim ~/.bashrc
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
```

```
$ source ~/.bashrc
```

好きなPythonをインストールして、利用できるようにしましょう。

```
pyenv install 3.6.11
pyenv global 3.6.11
pyenv rehash
python -V # 3.6.11
```

※3.7.2 は 2019/01/10現在、TensorFlowの公式サポート対象外です。

pyenvのトラブルシューティングページ
うまくインストール出来ない場合、ここを見れば解決できることが多いです。
https://github.com/pyenv/pyenv/wiki/common-build-problems


## テスト
そのままDeep Learningライブラリを入れてしまうと環境が汚れてしまうので、
venvを利用して仮想環境を作成します。

```
$ cd
$ mkdir workspace
$ cd workspace
$ mkdir test
$ sudo apt-get install python3-venv
$ python -m venv venv36testTF
$ source venv36testTF/bin/activate
```

仮想環境に入ったらTensorFlowをテストしてみましょう。
最新のバージョンでないと、CUDA 11系を利用できず、RTX 3000 シリーズの性能を発揮することはできません

```
$ pip install tensorflow-gpu==2.4 
```

mnistが動作するか、確認してみましょう。
batch_size が小さいとMNISTの場合、非常に遅いので、BatchSizeを適切なサイズにします。

```test_mnist.py```という名前で、以下のファイルを作成します。

```test_mnist.py
import tensorflow as tf
mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, batch_size=1024, epochs=5)
model.evaluate(x_test, y_test)
```

記述できたら実行してみましょう。

```
$ python test_mnist.py
```

60秒程度で学習が進んだら、GPUでの学習成功です。
手元の、 Ryzen 3900X + RTX 3080 の環境では、一部の cuda 系のライブラリの読み込みに失敗して、学習がうまくいきませんでした。

```
python test_mnist.py
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step
Epoch 1/5
60000/60000 [==============================] - 7s 121us/step - loss: 0.2010 - acc: 0.9397
Epoch 2/5
60000/60000 [==============================] - 7s 118us/step - loss: 0.0806 - acc: 0.9748
Epoch 3/5
60000/60000 [==============================] - 7s 118us/step - loss: 0.0528 - acc: 0.9836
Epoch 4/5
60000/60000 [==============================] - 7s 119us/step - loss: 0.0373 - acc: 0.9882
Epoch 5/5
60000/60000 [==============================] - 7s 118us/step - loss: 0.0290 - acc: 0.9904
10000/10000 [==============================] - 0s 43us/step
```

以下のコマンドでGPUの稼働状況を確認してみましょう。
GPU稼働率などが学習時に上がっていれば、GPUを使っていることが確認できます。
バージョン関連エラーが起きる場合、再起動すると治ることがあります。

```
nvidia-smi -l
```



# CUDA 11.1の利用について
Nvidia-driver 455、RTX 3000 シリーズと
CUDA 10系については相性が悪いため、
CUDA 10系をインストールしても動かない可能性が高いです。

NVIDIA-Container Toolkit を利用しても、CUDA 10系のコードは非常に低速でしか動かないです。

CUDA 11系しか使わない場合でも、NVIDIA-Container Toolkit の 利用は便利なため、手順を示します。
※ かつて、nvidia-docker, NVIDIA-Docker2の後継です。
▼詳細の解説記事
https://medium.com/nvidiajapan/nvidia-docker-%E3%81%A3%E3%81%A6%E4%BB%8A%E3%81%A9%E3%81%86%E3%81%AA%E3%81%A3%E3%81%A6%E3%82%8B%E3%81%AE-20-09-%E7%89%88-558fae883f44
NVIDIA-DriverをDockerコンテナから、様々なバージョンのCUDAを簡単に使うことができます。

### Docker の インストール
```
curl https://get.docker.com | sh
sudo systemctl start docker && sudo systemctl enable docker
sudo usermod -aG docker $USER
```

設定を反映するために、 一度 shell から exitして、
Docker の 動作確認を行います。

```
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:8c5aeeb6a5f3ba4883347d3747a7249f491766ca1caa47e5da5dfcf6b9b717c0
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

```

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

```
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
sudo systemctl restart docker
```

### 様々なバージョンのCUDAの利用

▼以下のリポジトリから、必要なバージョンの cuda の docker container を利用します。
https://hub.docker.com/r/nvidia/cuda/tags

```
# CUDA 11.0 系
docker run --gpus all --rm nvidia/cuda:11.0-base nvidia-smi
docker run --gpus all --rm nvidia/cuda:11.0-base nvcc -V

# CUDA 10.0 系
docker run --gpus all --rm nvidia/cuda:10.0-base nvidia-smi

# GPU ID または UUID を指定して使用
docker run --gpus '"device=0,1"' --rm nvidia/cuda:11.0-base nvidia-smi
# CUDA 10.0 系 で shellを起動
docker run --gpus all --rm nvidia/cuda:10.0-base /bin/bash
```


# docker コンテナ内でのGPU実行例

先程作成した、test_mnist.py を実行します。
-v の path は手元の環境(username)に合わせて差し替えてください。

```
docker run -it --gpus all -v /home/username/workspace/test:/home/ tensorflow/tensorflow:2.1.2-gpu python /home/test_mnist.py

```

手元の環境では RTX 3080 を使い、 Docker コンテナ内で、 CUDA 10.1 系を利用して学習を行うことが出来ました。
1 epoch 2秒程度で学習が進んでいるのでかなり高速になっています。

```
Train on 60000 samples
Epoch 1/5
2020-11-13 01:56:05.519865: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10
60000/60000 [==============================] - 85s 1ms/sample - loss: 0.2210 - accuracy: 0.9350
Epoch 2/5
60000/60000 [==============================] - 2s 39us/sample - loss: 0.0973 - accuracy: 0.9704
Epoch 3/5
60000/60000 [==============================] - 2s 39us/sample - loss: 0.0692 - accuracy: 0.9781
Epoch 4/5
60000/60000 [==============================] - 2s 39us/sample - loss: 0.0536 - accuracy: 0.9830
Epoch 5/5
60000/60000 [==============================] - 2s 39us/sample - loss: 0.0416 - accuracy: 0.9864
10000/10000 [==============================] - 0s 34us/sample - loss: 0.0667 - accuracy: 0.9799
```