研究開発部の染谷 ( @ayemos_y ) です。好きな ImageNet のラベル(Synset)は "Eccentric, eccentric person, flake, oddball, geek" です。
クックパッドの研究開発部は2016年7月に発足し、現在はアルバイトを含め13名の体制となっています。その中で、こちらの記事でも紹介されている料理/非料理判別モデルを開発するなど、機械学習/ディープラーニング分野に特に力を入れて取り組んでいます。
最近は、モデルを開発し改善する手法などについて多くの情報にアクセス出来るようになり、このような技術をプロダクトに応用していきたいという気持ちが高まっている現場が多いかと思います。しかし一方で、分析の為のデータへのアクセスや画像認識モデルの実装や実験を行うためのGPU環境の整備など、現場の都合に対応するコストによって開発の勢いが鈍化してしまうような状況もめずらしくありません。
特にそのようなコストがチームのサイズに従って増えていくような場合は(つまり多くの場合においては)、組織のスケーラビリティを損なう重大な問題です。
クックパッドの研究開発部では、このような研究開発、特に機械学習における開発基盤にまつわる課題の解決にも積極的に取り組んでいます。今回はそのような取り組みの一部を紹介したいと思います。
研究開発専用AWSアカウントの利用
クックパッドには技術部開発基盤グループ/モバイル基盤グループなどの組織があり、開発基盤の整備や改善に取り組んでいますが、最近ではこのような組織が部署横断的かつ中央集権的に請け負っていた仕事を、部署ごとに分散出来るような体制に移行しつつあります。(この辺りの詳しい話はAWS Summit Tokyo 2017でも発表しました。 資料 動画 )
その取り組みの一環として、研究開発目的で利用するAWSアカウントを本番アカウントと別に用意し、研究開発部のメンバーの一部(現在は私だけですが)にAdminに近い権限を付与した上で、部署の責任範囲において開発基盤を積極的に改善するという体制が敷かれています。
オンデマンドGPUインスタンス
アカウント分離以前にも研究開発目的でGPUを利用したいという案件がありました。その際にはインフラストラクチャー部への依頼に始まり、必要なコンポーネントなどの要件のすり合わせと実際の作業が行われ、その間コミュニケーションが数往復しました。
結果として、本番アカウントに g2.2xlarge インスタンスが立ち上がり、必要コンポーネントがインストールされて利用可能になるまで4週間程かかりました。このような作業を部内で消化出来るようにするというのがアカウント分離の目的の中心でしたので、アカウントを分離後早速GPU環境の整備に取り組みました。
GPU環境とはつまり、GPUの搭載されたEC2インスタンスで、GPUを利用した開発が出来るものですが、OS環境が(不可逆に)壊れてしまった場合や、2台以上のGPUが必要になった時などを想定すれば、このような環境を低コストで繰り返し用意出来るような状況が望ましいです。手動でセットアップする従来の手法ではこれが実現出来ていないという課題がありました。ドライバーやCUDA Toolkitなど比較的低レイヤなセットアップ作業が多く、手間と時間もかかります。
そこで、最低限のコンポーネントを揃えた状態からAmazon Machine Image(AMI)を作成し、同じ状態のインスタンスを繰り返し立ち上げられるようにしました。
Packer を利用したAMIの構成管理
またさらに、各コンポーネントのバージョンアップや、異なるバージョンでセットアップされた複数のAMIを安定して管理するために、Packerを利用し、機械学習で利用するAMIを作成/構成管理しています。
PackerのChef Solo Provisioner)を利用し、Chefのrecipeと呼ばれるセットアップ手順を定義することで、これを自動で実行し、実行後の状態をAMIとして保存することが出来ます。これにより、手順をコードとして管理しておけるだけでなく、recipeを適切にパラメータ化することで、CUDA8/9をインストールしたAMIをそれぞれ別の名前で作成する等の作業を簡単に行うことが出来ます。(下図)
Slack Chat Botを利用したインスタンスの操作
AMIを用意した事で、必要なコンポーネントがインストールされた状態のGPUインスタンスを繰り返し作成することが出来るようになりました。しかしながらEC2インスタンスをオンデマンドで立ち上げる際には、VPCと特定のサブネット(のうち1つ)、キーペアやセキュリティグループを適切に選んでやる必要があります。またクックパッドではEC2インスタンスへの接続を適切に経由するためにインスタンスへのタグ情報を利用しており、これもまた設定してやる必要があります。
このような一連の操作を繰り返さない為に、Slack上で動作するChat Botから、より抽象度の高い操作によりインスタンスの作成や停止/再開を行えるようにしました。Chat Botの開発にはLitaを利用しました。
蛇足ですが、このような問題を解決するためにコマンドラインで動作するツールを配る事もできますが、Slackをインターフェースにする事で実行環境が統一されるので、開発者ごとの環境の差異を気にしなくて良くなり、また、利用されている様子から使い方を自然に見て覚えられたり、改善のヒントが得られるなどの利点があります。
インスタンスの自動停止
AMIとChat Botを整備したことにより、必要なGPU環境が数分で手に入るようになりました。一方副作用として、立ち上げたインスタンスの落とし忘れにより、アイドルなインスタンスから発生するコストが増えてきました。例えば金曜日の退勤前に実行した実験が深夜に終了し、その後週末の間なにもせずに立ち上がったままである、といったことが頻繁に起こるようになりました。
これ自体はコスト面で致命的な問題になるほどではないのですが、EC2インスタンスの課金も秒単位になったことですし、使用していないインスタンスはなるべく早く停止したいところです。
そんな時は、Amazon CloudWatch EventsとAWS Lambdaを組み合わせることで、「一定時間以上アイドルなインスタンスを停止させる」Pythonスクリプトを「5分毎に実行する」といった構成を非常に簡単に実現することが出来ます。
ちょっとした考察
計算機コストの最適化を考えた時に、例えばコンテナによって仮想化され、場所透明性を持ったワークロードをインスタンスのグループ(あるいはプール)において実行する事で、よりインスタンスのアップタイムを効率的に利用出来るといった手法も考えることが出来ます。
しかしながら複数のワークロードでGPUを共有する場合には、コンテナ化するだけではなく、ワークロードのスケジューリングなどの複雑性を導入する必要が出てきます。またコンテナ仮想化それ自身も、実験環境の可搬性を高めるという点で便利な一方で、ネットワーキング、ロギング、データ永続化など、いくつかの複雑さが導入されるという意味で、実験環境において必要でなければ使わないという姿勢が適切なようにみえます。
そのような理由で現状は、個人に対して個人が専有出来るインスタンスを用意して必要に応じて動かすという構成を取っています。しかしながら今後も使用感やコスト面の課題を探しながら継続的に改善を進めて行くことになります。
まとめ
というわけで、今回はクックパッドの機械学習基盤についてお話しました。 Packerを利用して必要な環境をAMIとして作成/管理し、Chat Botを利用して作成/停止/再開する事で、チームメンバのそれぞれが、長くとも数分で必要なGPU環境を利用出来るという環境を整えました。
研究開発部というと、どうも実際のプロダクトと距離があるという印象ですが、チーム単体で見た時にもそれはやはりユーザーに価値を届け続ける組織である必要があると考えています。言い換えれば、ユーザーとの接点であるプロダクトに繋がるアウトプットをし続ける事が必要であり、その為にすばやい実験や実装が出来る環境があることも重要です。
そのような考えから、機械学習/ディープラーニングを中心とした最新技術へのキャッチアップとその応用はもちろん、チームの成果を最大化するための運用の改善にも積極的に取り組んでいます。
クックパッドで機械学習を利用して新たなサービスを創り出していける方に加え、研究開発部の開発環境を改善していく方も募集しています。 興味のある方はぜひ話を聞きに遊びに来て下さい。
追記(お知らせ)
11月27日-12月1日にラスベガスで開催される AWS re:Invent 2017 にインフラ部の星と一緒に登壇します。 "Containerized Machine Learning on AWS" というテーマで料理きろくで利用されている画像判定システムののアーキテクチャを中心に話します。乞うご期待!