更新履歴
- [2017/03/08] AWS 公式 Deep Learning AMI v2 リリース!
CUDA 8.0 になり、TensorFlow v1.0.0, MXNet v0.9.3 など
Deep Learning に便利な AMI
NVIDIA 提供
2016/09 末に公開された模様。
自分で CUDA をインストールしたことがある方ならわかると思いますが、NVIDIA の GPU ドライバから始まり、CUDA をインストールするのはなかなかの手間でした。(まあ、一度 AMI を作ればってのはありますが)
この AMI を使えば、ものすごく簡単にサーバが使い始められます!
AWS 提供
MXNet、Caffe、Tensorflow、Theano そして Torch など人気のフレームワークが事前にインストール・設定・テストされた AMI。ただし、こちらには CUDA がインストールされておらず、東京リージョンには配布されていません・・。(追記:最新版は CUDA 入っていますし、東京でも使えます!ありがたい!!)
(お試し用テストサンプルが入っていたりするようです)
[ec2-user@ip-10-0-0-10 ~]$ ls -la /home/ec2-user/src/bin
合計 40
drwxrwxr-x 2 ec2-user ec2-user 4096 9月 20 00:48 .
drwxrwxr-x 14 ec2-user ec2-user 4096 9月 28 20:21 ..
-rwxr-xr-x 1 ec2-user ec2-user 350 9月 20 00:12 testAll
-rwxr-xr-x 1 ec2-user ec2-user 1207 9月 20 00:12 testCaffe
-rwxr-xr-x 1 ec2-user ec2-user 1141 9月 20 00:12 testMXNet
-rwxr-xr-x 1 ec2-user ec2-user 70 9月 20 00:13 testTensorFlow
-rwxr-xr-x 1 ec2-user ec2-user 66 9月 20 00:13 testTheano
-rwxr-xr-x 1 ec2-user ec2-user 1058 9月 20 00:13 testTheanoOrTensorFlow
-rwxr-xr-x 1 ec2-user ec2-user 861 9月 20 00:13 testTorch
-rwxr-xr-x 1 ec2-user ec2-user 210 9月 20 00:13 testUtil
起動してみる
NVIDIA CUDA Toolkit 7.5 on Amazon Linux を使い、中身を確認してみます。
起動手順
1. マーケットプレイスでライセンスに承諾
適切なリージョンを選択し continue
をクリックします。
スポットインスタンスを使いたいので、マニュアルでの起動を選択。画面の左下にある AMI の ID を控えつつ、(今回の AMI はいまのところ無料ですが)起動時間あたりの利用料を確認し、ソフトウェアの規約に従うことを承認します。
2. EC2 インスタンスの起動
スポット料金を設定しつつ g2.2xlarge インスタンスを起動します。
スポットの金額が市場を下回るとインスタンスが起動します。
3. EC2 に SSH
起動したらサーバに入ってみます。
ssh -i ec2.pem ec2-user@x.x.x.x
インストールされているドライババージョンを確認してみます。
[ec2-user@ip-10-0-0-10 ~]$ nvcc -V
-bash: nvcc: コマンドが見つかりません
なるほど。
[ec2-user@ip-10-0-0-10 ~]$ /usr/local/cuda/bin/nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2015 NVIDIA Corporation
Built on Tue_Aug_11_14:27:32_CDT_2015
Cuda compilation tools, release 7.5, V7.5.17
はい、しっかり 7.5 ですね。AMI 素晴らしい!!
NVIDIA-docker も入れとこう
1. docker を入れて
公式ドキュメント には従わず1、以下のコマンドで Docker をインストールします。
sudo yum install -y docker
sudo service docker start
sudo usermod -aG docker ec2-user
以後 ec2-user でも docker コマンドが使えるように、いったん SSH から抜けて入りなおします。
2. NVIDIA-docker も入れる
残念ながら 1.0.0
時点では、配布されている rpm の依存パッケージ名が AmazonLinux だとアレなもので、バイナリを持ってきて置くことにします。
wget -P /tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.0/nvidia-docker_1.0.0_amd64.tar.xz
sudo tar --strip-components=1 -C /usr/bin -xvf /tmp/nvidia-docker*.tar.xz && rm /tmp/nvidia-docker*.tar.xz
3. nvidia-docker-plugin の起動
sudo mkdir -p /run/docker/plugins/
sudo -b nohup nvidia-docker-plugin > /tmp/nvidia-docker.log
もし後からサーバを再起動する / AMI をとるつもりであれば、以下のようにスクリプトを用意しておくとよいです。
sudo sh -c "cat << EOF > /etc/init.d/nvdocker-plugin
#!/bin/sh
# chkconfig: 345 98 20
# description: NVIDIA-docker plugin
nvidia-docker-plugin > /tmp/nvidia-docker.log
EOF"
sudo chmod +x /etc/init.d/nvdocker-plugin
sudo chkconfig --add nvdocker-plugin
plugin が起動したら、REST API の疎通を確認します。
[ec2-user@ip-10-0-0-10 ~]$ curl 127.0.0.1:3476/v1.0/docker/cli
--volume-driver=nvidia-docker --volume=nvidia_driver_352.99:/usr/local/nvidia:ro --device=/dev/nvidiactl --device=/dev/nvidia-uvm --device=/dev/nvidia0
4. 起動確認
インストールした NVIDIA-docker で nvidia-smi コマンドを実行します。
[ec2-user@ip-10-0-0-10 ~]$ nvidia-docker run --rm nvidia/cuda:7.5 nvidia-smi
Tue Oct 11 00:38:26 2016
+------------------------------------------------------+
| NVIDIA-SMI 352.99 Driver Version: 352.99 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GRID K520 On | 0000:00:03.0 Off | N/A |
| N/A 25C P8 17W / 125W | 11MiB / 4095MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
いい感じ2ですね。
検証
推論サーバの起動
GPU を推論に使い、HTTP プロトコルを話す API サーバを使ってベンチマークをとってみます。
1. GRE インストール
NVIDIA 社がデモ用に作った、Caffe での推論を REST API 化した GPU REST Engine3 というアプリケーションを使います4。
以下のコマンドで推論サーバを起動します。
- コミットを b7fac33 に戻し、CUDA7.5 系にする必要あり
-
docker build
には g2.2xlarge で 30 分程度かかります
cd $HOME
git clone https://github.com/NVIDIA/gpu-rest-engine
cd gpu-rest-engine
git checkout b7fac33
docker build -t inference -f Dockerfile.inference_server .
nvidia-docker run -d --name api -p 8000:8000 inference
2. 起動確認
git リポジトリに同梱されているウサギの画像を推論サーバに問い合わせてみます。
[ec2-user@ip-10-0-0-10 ~]$ IMAGE="./images/1.jpg"
[ec2-user@ip-10-0-0-10 ~]$ curl -XPOST --data-binary @${IMAGE} 127.0.0.1:8000/api/classify
[{"confidence":0.9998,"label":"n02328150 Angora, Angora rabbit"},{"confidence":0.0001,"label":"n02325366 wood rabbit, cottontail, cottontail rabbit"},{"confidence":0.0001,"label":"n02326432 hare"},{"confidence":0.0000,"label":"n02085936 Maltese dog, Maltese terrier, Maltese"},{"confidence":0.0000,"label":"n02342885 hamster"}]
99.98% の確率でアンゴラウサギらしいです。動いてますね。
この状態で SecurityGroup さえ解放されていれば、外部からの推論も行えます。楽しい。
簡易ベンチマーク
検証用クライアントのビルド
rakyll/boom を内包したツールをビルドします。
docker build -t client -f Dockerfile.inference_client .
ベンチマークの実施5
[ec2-user@ip-10-0-0-10 ~]$ docker run --rm -e CONCURRENCY=1 -e REQUESTS=20000 --net=host client
Summary:
Total: 258.6445 secs
Slowest: 0.0167 secs
Fastest: 0.0127 secs
Average: 0.0129 secs
Requests/sec: 77.3262
Total data: 6880000 bytes
Size/request: 344 bytes
[...]
GRE の README.md には「スタンドアローンな Caffe ならだいたい秒間 500 画像処理できる」とありますが、まあ、はい。
一方でこの GRE、マルチ GPU に対応してちゃんとリクエスト捌いてくれるということなので・・
インスタンスタイプ変更
Amazon EC2 では最近、P2 系がリリースされました。
New P2 Instance Type for Amazon EC2 – Up to 16 GPUs | AWS Blog
ということで、せっかくなので p2.16xlarge でもベンチマークをとり比較しようと思います6。GPU そのものも K80 だし、何から何まで高スペックになるので期待が高まりますね!
p2.16xlarge で再取得
10月12日現在、スポットインスタンスが意味不明な金額に高騰しているので素直にオンデマンドで起動します。上述の手順同様に7 GRE までのインストールを済ませ8、nvidia-smi を流してみます。
[ec2-user@ip-10-0-0-10 ~]$ nvidia-docker run --rm nvidia/cuda:7.5 nvidia-smi | grep K80 | wc -l
16
これを参考に CONCURRENCY
の値をよしなに変更しつつ、ベンチマーク取得コマンドを打ってみます。
[ec2-user@ip-10-0-0-10 ~]$ docker run --rm -e CONCURRENCY=16 -e REQUESTS=20000 --net=host client
Summary:
Total: 14.1379 secs
Slowest: 3.9332 secs
Fastest: 0.0055 secs
Average: 0.0110 secs
Requests/sec: 1414.6341
Total data: 6880000 bytes
Size/request: 344 bytes
[...]
おーなるほど。
更に、p2 系では GPU 最適化 が行えるので、その上でもう一度やってみます。
nvidia-docker run --rm --privileged nvidia/cuda:7.5 nvidia-smi -pm 1
nvidia-docker run --rm --privileged nvidia/cuda:7.5 nvidia-smi --auto-boost-default=0
nvidia-docker run --rm --privileged nvidia/cuda:7.5 nvidia-smi -ac 2505,875
[ec2-user@ip-10-0-0-10 ~]$ docker run --rm -e CONCURRENCY=16 -e REQUESTS=20000 --net=host client
Summary:
Total: 7.9519 secs
Slowest: 0.0200 secs
Fastest: 0.0055 secs
Average: 0.0063 secs
Requests/sec: 2515.1144
Total data: 6880000 bytes
Size/request: 344 bytes
[...]
そもそも p2 系はスペック的に学習に最適なサーバだと思いますが、推論でもこれだけ違いがでてくるとわくわくしますね!!
利用する GPU デバイス数を変えてみる
NVIDIA-docker はやれる子なので、docker コンテナに引き渡しアプリで利用するデバイスを自由に指定できます。(当然ながら docker コンテナからは渡された GPU しか見えません)
現在動いているサービスを一度止め
docker stop api
docker rm api
5 GPU に制限して起動し直します。
NV_GPU=0,1,2,3,4 nvidia-docker run -d --name api -p 8000:8000 inference
[ec2-user@ip-10-0-0-10 ~]$ docker run --rm -e CONCURRENCY=5 -e REQUESTS=20000 --net=host client
Summary:
Total: 25.8224 secs
Slowest: 0.5705 secs
Fastest: 0.0055 secs
Average: 0.0064 secs
Requests/sec: 774.5201
Total data: 6880000 bytes
Size/request: 344 bytes
[...]
それっぽい値ですね!
おわり。
-
yum update でカーネルが更新されてしまうと、再起動時に必要なモジュールが読み込まれなくなるため。
sudo sh -c 'echo "exclude=kernel*" >> /etc/yum.conf'
などで対処しておいてもいいかもしれない ↩ -
docker: Error response from daemon
が返ってきたら再度実行してみてください。2度目なら通ると思います ↩ -
Go の http サーバ経由で Caffe での推論を行う薄いラッパーです ↩
-
画像の推論はせず、CUDA の kernel call のみを計測するアプリケーション も同梱されています。 ↩
-
上限緩和しないと使えないのですが、そもそも申請フォーム上 p2 系が選択できないため、コメント欄で「p2 使わせて!」と懇願してしばらく待ちましょう ↩
-
g2 などでの AMI 化がうまくいっていないと p2 起動後に絶望するので、間違いなく動作する、NVIDIA 公式 AMI からスクリプトをあてていく手順をお勧めします。慣れていなければ。 ↩
-
推論サーバは GPU 分の初期化処理(モデルのロードなど)が走るため、起動までしばらく時間がかかります。
docker logs -f api
などで "Starting server listening on :8000" が表示されるまで気長に待ちます。 ↩