リソースとコストの最適化、そして、機械学習ジョブの実行方法

服部圭悟氏(以下、服部):では続いて、「リソースとコストをどう最適化するか?」と「機械学習ジョブをどう実行するか?」を同時に説明したいと思います。

やりたいこととしては、可能なかぎりコストを抑えて、でも安定した計算機クラスタを作りたい。安かろう悪かろうじゃダメってことですね。

それからスケーリングを自分でマネージドしたくないというところ。必要に応じてインスタンスが追加されて、必要なければインスタンスが削除されるような、オートスケールアウト・オートスケールインをやりたい。これをGPUサーバでもやりたいというのが要求ですね。

さらに可能なかぎりいろいろなジョブをもう本当に計算機クラスタをフル稼働させて使いたい。24時間365日働かせたいというところが要求としてあります。

Spot InstancesとKubernetesジョブを使う

これを文献ではどうしたかというと、Spot Instancesを使っています。Spot InstancesとはAWSのサービスで、安く計算資源を借りられるようなものになっています。これにEKSを組み合わせることで安価な計算機クラスタを作ったと。

機械学習のジョブはKubernetesのジョブを使っています。Kubernetesの中にキューイングとスケジューリングが入っているので、そこを気にする必要がなくて、かつKubernetes Jobってリトライポリシーとかを簡単にyamlで設定できるので、簡単にリトライとかもできるから、そこをけっこう便利に使えます。たぶんAWSでいうとAWS Batchのような機能ですね。

もう1つ何をしたかというと、Spot Instancesを使っている以上、インスタンスがふいに取り上げられることがあるんですね。2分前に通知されるんだけど、2分でできることなんてほぼないので、これに対応する必要があります。

文献ではどうしたかというと、少なくとも10分に1回チェックポイントを設けて、それをEFSに保存する。学習の結果を保存するということをしています。

そうするとジョブが死んだときに、Kubernetesがジョブ死んだということを検知するので、新しくリトライしようと、新しくジョブを作ろうとしますと。ジョブの中でEFSを参照してチェックポイントから学習を再開するというコードが入っているので、死んでも途中から再開できるよという構成にしています。よくできている。

ABEJA Platformでの解決

ABEJA Platformではどうしているかについて話すと、同じ感じになっています。Spot Instancesを使っています。Spot Instances自体の管理がすごく大変なので、これ僕がやったわけじゃないのであれですけど、Spot Instancesを合理的に管理するSpotInstというサービスを使っています。こちら文献あるので、ぜひ見てほしいと思います。

ほかにどういうノウハウがあるかというと、まずインスタンスに使うイメージを固定しました。何を言っているかというと、プラットフォーマーなのでユーザーが自由に使えてほしい一方で、ユーザーがどのCUDAのバージョンを使うかわからないので、全部入っているAll-in-Oneのイメージを使うってことをしています。

ほかには、インスタンスの種類を固定した。何を言っているかというと、Kubernetesを使うとCPUとメモリの要求量を自分で選べるんですよ。ユーザーにリソース量を選ばせることもできます。ただ、それを自由にやらせるとパズルがはまらなくなります。インスタンスに効率的に学習ジョブを配置できないんです。すると、インスタンスの利用効率が下がって、余剰が微妙に空いているインスタンスがいっぱい立ち上がることになるので、そうするとこっち側がお金をけっこう払わなければいけない。

そこをコントロールしたくなかったので、選択肢から「CPUはこの中から選べ」とか「メモリはこれだけのサイズの中から選べ」というような選択肢制にすることで、インスタンスの利用効率を上げて費用を抑えるってことをしています。

それからユーザーのコードをEFS上にダウンロードして動かすということをしています。これは何をしているかというと、成果物のサイズが予想できないように、コードのサイズも予想できないんですね。

人によっては言語モデルをコードの中に内包して、それをGitリポジトリに格納する場合もまぁまぁあるというので、それによってDisk Fullで死ぬってことを避けたいから、コードもEFS上にダウンロードして、Disk fullでPodが死なないようにするというノウハウを使っています。

分散学習について

では、最後に分散学習どうするかについて。やりたいことは、複数のGPUを使った分散学習がしたい。ただし、既存のコードはそのためだけに変えることはしたくありません。

