Housmartの高松です。今回はディープラーニングのためのGPU計算実行環境を物理サーバーからAWSのECSに移行した話について紹介したいと思います。
昨今のディープラーニングブームで、普通のWebサービスを作るエンジニアでもGPU実行環境が欲しい!という場面に出くわすことが多くなってきていると思います。そんな時にサクッと環境を作れるとかっこいいですね。
また、この記事はディープラーニングのエンジニアリング Advent Calendar 2017の25日目に参加しています。
背景など
Housmartでは、マンションを賢く買えるアプリ「カウル」で提供している売り出し中のマンションの市場相場価格を推定する機能にディープラーニングを利用しています。その他にも実験的なプロジェクトとしてディープラーニングを用いた画像分類などにも取り組んでいます。
実行環境として、2年ほどGPUを搭載した物理マシンをオフィスに置いて計算を行なっていましたが、2017年12月からAWS ECSに移行しました。
理由としては以下の2つです。
クラウド上のGPUマシンの値段が下がって来た
GPU物理マシンを構築した当時(2015年ごろ)は1番小さいGPUインスタンスを1ヶ月起動し続けるだけで20万円を超えるくらいの金額だったと記憶しています。(移行前の物理サーバが1台20万円ちょっと)
今では値段も下がってきて、AWSのGPU搭載で一番小さいp2.xlargeのインスタンス(1GPU/4vCPU/61GB RAM)だと1時間あたり$0.9と非常に安価に利用できるようになってきました。
1ヶ月稼働し続けたとしても \$650/month 、仮に1日あたり2時間程度の利用だとすると \$54/month です。日次で動かすバッチだけならこの程度のコストで利用可能なので、移行を決めました。
参考) Amazon EC2 P2 インスタンス Amazon EC2 P3 インスタンスをリリース
物理サーバーは管理がやっぱり辛い
2年程度GPUマシンの管理をしていましたが、やっぱり物理サーバーの管理は辛いですね。
ネットワークのトラブルや、間違えて環境を壊してしまったり、ドライバやOSのアップデートで動かなくなったりとその度にトラブルシューティングに結構な時間を取られてしまいます。
なぜAWSを選んだか
GCP・AWS・さくらなど、現実的な選択肢がいくつかありますが、各社値下げ合戦をしているのでそこまで大きな価格差は今後も出ないだろうという予想をしています。
なので、現状のカウルのインフラ構成に沿ってAWS ECSを使うことに決めました。リソースをたくさん使う様ながっつりしたGPU計算をする場合はもうちょっとシビアに比較した方がいいかもしれませんが、カジュアルな使い方ならAWSで十分でしょう。
現状、値段的には Microsoft >>> IBM >> AWS > GCP > さくら という感じでしょうか。ただ直近さくらはNVIDIAのライセンス問題もあり、今後どうなるかはわかりません。
構成
以前のブログ「会社の本番環境をDocker(ECS)に置き換えるために準備したこと気づいたこと」で紹介したDigdagを用いたバッチ実行環境から、GPUマシンで構築したECSクラスタにjobを投入する方式を採用しています。(Digdagからのjob実行時にクラスタ名を渡しているので、そこにGPUクラスタ名を渡すイメージ)
また、24時間フル稼働させる必要はないので、GPU計算を必要とするjobの直前にGPUクラスタにインスタンスを追加し、バッチが終わり次第インスタンスを落とすという経済的な設計になっています。
インスタンスのスケーリングはecs-cliというECSクラスタ用のコマンドラインツールを使っています。
クラスタ設定方法
以下の手順で設定していきます。
- GPU on ECS用のAMIを作成する
- ECSクラスタを作成する
- ECSクラスタの裏側にあるCloudFormationにAMIを登録する
- GPU用のTaskDifinitionを作成する
順番に見ていきましょう。
1. GPU on ECS用のAMIを作成する
公式ドキュメントが存在するので、こちらを参照してください。 GPU用のドライバが入っているAMIにnvidia-dockerをインストールして、再度AMIを作成する手順です。
nvidia-dockerとは、dockerのラッパーとして実装されているツールで、ホストOS上にNVIDIAのドライバがインストールされていれば、CudaToolkitを含んだコンテナからGPUを利用出来るようになります。 参考)http://www.nvidia.co.jp/object/docker-container-jp.html
2. ECSクラスタを作成する
こちらも公式の手順にそってクラスタを作成してください。 細かい設定はこの後いじるので、基本的にはデフォルト値で作成して問題ありません。
3. ECSクラスタの裏側にあるCloudFormationにAMIを登録する
ECSは実は裏側でCloudFormationのテンプレートを保持しています。 クラスタで起動するインスタンスのタイプや元となるAMIを変更するにはCloudFormationのテンプレートを修正する必要があります。
AWSコンソール上で CloudFormation > EC2ContainerService-${クラスタ名}を選択 > Update Stack > 2番目の画面で以下2箇所を設定 > 更新 で設定完了です。
4. GPU用のTaskDifinitionを作成する
先ほどのドキュメントにもある通り、実行時にコンテナからnvidiaのドライバを見える様にする必要があるので、マウントポイントを設定しましょう。以下のコマンドの-vオプションに相当する設定です。
sudo docker run -v /var/lib/nvidia-docker/volumes/nvidia_driver/latest:/usr/local/nvidia nvidia/cuda:9.0-cudnn7-devel nvidia-smi
ECS > Task Definitions > Create new Task Definition > Add volume としてマウントするVolumeを作成します。
続いて Add container > Mount points から作成したVolumeをマウントします。
あとは通常通りTaskDefinitionを作成してください。
これでECS上からGPU計算ができる環境が整いました。
インスタンスのスケーリング
最後にインスタンスのスケーリングについて紹介します。 ecs-cliをこちらを参考にインストールします。バイナリが配られているので落としてくるだけでOKです。
AWSの環境変数をセットして
export AWS_ACCESS_KEY_ID=xxxx
export AWS_SECRET_ACCESS_KEY=xxxx
以下のコマンドでecs-cliからクラスタのインスタンス数を操作することができます。先ほど設定変更したCloudFormationのStack nameを指定しなければうまく動かないので注意してください。
# ecs-cliの設定
ecs-cli configure --region ap-northeast-1 --cluster ${cluster-name} --cfn-stack-name ${cloudformation-stack-name}
# GPUインスタンス1台立ち上げ
ecs-cli scale --capability-iam --size 1
# GPUインスタンス全台ストップ
ecs-cli scale --capability-iam --size 0
上記のコマンドをシェル化して、Digdagの定義でGPU計算jobの前後で呼び出せば使う時だけインスタンスが立ち上がるようになります。
参考) http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ECS_CLI_installation.html http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/cmd-ecs-cli-scale.html
最後に
いかがでしたでしょうか。今回はAWS ECS上でGPU計算環境を構築する手順をご紹介しました。 みなさんがクラウド上でGPU環境をサクッと作れる様になる助けになれば幸いです。