RTX-3090/3080＋MINT Linuxでtensorflow 1.15を使う

# RTX-3090/3080＋MINT Linuxでtensorflow 1.15を使う

ディープラーニング用にRTX-3090/3080を買ってみたものの、tensorflow 1.xが使えなくなって困っている人はいないでしょうか？

## 背景

RTX-3090/3080をLinuxから認識するには、最新ドライバーのnvidia455が必要になります。
nvidia455をインストールすると、自動的にcuda 11.1がインストールされます。
しかし、tensorflow-gpuの1.x系はcuda 11に対応していないので、tensorflow 1.xでGPUが使えなくなってしまいます（tensorflow2.xやpytorchは現時点でnightlyビルドで対応、次リリースで正式対応なので心配ないです）。

### 解決方法

そんなこともあろうかと！NVidiaがNVidia NGCでDockerコンテナを公開してくれています。
新しいドライバーとcudaに対応したtensorflowをセットアップしたDockerコンテナを導入すれば、RTX-3090/3080でtensorflow 1.xも使えるようになります。
NVidia NGCには、tensorflow1.x以外にも、色々な機械学習プラットフォームのDockerコンテナがあるので、これからはcondaとかじゃなくNVidia NGCのコンテナをデフォルトの環境にする方が良いかもしれないです。

### MINT Linux？

しかし、NVidia NGCの動作環境には、MINT Linuxが無くて、HPにある手順そのままでは動きません。
そこで、Ubuntu 18.04のバイナリを持ってきて動かします。

なので、この記事では、

- cuda11でtensorflow1.xを動かす
- MINT LinuxでNVidia NGCのコンテナを動かす

という、二つのはまりポントを書いています。

## 目次：

- nvidia455とcuda 11.1をインストール
- Docker 19.3.13をインストール
- nvidia-container-runtimeをインストール
- Dockerを設定
- NVidia NGCのコンテナを実行


### nvidia455とcuda 11.1をインストール

まずは、最新のNVidiaドライバーをインストールします。
古いドライバーが動いている場合、lightdmがグラフィックボードを使っているので、その時はまずCtrl+Alt+F1でGUIを抜け、CUIログインします。
そして、lightdmを停止させて、nvidia455の実行ファイルを起動します。

```sh
$ sudo service stop lightdm
$ sudo sh NVIDIA-Linux-x86_64-455.23.04.run
$ reboot
```

適当にYESを選んで、再起動すれば、ドライバーのインストールは完了です。

### Docker 19.3.13をインストール

簡単なのでコマンドだけ置いときます。

```sh
$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
```

### nvidia-container-runtimeをインストール

https://ngc.nvidia.com/catalog/all
からお目当てのコンテナを選んで、そこにあるコマンドそのままでOKです。

```sh
$ sudo docker pull nvcr.io/nvidia/tensorflow:20.08-tf1-py3
```

「tf1」のところを「tf2」にすると、tensorflow 2.x系を導入したコンテナが入手出来ます。その他にもpytorchのコンテナとか色々あります。

### Dockerを設定

ここから、MINT Linuxでのはまりポイントです。
基本的には、
https://collabnix.com/introducing-new-docker-cli-api-support-for-nvidia-gpus-under-docker-engine-19-03-0-beta-release/
の手順そのままなのですが、MINT Linuxに対応してないので、ubuntu 18.04のバイナリを持ってきて動かします。
まず、以下のように、直接、ubuntu 18.04を指定してリポジトリを追加します。

```sh
curl -s -L https://nvidia.github.io/nvidia-container-runtime/gpgkey | \
  sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-container-runtime/ubuntu18.04/nvidia-container-runtime.list | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-runtime.list
sudo apt-get update
```

で、nvidia-container-runtimeをインストールします。
/usr/bin/nvidia-container-runtime-hookに実行ファイルが作成されればOKです。

```sh
$ sudo apt-get install nvidia-container-runtime
$ which nvidia-container-runtime-hook
/usr/bin/nvidia-container-runtime-hook
```

次に、dockerdの設定をします。こちらは、
https://github.com/NVIDIA/nvidia-container-runtime
の手順に従います。
以下のように/etc/systemd/system/docker.service.d/override.confファイルを作成します。

```sh
$ sudo mkdir -p /etc/systemd/system/docker.service.d
$ sudo vim /etc/systemd/system/docker.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --host=fd:// --add-runtime=nvidia=/usr/bin/nvidia-container-runtime
```

次に、/etc/docker/daemon.jsonファイルを作成します。

```sh
sudo vim /etc/docker/daemon.json
{
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}
```

HPの手順では直接dockerdを叩いていますが、ここでは/etc/init.d/dockerファイルを編集して、dockerdの起動オプションを指定します。

```sh
$ sudo vim /etc/init.d/docker
↓この行を編集
DOCKER_OPTS="--add-runtime=nvidia=/usr/bin/nvidia-container-runtime"
```

再起動します。

```sh
$ reboot
```

### NVidia NGCのコンテナを実行

Dockerコンテナの中でnvidia-smiを実行します。

```sh
$ sudo docker run -it --rm --gpus all ubuntu nvidia-smi -L
```

正しくGPUが見えていれば成功です。

```sh
$ sudo docker run --gpus all -it --rm -v local_dir:/workspace nvcr.io/nvidia/tensorflow:20.08-tf1-py3
↓ここからはDockerの中
$ python
>>> import tensorflow
>>> tensorflow.__version__
'1.15.3'
```

tensorflow 1.xのコンテナの中で、tensorflow 1.15が動いています。