文献ではどうしたかというと、Horovodというものを採用しています。HorovodはたしかUberが作っているOSSだったと思うんですけど。

Horovod自体は複数のインスタンスの上で起動させられるし、複数のインスタンスと協調して分散学習ということもできるんですけど、KubernetesでSpot Instancesを使っている構成の関係で、Workerノードがふいに死ぬことがあったりします。すると、そのへんのコントロールが非常に面倒くさいことになります。そこで文献では、Multi-GPUを使ったシングルインスタンスにおける分散学習だけをサポートするという決めをしています。

HorovodはDocker Imageをたくさん提供していて、主要なライブラリは全部押さえているので簡単に使えるところと、サンプルコードがすごく充実していて、実際に見ていただくとわかるんですけど、既存のコードをほとんど変えることなく分散学習ができるというところで、すごく簡単に導入できて便利だなと思いました。

ちなみにSpot Instancesを使っているためジョブが突然死するので、学習を再開できるようにmaster-workerがほかのワーカーの面倒を見るようなかたちにもなっています。実際に変数の値を初期化するのもmaster-workerの仕事にしていますし、チェックポイントへの書き出しとチェックポイントからの復元も全部master-workerがやるというふうにしています。

もちろん乱数は固定して、データをシャッフリングしたりとかデータをスプリットするときの乱数シードを固定して再現できるようにしています。

ABEJA Platformでどうしているかというと、まだ分散学習はサポートできてはいません。公式にはできていないです。ただ、ABEJA Platformも自分の任意のDocker Imageを使えるので、一部ちょっとした独自のルールがあるんですけど、そこをうまいことやればできなくはない。ただ、公式にサポートしたいと思っているので、話をしていたところでした。

今日持ち帰れること

最後に振り返りです。データセットはEBSにもって、成果物はEFSにもつような運用をしたいので、両方ともマウントして使うのがいいというのが1つ。リソースとコストはSpot Instancesを使うといいよというのがもう1つ。機械学習のジョブはKubernetes Jobを使うと楽にできるよというのが1つ。最後が、分散学習をどうするかというと、Horovodを使うと簡単にできるよというのが今回のお持ち帰りでした。

本当、先ほども言ったとおり、我々の経験を踏まえてもすごくこの記事の言っていることは的を射ていると思ったし、すごく簡潔にまとめてくれてありがたいというところで、すごくよかったという話を今日はして、おしまいになります。

ご視聴ありがとうございました。

成果物の保存にS3を使わない理由

上田隼也氏(以下、上田):いや、すばらしいですね。

服部圭悟氏(以下、服部):ありがとうございます。

上田:質問が2個ぐらい来ています。1つ目です。「データセットにEBSを使う理由はとても納得できたのですが、なぜ成果物の保存にS3を使わないのでしょうか? EFSを使う理由はS3でもいけるんじゃないでしょうか?」という質問です。

服部:結局S3にも保存するんですね。なんでEFSを使っているかというと、「ファイルを保存するときにS3に保存するコードを誰が書くか?」という話なんです。

機械学習エンジニアが自由に使いたい……ようにしたかったので、本当にローカルにファイルを保存するのが一番簡単じゃないですか。なんかS3のbotoを使ってとかやるよりは。その体験を作りたかったので、まずEFSに吐き出すってことをしたかったのが1つ。

もう1つは、さきほど成果物をTensorBoardとかで見たいって話を言ったと思うんですが、S3に上げてしまってまたもってくるというのをしたくなかったので、そういうファイルを直接置くという体験を届けたかったのと、置いてもメリットがあるので、EFSを1回介しています。

EPSとEFSの速度差

上田:なるほど。では次の質問です。「EBSとEFSはどれぐらいReadの速度の差があるのでしょうか? モデルにもよると思うのですが、学習時間のほうが読み込みの時間よりも支配的な印象があり、ABEJAさんがEFSを採用されたように、どちらを採用するかはケース・バイ・ケースなのかなと思いました」というやつです。

服部:これは、プロファイリングしたメンバーがいたんですけど、その時はそんなに差が出なかったんです。ネットで調べると3倍ぐらい違うよというのが出てくると思います。

