ACES エンジニアブログ

ACESのエンジニアブログです。

まさにコストカット祭り - GPUサーバー代を約30%削減した話 -

こんにちは!ACES でソフトウェアエンジニアをしている西川(@kotosearch)です。

今回は「まさにコストカット祭り - GPUサーバー代を約30%削減した話 -」と題して、高くつきがちな GPU サーバーに焦点をあてて、実際に私たちがコストカットに成功した Tips を皆さんにご紹介したいと思います。

前提として ACES は上場を目指しており、事業の健全性や採算性が求められる中で、予実の達成は不可避です。喫緊の課題として原価通信費(サーバー代など)の増大が上がっており、こちらを削減することが至上命題でした。

1年ほど前の話にはなりますが、2024年2-3月ごろにかけて行ったコスト削減の取り組みについて語って行きます。

そもそも GPU サーバーって高いの?

私たちのプロダクト ACES Meet では、録画・録音した会議データを解析し、文字起こしやサマリー、スタッツ等をユーザーに提供する Web アプリケーションです。

音声や動画の解析はプロダクトのコアバリューなのですが、音声・動画解析は非常に高負荷なタスクであり、CPU に比べて並列計算が高速な GPU を使う方法が主流です。

しかし、GPU インスタンスは CPU インスタンスに比べて利用料金が高いので、「必要な時に必要なリソースだけ使う」という観点を持たずに運用していると、あっという間に月々の費用が跳ね上がってしまいます。

EC2 インスタンスのオンデマンド料金(東京リージョン)で比較すると、同じスペックでも GPU インスタンスの方が2倍ほど高い料金設定となっています。

抱えていた課題

前提として、ACES Meet では AWS Batch を使って GPU インスタンスを起動し、推論処理を実行します。

AWS Batch は「インスタンスの起動 ⇒ コンテナの起動・実行・停止 ⇒ インスタンスの停止」を自動でやってくれるサービスで、インスタンスの起動時間に応じて課金されます。

推論に使う重みファイルは Docker イメージに含まれており、ECR から都度 docker pull してインスタンスを起動していました。

そしてこの仕組みで運用していると、次第に以下のような課題に直面しました。

  • docker イメージにモデルの重みファイルや pytorch のような重いライブラリなどを含んでおり、docker pull に 10分 以上かかる
  • docker pull が長いせいでインスタンスの起動時間が伸びてしまい、コストが高くなる
  • 実行環境を隔離するため1つのEC2インスタンスに1コンテナだけ起動するようにしているので、イメージキャッシュが非常に使いづらい

特に docker pull 時間が伸びることで、コストとユーザー体験の両面で悪い影響を与えていたので、なんとか GPU サーバーの起動時間を短くできないか模索していました。

解決法

結論からお話しすると、コストカットで効果的だったアプローチは以下の2つでした。

  1. コンテナイメージの容量を削減する
  2. ボリュームの I/O 性能を上げる

詳しく解説していきます。

1. コンテナイメージの容量を削減する

重みファイルを Docker イメージではなく S3 に配置

AIを活用していると学習済みモデル(重みファイル)の容量が大きくなるケースが多々あります。

従来はこれらのファイルをコンテナイメージに直接含めていましたが、イメージサイズが増えて docker pull が非常に遅くなることで、起動も遅くなるしコストも増えるという問題がありました。

重みファイルは切り離し可能だったので、こちらは AWS S3 に配置し、コンテナ起動後にダウンロードする方式に変更しました。

重みファイルを剥がしたことでコンテナ自体が軽量化し、プル時間の削減によってGPUサーバー代を15%削減できました。

こちらはシンプルな方法ですが、運用している以外と盲点になっていて気づかなかったので、ちょっとした労力で大きくコスト削減できた例でした。

2. ボリュームの I/O 性能を上げる

EBS ボリュームを gp2 から gp3 に変更

GPU サーバーとは直接関係ないですが、まずはボリュームタイプを gp3 へアップグレードしました。

