Ubuntu 20.04で機械学習用GPUサーバを構築する機会があったのでその手順を公開します。今回は
- 環境を切り分けるためにdockerのコンテナに分析環境を構築
- コンテナ側でGPUを認識しTensorflowを利用
- 外部からコンテナのJupyter notebookに接続
前編ではUbuntu 20.04のセットアップを行いました。後編では
- NVIDIA ドライバのインストール
- Docker のインストール
- NVIDIA Container Toolkitのインストール
を行います。
NVIDIAドライバのインストール
「NVIDIA Docker って今どうなってるの? (20.09 版)」を参考にまず「CUDA Toolkit」のページで
- Operating System: Linux
- Architecture: x86_64
- Distribution: Ubuntu
- Version: 20.04
- Installer Type: deb(local)
を選んで”Base Installer”の”Installation Instructions:”のコマンドを参考にcuda-driversパッケージをインストールします。
なお、”Installation Instructions:”の最終行はcudaをインストールするコマンドになっているのでcuda-driversに変更しています。
$ wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin $ sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600 $ wget https://developer.download.nvidia.com/compute/cuda/11.2.1/local_installers/cuda-repo-ubuntu2004-11-2-local_11.2.1-460.32.03-1_amd64.deb $ sudo dpkg -i cuda-repo-ubuntu2004-11-2-local_11.2.1-460.32.03-1_amd64.deb $ sudo apt-key add /var/cuda-repo-ubuntu2004-11-2-local/7fa2af80.pub $ sudo apt-get update $ sudo apt-get --no-install-recommends install cuda-drivers
インストールが終われば再起動し、GPUを認識できているか確認します。
$ nvidia-smi
として
+-----------------------------------------------------------------------------+ | NVIDIA-SMI 460.32.03 Driver Version: 460.32.03 CUDA Version: 11.2 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 GeForce GTX 108... On | 00000000:01:00.0 Off | N/A | | 0% 41C P8 10W / 270W | 1MiB / 11178MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ | 1 GeForce GTX 108... On | 00000000:02:00.0 Off | N/A | | 0% 37C P8 10W / 270W | 1MiB / 11178MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+
とGPU情報が表示できればGPUドライバのインストールは完了です。今回は2枚のGPUを挿しており2枚とも認識されています。
Dockerのインストール
まずDockerをインストールします。https://get.docker.comにアクセスするとインストールスクリプトを返してくれるので
$ curl https://get.docker.com | sh
とします。dockerサービスの起動と自動実行の設定を行います。
$ sudo systemctl start docker $ sudo systemctl enable docker
次にsudoなしにdockerコマンドを実行するために
$ sudo usermod -aG docker $USER
としてDockerのインストールは完了です。念のため
$ docker --version
として18.09以降のバージョンになっているか確認しておきます。
NVIDIA Container Toolkitのインストール
NVIDIA Container Toolkitとしてnvidia-docker2パッケージをインストールします。
$ 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 --no-install-recommends install nvidia-docker2 $ sudo systemctl restart docker
これでDockerコンテナでGPUを使う準備ができました。ここからはDockerコンテナを作成します。
Dockerコンテナの作成
「DockerでのJupyter notebook環境の構築」で作ったコンテナ(jupyter_base)をベースにnvidia_docker_baseというコンテナを作っていきます。DockerfileなどはGithubに上げているので
$ git clone https://github.com/starpentagon/docker_image.git $ cd docker_image/nvidia_docker_base
とダウンロードします。
コンテナjupyter_baseは
- Ubuntu 20.04をベースイメージとして利用
- Jupyter notebookのインストール
- Jupyter notebookの外部接続用パスワードの設定
- 外部接続用パスワードを生成するスクリプトのコピー
- ユーザの追加
- 作業ディレクトリの作成
- ポートの開放
としていたのに加えてnvidia_docker_baseは
- nvidia/cudaをベースイメージとして利用
- CUDA 11.0, cuDNN 8をインストール
- Tensorflow, matplotlibをインストール
としています。実はここに行きつくまでにつまづいたところがあり
- パッケージのインストール中にキーボード設定が出て止まってしまうのを避けるため”ARG DEBIAN_FRONTEND=noninteractive”を設定
- コンテナにCUDA 11.2を入れるとTensorflow実行時に”libcusolver.so.10″が見つからないとエラーが出たのでCUDA 11.0をインストール
としています。
Dockerfile以外のスクリプトを説明するとdocker_build.shはDockerイメージをビルドし、もし外部接続用パスワードが設定されていない場合は設定方法を表示します。
docker_run.shでは
- 作業ディレクトリのマウント
- Dockerエンジン/コンテナ間のポートのマッピング
をしてGPU付きでDockerコンテナを起動します。
Jupyter notebook接続用のパスワードの設定
Jupyter notebook接続用のパスワードを事前に設定しておく必要があります。まず
$ ./docker_build.sh
を実行します。初回実行時はイメージをダウンロードするため少し時間がかかります。
一度、
$ docker run --rm -it nvidia_docker_base
でコンテナに入ります。コンテナ内で
$ python3 ~/scripts/pass.py
を実行するとパスワードを聞かれるので入力すると
ARG JUPYTER_PASSWD='sha1:25e2bc817b10:917f1e38841d80dfa40535f60a88bc83c5228297'
などのハッシュ化されたパスワードが表示されるのでコピーしておきます。(sha1:以下は入力したパスワードに応じて変化します。)
コンテナ内での作業は終わりなので
$ exit
としてコンテナから抜けます。ホスト側でDockerfileを開いて
ARG JUPYTER_PASSWD=''
となっている部分を先ほどコピーした内容に書き換えます。
Dockerコンテナの起動
パスワードの設定が終わったら再度、イメージをビルドしてコンテナ起動しJupyter notebookを立ち上げます。
$ ./docker_build.sh $ ./docker_run.sh
コンテナとGPUサーバのポートをマッピングしているのでGPUサーバのIPアドレス(今回は192.168.10.16)に対してhttp://(GPUサーバのIPアドレス):8888 にアクセスします。
パスワードが求められるので先ほどのパスワードを入力するとJupyter notebook接続できGPUを使った処理をすることができます。また、Jupyter notebookで編集したノートブックはGPUサーバの./nvidia_docker_base/workディレクトリに保存されます。
以上で次の構成の機械学習用のGPUサーバの構築が完了しました。
GPUを使った機械学習
最後にGPUを使った機械学習をしてみましょう。TensorflowのチュートリアルにあるFashion MNISTの学習モデル構築をしてみます。チュートリアルのページからNotebookをダウンロードしGPUサーバの./nvidia_docker_base/workに置きます。
$ cd ~/docker_image/nvidia_docker_base/work $ wget https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ja/tutorials/keras/classification.ipynb
http://(GPUサーバのIPアドレス):8888にアクセスしパスワードを入力するとJupyter notebookに接続できます。先ほどダウンロードしたclassification.ipynbを開いて実行します。
ポイントはモデルの学習
model.fit(train_images, train_labels, epochs=5)
にGPUを利用し高速化できます。GPUサーバにつないで
$ watch -n 1 "nvidia-smi"
とGPUの利用状況を監視しながら学習を実行すると
+-----------------------------------------------------------------------------+ | NVIDIA-SMI 460.32.03 Driver Version: 460.32.03 CUDA Version: 11.2 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 GeForce GTX 108... On | 00000000:01:00.0 Off | N/A | | 0% 32C P2 69W / 270W | 10591MiB / 11178MiB | 27% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ | 1 GeForce GTX 108... On | 00000000:02:00.0 Off | N/A | | 0% 32C P8 9W / 270W | 253MiB / 11178MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+
と確かに学習時にGPUを利用[1]チュートリアルのスクリプトではGPUが複数枚あっても1枚しか使いません。していることがわかります。
参考
脚注
↑1 | チュートリアルのスクリプトではGPUが複数枚あっても1枚しか使いません。 |
---|