機械学習とかGPUを使うプログラムを書いているとき,リモートのGPU搭載マシンで実行させたいときってないでしょうか...
ローカルPCにGPU積んでないとか,積んでるけどリモートのGPUが強力だからそっちで学習がっつり回したいとか,ファンうるさいからあっちでやってくれとか.
私は,GitレポジトリにあげてリモートでPullして実行をよくやります.が,CIツールを使って,もうちょっといい感じにできないかなと試してみましたので,そのときのメモ・手順をここに置きたいと思います.
構築イメージ
閉じた環境でやりたかったので,GitLabを利用しローカルにGitレポジトリマネージャー,CIサーバ,ランナーを構築します.そしてgit pushからのGPUマシンにデプロイをしていきます.
また,他の環境にも展開したいときサクッと行きたいので,Docker Composeを利用して構築します.
デプロイ先では,そこの環境を汚したくないので,ここもDockerを使います.Dockerコンテナ上でGPUを使うことになるので,NVIDIA Dockerで構築します.
事前準備
- GitLab構築マシン(CIサーバー側)
- GPU搭載Linuxマシン(デプロイ先)
※ 両方にDocker Compose,2にはNVIDIA Dockerもインストールしてください.
1, 2は同一マシンでも問題ありません.
ただし,NVIDIA Dockerのサポート対象の関係上[参考],2がLinuxであることは必須です.
本稿ではDocker Compose,NVIDIA Dockerのインストール方法については割愛させていただきます.インストール方法については,公式ドキュメントなどをご参考ください.
- Docker Compose: http://docs.docker.jp/compose/install.html
- NVIDIA Docker: https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(version-2.0)
GitLabを構築
まずGitLabをDocker Composeで構築します.
以下はYAMLの例です.initial_shared_runners_registration_token
でランナー登録時に使用するトークンを与えています.(今回はテストのため非常に安直)
実行コマンド例)docker-compose -f gitlab.yml up -d
version: '2'
services:
gitlab:
image: 'gitlab/gitlab-ce:latest'
container_name : gitlab
restart: always
hostname: 'mac-book.local'
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://mac-book.local'
gitlab_rails['time_zone'] = 'Asia/Tokyo'
gitlab_rails['initial_shared_runners_registration_token'] = 'token-share'
ports:
- '80:80'
# - '443:443'
# - '22:22'
volumes:
- './etc/gitlab:/etc/gitlab'
- './log:/var/log/gitlab'
- './data:/var/opt/gitlab'
GitLab RunnerをNVIDIA Dockerに構築&ワーカー登録
GPU搭載マシン側にGitLab Runnerコンテナを構成します.YAMLの例は下記に示します.
ポイントは,/var/run/docker.sock:/var/run/docker.sock
です.
ランナーをコンテナで動作させている場合,Docker in Docker (dind)を使うかと思います.
NVIDIA Dockerもdindいけるかもですが,NVIDIA Driverのマウントとか,私の実力では修羅の道になりそうなので,ここにあるようにDockerソケットのマウントでシンプルに行きます.
※ Dockerソケットのマウントはセキュリティ上好ましくない行為ですので,ご注意を.
version: '2'
services:
gitlab-runner:
image: 'gitlab/gitlab-runner:latest'
container_name : gitlab-runner
volumes:
# - './etc/gitlab-runner:/etc/gitlab-runner'
- '/var/run/docker.sock:/var/run/docker.sock'
dns: '192.168.X.X'
参考元:https://docs.gitlab.com/runner/install/docker.html
例ではURLにドメインを利用しているので,DNSを設定しています.
コメントアウト部分は設定ファイルのディレクトリです.有効にする場合,下記のような設定ファイルを事前に配置しておく必要があります.(無いとエラーで怒られます)
concurrent = 1
check_interval = 0
[session_server]
session_timeout = 1800
ランナーのコンテナを立てたら,ワーカーの登録を行います.登録のコマンド例は以下の通りです(例は全レポジトリ共有のワーカーの登録になります).runtime
オプションは必ずNVIDIA
にしてください.
また,ワーカーを登録するごとに上記config.toml
に設定状況が記録されるので,永続化しておくのが良いと思います.
各オプションの意味は下記URLや,gitlab-runner register
のヘルプで確認できます.
参考:https://docs.gitlab.com/runner/configuration/advanced-configuration.html
docker-compose -f gitlab-runner.yml exec gitlab-runner gitlab-runner register \
--non-interactive \
--request-concurrency 2 \
--url http://mac-book.local \
--registration-token "token-share" \
--executor docker \
--docker-image ubuntu:latest \
--docker-runtime nvidia \
--docker-dns "192.168.X.X" \
--docker-privileged=true \
--docker-pull-policy "never" \
--description "docker-runner" \
--tag-list "docker,oneshot" \
--run-untagged \
--locked="false"
登録が成功すると,以下のようにGitLabの管理者ページの登録ランナー一覧に表示されます.
今回ドメインを使ってやっているので,ランナーとワーカー登録時にDNSを教えています.
ちなみに,ランナーはジョブ取得時といったGitLabとコネクションするとき,ワーカーはGitレポジトリ引っ張ってくるときにDNS使ってます.
Let's Try!!
実際にデプロイがうまくいくか,レポジトリを適当に作ってテストしてみます.
CI用YAMLは以下の感じです.PyTorchでGPU調べてみるだけのシンプルなものです.nvidia-smi
するだけでもよかったかも.
image: 'pytorch/pytorch:latest'
deploy:
stage: deploy
script:
- python3 test-gpu.py
import torch
print('torch.cuda.is_available() ...', torch.cuda.is_available())
print('torch.cuda.get_device_name(0) ...', torch.cuda.get_device_name(0))
ジョブの実行結果はこちら(GitLabのレポジトリ→CI/CDから確認できます).どうやらうまくいったみたいです.
さいごに
CIツール使ってGPUコンテナに自動デプロイ的なことをやりました.
ただ,デプロイ先でのデータ永続化について扱っていないため,せっかく学習させたモデルが消えてしまったりします
このままでは正直使えないので,そこらへん別投稿とかで書けたらなぁと思ったり.
あと,最近購入したJetsonをデプロイ先にして遊びたいなぁ..
ありがとうございました.