これは本当に再現しないのですごいあれなんですけど、自分で実際に機械学習のジョブを回していると、明らかにEFS上で回していると遅いんですよ。EBSは試せていないのであれなんですけど、MacBook Proでローカルでやっているときは速かったのに、プラットフォーム上でやるとめちゃくちゃ遅いの何でだろうと思って見てみると、ファイルの読み込みのところでめちゃくちゃ時間かかっているのがわかるんですね。

だから本当、まだうまくプロファイリングできていないですけど、EBSのほうが速いというのを信じて、そっちに賭けたいって感じですかね。

S3のストレージクラスの使い分け

上田:なるほど。では僕からも質問していきたいと思います。僕けっこうGCPを使っているのでGCP的な質問になっちゃうんですけど……。

GCSとかってけっこう種類ごとに保存できたりするんです。例えば「アクセス回数めっちゃ少ないから、その代わりめちゃくちゃ安いストレージバケットにする」とか「頻度が高いからその分高くなる」みたいなのとかあります。

S3とかにも例えば「もうアーカイブ同然のデータだったらめちゃくちゃ安くする」とか「頻繁にアクセスするから逆に高い」みたいなとか、そういう分けて保存する機能とかあって、ABEJAさんとかでもそういうふうに用途で分けてS3を使っているのかどうかみたいなのを聞いてみたいなと思いました。

服部:いや、僕も詳細は把握していないんですけど、でもそれは使っていますね。ログとかは一定の期間のあとにコールドストレージのほうに移すということはしています。たぶんそれぐらいですかね。

上田:なるほど。ただ、コスト関係のところは僕もかなり共感できていて。僕の会社とかでも、1つのGCPを共有にして学習ジョブとか走らせてみたいな。気がついたらめちゃくちゃビリングコスト高いのがポンと生まれていて「誰これ?」みたいな。なんかこう、慌てて消すとか。あとEBSなんかめっちゃ作られていると、「なぜだ?」みたいなとか、いろいろあったりするんですけど。

やっぱりプラットフォームとかでかなり抽象化していかないと、人手でマニュアルで作ったものをがんばって探してまた消していくとか。アラートかけるのもそれは1つの手だと思うんですけど、使い手側にまた面倒くさいだろうなと思ったりするので。

服部:そうですね。

上田:難しいところだなと思いますね。

服部:そう思います。本当。

上田:実際、例えば……これはけっこうセンシティブな質問なのかもしれないですけど、機械学習プラットフォームをビジネスとして提供する場合って、インフラのコストのほうが高くなっちゃって、ビジネス的な利ざやというか、そういうのけっこう難しそうだなって僕の印象ではあるんですよ。

服部:いや、本当そうなんですよね。そもそもAWSとかGCPとかの計算資源が提供されている上でサービスをするので、そこがまずベースとしてかかっています。クラウドインフラにすごく詳しい人からすると、やっぱり「このCPUでこれだけ使ったらこれぐらいでしょ」というのは感じるところなんですよね。そこの上で僕ら商売しているので、やっぱり少し割高になってしまうってところはけっこうつらいところで。

どうしているかというと、やっぱり自分たちでAWSとかでプラットフォームを組むと、相当いろいろやらなきゃいけないことがあるんですよ。本当、プラットフォームにする上で必要なこととかすごくいっぱいあって。

先ほどのエージェントのクリーナーとかもそうですし、どのユーザーがどれだけ使ったかというクォータの管理とかもしているんですね。そういうのを全部自分で実装しようとするととてもじゃないけど大変だから、プラットフォームを使う価値あるよねってところがやっぱり大きいですね。

Kubernetesを使うと効果的な機械学習の種類

上田:次の質問が来ました。「Kubernetesを使うと効果的な機械学習の種類(例えば画像分析・自然言語処理など)はどんな場合でしょうか? 機械学習でKubernetesを使うメリットがまだイマイチわかっていないので、メリットを教えていください」という質問です。

服部:効果的な学習対象というのは実際ないですね。ただの計算資源なので。

何がいいところがあるかというと、機械学習エンジニアでも比較的簡単にKubernetesって使えるんですよ。それは運用するという意味ではなくて、自分でその計算クラスタを作って自分で運用……自分でマネージドするって、本当自分しか使わないという意味で。

