はじめに
自宅PCをリニューアルしたときから、画策していたこと。。。
それは、搭載した**GPU(NVIDIA GeForce GTX 1660 SUPER)**を使った分析環境を仕立てること!
過去の記事(※1)では、VirtualBox/VagrantでUbuntu/Dockerを準備し、JupyterHub/JupyterLabを起動した。
が、その構成だと、GPUが使えないという状況にあった。。。せっかく搭載されているのに活かせず。。。
Windows Insider Previewに参加しながら、WSLの動向に気にしていたのだが、状況は変わってきた様子!!
というわけで、**「JupyterHubを利用した分析環境を、WSLに移行&NGCカタログでGPU使用に構成変更かけてゆく流れ」**を紹介してゆく。
本稿で紹介すること
- Dockerの環境設定
- JupyterHub/JupyterLabの環境設定
- Dockerコンテナイメージのビルド based on NGC Catalog
- JupyterHub/JupyterLabの起動
- GPUデバイスの認識確認(TensorFlowおよびPyTorch)
jupyterhub | Read the Docs
JupyterHub — JupyterHub 1.0.0 documentation
GitHub - jupyter/docker-stacks: Ready-to-run Docker images containing Jupyter applications
本稿で紹介しないこと
- Windows Insider Previewの参加(およびWindiws Update) ※Microsoft Windows [Version 10.0.22000.120]を使用
- GPUドライバのインストール(For NVIDIA GeForce GTX 1660 SUPER) ※NVIDIAドライバ: 471.41
- WSL2のインストール
- Ubuntuのインストール(From Microsoft Store) ※Ubuntu 18.04.5 LTSを使用
- Dockerのインストール ※Docker Community Edition 20.10.8を使用
- NVIDIA Container Toolkitのイントール ※nvidia-docker2 2.6.0を使用
- NGC Catalogの全般(Requirements等々)
- Pythonライブラリ(MeCab、TensorFlow、PyTorch)の全般
待ってました CUDA on WSL 2
WSL2を用いたdockerでGPU認識(2020年8月)
TensorFlow | NVIDIA NGC
TensorFlow Release Notes :: NVIDIA Deep Learning Frameworks Documentation
PyTorch | NVIDIA NGC
PyTorch Release Notes :: NVIDIA Deep Learning Frameworks Documentation
環境構築
大きく、4ステップです。これら、WSL2/Ubuntu上で実行します。
- Dockerの環境設定
- JupyterHub/JupyterLabの環境設定
- Dockerコンテナイメージのビルド based on NGC Catalog
- JupyterHub/JupyterLabの起動
事前準備
以下のリンクに記載された手順を見本とし、WSL2のUbuntu18上でNVIDIA Container Toolkitのインストールまで進めます。
待ってました CUDA on WSL 2
WSL2を用いたdockerでGPU認識(2020年8月)
以下、筆者の環境です。
C:\>ver
Microsoft Windows [Version 10.0.22000.120]
C:\>nvidia-smi
Tue Aug 10 09:25:51 2021
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 471.41 Driver Version: 471.41 CUDA Version: 11.4 |
|-------------------------------+----------------------+----------------------+
| GPU Name TCC/WDDM | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 NVIDIA GeForce ... WDDM | 00000000:01:00.0 On | N/A |
| 42% 38C P8 14W / 125W | 619MiB / 6144MiB | 1% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.5 LTS"
$ docker version
Client: Docker Engine - Community
Version: 20.10.8
API version: 1.41
Go version: go1.16.6
Git commit: 3967b7d
Built: Fri Jul 30 19:54:08 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.8
API version: 1.41 (minimum version 1.12)
Go version: go1.16.6
Git commit: 75249d8
Built: Fri Jul 30 19:52:16 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.9
GitCommit: e25210fe30a0a703442421b0f60afac609f950a3
nvidia:
Version: 1.0.1
GitCommit: v1.0.1-0-g4144b63
docker-init:
Version: 0.19.0
GitCommit: de40ad0
$ sudo dpkg -l | grep -i nvidia
ii libnvidia-container-tools 1.4.0-1 amd64 NVIDIA container runtime library (command-line tools)
ii libnvidia-container1:amd64 1.4.0-1 amd64 NVIDIA container runtime library
ii nvidia-container-runtime 3.5.0-1 amd64 NVIDIA container runtime
ii nvidia-container-toolkit 1.5.1-1 amd64 NVIDIA container runtime hook
ii nvidia-docker2 2.6.0-1 all nvidia-docker CLI wrapper
NGC Catalog(※2、※3)より、TensorFlowおよびPyTorchのコンテナイメージを取得しておきます。
Python 3.6を使いたいため、過去タグ「20.11-*」を取得しています。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jupyterhub/jupyterhub 1.0-custom 972a2af201e9 2 hours ago 418MB
jupyter/minimal-notebook 2343e33dec46-custom 4d9dcbd96625 16 hours ago 3.47GB
nvcr.io/nvidia/tensorflow 20.11-tf2-py3 98a7952f7f9c 9 months ago 11.6GB
nvcr.io/nvidia/pytorch 20.11-py3 ae35b2b3cad1 9 months ago 13.2GB
jupyterhub/jupyterhub 1.0 c399e04fda3c 20 months ago 283MB
jupyter/minimal-notebook 2343e33dec46 c3bbd3471e39 2 years ago 2.72GB
hrektts/fusiondirectory-openldap 1.1.9-1.2-1 7f2e4370509d 4 years ago 226MB
hrektts/fusiondirectory 0.2.0 b56f1086a08d 4 years ago 345MB
Dockerネットワーク「jupyterhub」を作成しておきます。形態はBridgeです。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
d880009721fa bridge bridge local
dc9d83b0f49c host host local
d26548c59f23 jupyterhub bridge local
18e4f9062739 none null local
1. Dockerの環境設定
以下のリンクに記載された手順を見本とし、DockerのDefault RuntimeをGPUが使えるRuntimeへ変更します。
Upgrading to the NVIDIA Container Runtime for Docker :: DGX Systems Documentation
以下、環境設定の例です。★マークの付いた行を追記・保管後、Dockerサービスを再起動します。
$ cat /etc/docker/daemon.json
{
"default-runtime": "nvidia", ★本行を追記
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
}
}
2. JupyterHub/JupyterLabの環境設定
以下のリンクに記載された項目を参考に、JupyterHub/JupyterLabの振る舞いを決めて、**環境設定ファイル(jupyterhub_config.py)**に記述します。
jupyterhub | Read the Docs
JupyterHub — JupyterHub 1.0.0 documentation
GitHub - jupyter/docker-stacks: Ready-to-run Docker images containing Jupyter applications
以下、過去の記事(※1)からの変更点です。
- ①LDAPサーバのアドレス変更
- ②NGC Catalogのカスタムイメージを選択肢に登録
①LDAPサーバのアドレス≒WSL2/Ubuntuのeth0ですが、
WSL2/Ubuntuを起動するたびに変わっているようで、その点注意。
以下、環境設定ファイル(jupyterhub_config.py)です。
c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.valid_username_regex = r'^[a-z0-9][.a-z0-9_-]*$'
c.LDAPAuthenticator.use_ssl = False
c.LDAPAuthenticator.server_address = '${WSL2/Ubuntuのeth0}' ★変更点①
c.LDAPAuthenticator.server_port = 389
c.LDAPAuthenticator.bind_dn_template = 'uid={username},ou=people,ou=jhub,dc=hoge,dc=com'
c.LDAPAuthenticator.lookup_dn = False
c.JupyterHub.hub_connect_ip = 'jupyterhub'
c.JupyterHub.hub_ip = '0.0.0.0'
c.Authenticator.admin_users = {'admin', 'jupyter'}
from dockerspawner import DockerSpawner
class DemoFormSpawner(DockerSpawner):
def _options_form_default(self):
default_stack = 'jupyter/minimal-notebook'
return """
<label for="stack">Select your desired stack</label>
<select name="stack" size="1">
<option value="jupyter/minimal-notebook:2343e33dec46">jupyter/minimal-notebook</option>
<option value="jupyter/minimal-notebook:2343e33dec46-custom">jupyter/minimal-notebook(w/MeCab)</option>
<option value="nvcr.io/nvidia/tensorflow:20.11-tf2-py3-custom">nvcr.io/nvidia/tensorflow</option> ★変更点②
<option value="nvcr.io/nvidia/pytorch:20.11-py3-custom">nvcr.io/nvidia/pytorch</option> ★変更点②
</select>
""".format(stack=default_stack)
def options_from_form(self, formdata):
options = {}
options['stack'] = formdata['stack']
container_image = ''.join(formdata['stack'])
print('SPAWN: ' + container_image + 'IMAGE')
self.image = container_image
return options
c.JupyterHub.spawner_class = DemoFormSpawner
notebook_dir = '/home/jovyan'
c.DemoFormSpawner.notebook_dir = notebook_dir
c.DemoFormSpawner.volumes = {'jupyterhub-user-{username}':notebook_dir}
c.DemoFormSpawner.remove = True
c.DemoFormSpawner.default_url = '/lab'
c.DemoFormSpawner.start_timeout = 300
c.DemoFormSpawner.http_timeout = 120
c.DemoFormSpawner.network_name = 'jupyterhub'
3. Dockerコンテナイメージのビルド based on NGC Catalog
以下、コンテナイメージのビルド用環境設定ファイル(TensorFlow版)です。
PyTorch版は、先頭行のFROMの指定を変更するのみです。
FROM nvcr.io/nvidia/tensorflow:20.11-tf2-py3
RUN python3 -m pip install jupyterhub==1.0.0
RUN useradd -m jovyan
ENV HOME=/home/jovyan
WORKDIR $HOME
USER jovyan
CMD ["jupyterhub-singleuser"]
以下、ビルドコマンドです。
$ docker image build -t nvcr.io/nvidia/tensorflow:20.11-tf2-py3-custom -f Dockerfile.tensorflow.lab .
4. JupyterHub/JupyterLabの起動
以下、環境設定(環境変数の定義)を含む起動コマンドです。
過去の記事(※1)からの変更なしです。
$ docker run -v /var/run/docker.sock:/var/run/docker.sock -p 8000:8000 -p 8001:8001 -p 8081:8081 \
-d --name jupyterhub --net jupyterhub jupyterhub/jupyterhub:1.0-custom
Webブラウザで http://127.0.0.1:8000/hub/login にアクセスし、JupyterHubのログイン画面が表示できればOKです。
では早速、動作確認
TensorFlowおよびPyTorchで、GPUデバイスが認識できているか否か、を確認します。
結果、**GPU(NVIDIA GeForce GTX 1660 SUPER)**がきちんとPythonプログラムから認識できています!!!
これで、Google Colaboratoryに頼らずとも、手元の環境でPythonプログラムを実行できるようになります。
・・・というほど、普段は負荷/データ量においてGoogle Colaboratoryでの限界を感じてはいませんが。。。
TensorFlowでのGPUデバイス確認画面
以下、確認用のCode例です。
import tensorflow as tf
gpu_devices = tf.config.list_physical_devices('GPU')
if gpu_devices:
details = tf.config.experimental.get_device_details(gpu_devices[0])
print(details)
# {'compute_capability': (7, 5), 'device_name': 'NVIDIA GeForce GTX 1660 SUPER'}
ちなみに、このときコンテナ一覧を確認すると、NGC Catalogをカスタムしたイメージからコンテナが起動されていることがわかります。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0967a1df5d63 nvcr.io/nvidia/tensorflow:20.11-tf2-py3-custom "/usr/local/bin/nvid…" About a minute ago Up About a minute 6006/tcp, 6064/tcp, 8888/tcp
PyTorchでのGPUデバイス確認画面
以下、確認用のCode例です。
import torch
print(torch.cuda.get_device_name())
# NVIDIA GeForce GTX 1660 SUPER
print(torch.cuda.get_device_capability())
# (7, 5)
こちらも同じく、コンテナ一覧を確認すると、NGC Catalogをカスタムしたイメージからコンテナが起動されていることがわかります。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6fb7d292bbf8 nvcr.io/nvidia/pytorch:20.11-py3-custom "/usr/local/bin/nvid…" 3 hours ago Up 3 hours 6006/tcp, 8888/tcp
まとめ
自宅PCをリニューアルしたときから描いていた構成を実現できました。これで、GPUを使ったPythonプログラムを動かせます。
とはいえ、VirtualBox/Vagrantを使うケースも存在するので、適材適所で使ってゆこうと考えています。
(ちょっと前は、WSLとVirtualBoxが上手く共存できない、という状況だったと思うのですが。。。進歩のスピードが素晴らしい。)