理由は「シンプルに安い」のとスループットを上げられる」こと。同じ容量でも実は gp3 の方が20%安く、また IOPS やスループットなども gp2 に比べて大幅に引き上げ可能です。

後述するスループット向上」のためにアップグレードしたかったのですが、ストレージを変えるだけで単価も下がるのはラッキーということで、すぐさま gp3 に移行しました。

docs.aws.amazon.com

EBS ボリュームのスループットを上げる

まず用語の解説からです。ボリュームの I/O 性能を表す指標には次の2つがあります。

  • IOPS: 1秒間にストレージへ読み書きできる回数
  • スループット: 1秒間にストレージへ読み書きできる容量

docker イメージはモデルや推論関連のライブラリなど重いものが入っていると、スループット性能を上げることで docker pull が早まる可能性があるのです。

解説に入る前に、docker pull について少し掘り下げます。

Docker イメージは複数のレイヤーで構成されており、レイヤーの実態は圧縮された tar アーカイブファイルです。

docker pull を実行すると、各レイヤーをリモートレジストリから並列でダウンロードし、ダウンロードできたレイヤーから順次展開(解凍)していきます。

% docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
f7ec5a41d630: Pull complete
aa1efa14b3bf: Extracting  2.654MB/26.58MB  # 展開中
b78b95af9b17: Download complete
c7d6bca2b8dc: Download complete
cf16cd8e71e0: Download complete
0241c68333ef: Download complete

dockerlabs.collabnix.com

docker pull に時間がかかっていた原因をよく調べると、ダウンロードより解凍に時間がかかっていることがわかりました。

ということは、ストレージのI/O性能を上げて解凍を早めれば良いのでは?ということで、やってみました。

重いイメージを素早く解凍する必要があるので、IOPS ではなくスループットを上げて検証してみることにしました。(スループット: 1秒間にストレージへ読み書きできる容量)

前提として、GPU サーバーのコスト推移は以下のように計算します。概算を知りたいので、細部は省略しています。

段階的にスループットを上げて検証し、インスタンス起動時間とコスト削減幅をプロットしていった結果、スループット275MB/s にすると最も ROI が高いことがわかりました。

結果的にインスタンス起動時間は4分短縮。GPUサーバー代をさらに18%削減できました。

当然ユースケースによりますが、docker pull 時間が長い場合はI/O性能を上げてやると、起動時間の短縮 & コストカットにつながるかもしれません。

(余談)コストカットはお祭りである

もちろん粛々とコストカットに取り組むことは大切ですが、同時に周りを巻き込んでお祭りムードでやることも大事でした。

みんなで肩組んで、どこがボトルネックなのか?どこを潰せばこれだけ減らせるか?を取り組むメンバー全員で向き合って話し、一致団結することで士気も高まって次々とアイデアが浮かんできました。

コストカットは前に進むというより後ろを振り返るような業務ですが、

  • やったらやった分だけすぐに数字に出る
  • 開発だけではなく、会社全体がハッピーになる

のようにいいこと尽くしなので、むしろやっていて楽しいしお祭りなんです。

ちなみに、「芸術は爆発だ」ならぬ「コストカットはお祭りだ」というお話は、こちらでも語られているのでぜひ👇

youtu.be

まとめ

クラウドサーバーは「インスタンス起動時間 + インスタンスの稼働時間」で課金されるので、この両面でコストカットしてくことが重要です。

今回は推論処理そのものの見直しではなく、アプリケーションレイヤーだけで解決可能な「インスタンス起動時間」にフォーカスしてコストカットを行いました。私個人としては、I/O性能を見直すことで docker pull が早くなるというのはかなり意外な発見でした。

GPU サーバーは優れたパフォーマンスを持つ一方で、運用を誤るとコスト面で大きなデメリットを生むので、今回ご紹介したような小さな工夫を積み重ねて、コストカットの参考にしていただければと思います!