#はじめに
Dockerの解説記事は多くありますが、情報が結構ばらばらで実際に機械学習できるようになるまでには、ネットの海を漂い続けなければなりませんでした。
またDockerのバージョンが新しめなせいもあってか、以前のバージョン通りではうまく行かないことも多々ありました。
今回、dockerのインストールからcudaイメージ、pytorchを使った機械学習まで通してやっていきます。
参考になれば幸いです。
#環境
ubuntu 18.04
Geforce 1080ti
nvidia driver 430.26
#dockerインストール
まずはdockerのインストールからです。
docker公式に従ってコマンドを打ち込んでいきます。
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
上から順に実行していき、最後にバージョンを確認します。
$ docker version
>Client: Docker Engine - Community
Version: 19.03.2
API version: 1.40
Go version: go1.12.8
Git commit: 6a30dfc
Built: Thu Aug 29 05:29:11 2019
OS/Arch: linux/amd64
Experimental: false
最後にdockerコマンドにsudoをつけるのがめんどくさい人は以下を実行して再起動します。
ただしdockerに権限を与えてしまうので自己責任で。
$ sudo usermod -aG docker __username__
###参考
Ubuntuにdockerをインストールする
#CUDAイメージをプル
最初からpytorchをいれても動く可能性はありますが、まずcudaイメージをいれて、gpuを認識できるか確認しましょう。
cudaイメージをダウンロードします。(もしかするとこの章自体いらないかもしれないです。次の章のpytorchプルをしちゃってください)
$ docker pull nvidia/cuda:10.0-cudnn7-devel-ubuntu16.04
$ docker pull nvidia/cuda
だと最新版が入りますが後のpytorchのベースイメージに合わせました。
そしてnvidia-smi
でgpuを確認します。
$ docker run --rm --gpus all nvidia/cuda:10.0-cudnn7-devel-ubuntu16.04 nvidia-smi
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 430.26 Driver Version: 430.26 CUDA Version: 10.2 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce GTX 108... Off | 00000000:17:00.0 Off | N/A |
| 23% 28C P8 9W / 250W | 2MiB / 11178MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
ちなみに多くのサイトで書いてある、runオプションのruntime
は自分の環境ではエラーが出てできませんでした、
これにも書いてあるとおり、その代わりに--gpus
を使うようです。
###エラーが出た人へ
docker: Error response from daemon: linux runtime spec devices: could not select device driver "" with capabilities: [[gpu]].
もし上記のようなエラーが出たとき、ありがたいことに解決策書いてる方がいらっしゃったので紹介します。
New Docker CLI API Support for NVIDIA GPUs under Docker Engine 19.03.0 Pre-Release
場所はどこでもいいのでshファイルを作ります。
$ gedit nvidia-container-runtime-script.sh
そのshファイルに以下を打ち込み、実行します。
curl -s -L https://nvidia.github.io/nvidia-container-runtime/gpgkey | \
sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-container-runtime/$distribution/nvidia-container-runtime.list | \
sudo tee /etc/apt/sources.list.d/nvidia-container-runtime.list
sudo apt-get update
実行
$ sh nvidia-container-runtime-script.sh
$ sudo apt-get install nvidia-container-runtime
$ docker run -it --rm --gpus all ubuntu nvidia-smi
無事にgpuが認識されていたら成功です!
###参考
dockerでgpuコンテナの作成
#pytorchをビルド
https://github.com/pytorch/pytorch
まずは上のgitからクローンします。
クローンしたら、pytorchディレクトリに移動してビルドをします。
docker build -t pytorch -f docker/pytorch/Dockerfile .
結構時間がかかりますが、気長に待ちましょう。
終わったら確認してみます。
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
pytorch latest 47ea93f4ed87 6.12GB
nvidia/cuda 10.0-cudnn7-devel-ubuntu16.04 b739d7317c55 3.12GB
pytorchのイメージがあればokです。(作成日時は抜きました。)
###(追記)
別にbuildしなくてもpullするだけでよかった
docker pull pytorch/pytorch
#コンテナを作成して起動
これでやっと学習のためのコンテナを作成できます。
$ docker run -it --gpus all -v マウントしたい場所:docker側の場所 --shm-size 8G --name ml pytorch
コマンドの説明をします。
docker run
はイメージからコンテナを作成し、起動をします。
-it
はそのままコンテナ内でbashを起動してくれます。つまり、runをしてそのままコンテナ内で作業することができます。
-v
はホストpcのディレクトリをdockerにマウントします。
例えばホストPC側で~/ML/
が機械学習のディレクトリであるとき、-v ~/ML:/ML
とすることで、マウントをすることができ、好きなエディタで編集して実行する事ができます。
--shm-size
はコンテナに割り当てるメモリの量です。今回は8GB割り当てています。
--name
はそのコンテナの名前です。起動やログイン時に使います。
起動が成功するとbashの前にroot@0f5c51d62772
のようなコンテナidが付きます。
#学習
先程の例のように/ML/
にtrain.py
を置いて学習させます。
コードはPytorchチュートリアルを参考にしたものです。
import torch
import torchvision
import torchvision.transforms as transforms
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Net().cuda()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
for epoch in range(10):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
inputs, labels = inputs.cuda(), labels.cuda()
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 2000 == 1999:
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.0
print('Finished Training')
python train.py
で訓練が始まったら成功です!
#おまけ
コンテナに入るときはそのコンテナが起動していないといけません。
コンテナが起動状態を見るにはdocker ps -a
で確認できます。
起動はdocker start コンテナの名前
、入るときはdocker attach コンテナの名前
を使います。
コンテナから抜けるときはctrl P Q
を同時に押します。