ECSとかでプラットフォームとかがんばって作ろうとするより、Kubernetesでポンッとただジョブを投げるほうがけっこう簡単にできます。あんまりインフラの知識がなくてもそこそこ使えるってところはメリットとして1つありますね。

2つ目のメリットとしては、やっぱりKubernetesがすごく流行っているので、MLOpsでも「Kubernetesを使ってやっていこう」という文脈がすごく増えています。Kubeflowもそうですが、そういうKubernetesで動く機械学習のOSSの話がけっこう。その恩恵が使えるのは大きいですね。

先ほどのHorovodもOpen MPIのやつを使っているんですが、公式にオペレーターとかが増えていて、TensorFlowとかPyTorchとかのオペレーターとかも簡単に使えるようになっています。分散学習とかすごくしやすくなっていて、エコシステムもけっこう整ってきているから、Kubernetesに乗っておくとけっこう楽できるところは多くありますね。

学習フェーズの再現性

上田:なるほど。次の質問が来ました。「ABEJAさんでは学習フェーズの厳密な再現も重要視されていますか? 以前の後藤さんのツイートで乱数固定だけでは再現の困難さを言っていたので気なります」と。これ服部さんのことですよね。たぶんちょっと名前が後藤さんですけど。

服部:再現性ですか? お客さんでもあんまりまだそこまで気にしている人は多くはなかったですね。

重要な要素は僕じゃなくてKubeConとかでも、けっこう発表されていて、データに何を使っただとかアノテーション結果にどれを使ったかだとか、そういうのをきちんとバージョニングして管理する必要があるという話はもちろん出ています。

たぶんそれが重要になってくるのは人命がかかってくるところで、今でもすでに気をつけているところだったら、医療とか金融、あとは自動運転とかですかね。そのへんはもう本当にデータのバージョン管理とかはしっかりやっています。

再現性のためにはそういったデータ、それから「どのGPUを使ったか?」というところとかを全部気にする必要があるし、もちろん乱数シードも固定する必要があります。固定したつもりが固定していなかったということもありうるし、マルチスレッドしたら実はマルチスレッドは固定していなかったということもあり得るので、そういうところはちゃんと再現性を重視するのであれば、しっかりとマネージドしていかなきゃいけないところではありますね。

ただ、あんまりまだ世の中的に再現性を重視している事例はそんなに出ていないと思うし、実際自分たちでPoCを回したりだとか案件とか回していく中では、そんなにまだ重要なところではないと思います。

上田:なるほど。僕も経験的に感じるのは、けっこう地獄ですよね。それ完全な再現性はありますかと聞かれると辛いという。

服部:そうですね(笑)。

上田:そもそもその段階ではないみたいなというお話でもありますね。

服部:そうですね。

Kubernetesを使った機械学習基盤アークテクチャの参考文献

上田:次の質問です。たぶんこれで最後ですね。「Kubernetesを使った機械学習基盤のアーキテクチャで参考にある文献とか記事などはありますか?」というものです。

服部:そうですね。僕がリンクどこかで……あっ、資料に……書いていないか。「https://ethical.institute」というのがあって、そこのメルマガに登録しておくとすごくいいですね。僕いつも、そこからけっこうキャッチアップしています。

服部:そこがホストしているGitHubのリポジトリがあって、そのGitHubのリポジトリにMLOps関係のOSSがかなりたくさんあるので、それを全部マスターしたらもうたぶん世界一詳しいと思いますので、そちらがオススメです。「https://ethical.institute」というところです。

上田:僕も毎週メルマガ読んでいます。

服部:いいですよね。

上田:はい。じゃあ最後にこれだけやっちゃいましょうか。「(ABEJAでは)生のk8sを使っているのか、もしくはKubeflowみたいのを使っているのでしょうか?」という質問です。これで質問を打ち切ります。

服部:生のKubernetesを使っています。生のKubernetesでその上でホストするサービスを作っています。Kubeflowは少し試して、なんかこれをマネージドしていくのがつらいなと思ったのでやめました。

上田:Kubeflowを提供するというのがきつそうですね。運用するのは辛そうな気が。

服部:バージョンもけっこう上がるし、まだそんな使えなさそうなやつもけっこうあるので。

上田:わかりました。服部様、今回の発表、ありがとうございました。

服部:ありがとうございました。