ベスト プラクティス: GPU を使用した Cloud Run での AI 推論

このページでは、AI 推論に GPU と Cloud Run サービスを使用する際のパフォーマンスを最適化するためのベスト プラクティスについて説明します。ここでは、大規模言語モデル(LLM)を中心に説明します。

スケーリング イベントにリアルタイムで応答可能な Cloud Run サービスを作成して、デプロイする必要があります。そのため、次の点に注意する必要があります。

  • 読み込みが高速で、GPU に対応する構造への変換が最小限で済むモデルを使用し、その読み込み方法を最適化します。
  • 同時実行を効率的で最大限に活用できる構成を使用し、コストを抑えながら、1 秒あたりのターゲット リクエストの処理に必要な GPU の数を減らします。

Cloud Run に大規模な ML モデルを読み込む際のおすすめの方法

ML モデルは、コンテナ イメージ内に保存するか、Cloud Storage からの読み込みを最適化することをおすすめします。

ML モデルの保存と読み込みのトレードオフ

比較する項目は次のとおりです。

モデルの位置 デプロイ時間 開発環境 コンテナの起動時間 ストレージ費用
コンテナ イメージ 低速。規模の大きいモデルを含むイメージを Cloud Run にインポートするには、より長い時間が必要になります。 コンテナ イメージを変更すると再デプロイが必要になります。大規模なイメージの場合、再デプロイに時間がかかることがあります。 モデルのサイズによって変わります。非常に大きなモデルの場合、Cloud Storage を使用すると予測可能なパフォーマンスを実現できますが、パフォーマンスは低下します。 Artifact Registry に複数のコピーが存在する可能性があります。
Cloud Storage FUSE ボリューム マウントを使用して読み込まれる Cloud Storage 高速。モデルはコンテナの起動時にダウンロードされます。 設定が難しくなく、Docker イメージの変更も必要ありません。 最適化されたネットワークでは高速。ダウンロードを並列処理しません。 Cloud Storage に 1 つのコピー。
Cloud Storage。転送マネージャーの同時ダウンロードのコードサンプルに示すように、Google Cloud CLI コマンド gcloud storage cp または Cloud Storage API を使用して同時にダウンロードされます。 高速。モデルはコンテナの起動時にダウンロードされます。 イメージに Google Cloud CLI をインストールするか、Cloud Storage API を使用するようにコードを更新する必要があります。設定が少し難しくなります。 最適化されたネットワークでは高速。Google Cloud CLI はモデルファイルを並列でダウンロードするため、FUSE マウントよりも高速です。 Cloud Storage に 1 つのコピー。
インターネット 高速。モデルはコンテナの起動時にダウンロードされます。 通常はシンプルです(多くのフレームワークでは中央リポジトリからモデルがダウンロードされます)。 通常は不安定で予測不能です。
  • フレームワークが初期化中にモデル変換を適用する場合があります(これはビルド時に行う必要があります)。
  • モデルホストとモデルのダウンロード用のライブラリが効率的でない場合があります。
  • インターネットからのダウンロードには、信頼性に関するリスクがあります。ダウンロード ターゲットが停止している場合、サービスが開始されない可能性があります。また、ダウンロードされた基盤となるモデルが変更され、品質が低下する可能性があります。独自の Cloud Storage バケットにホストすることをおすすめします。
モデル ホスティング プロバイダによって異なります。

コンテナ イメージにモデルを保存する

Cloud Run にデプロイされたコンテナ イメージに ML モデルを保存した場合、Cloud Run の組み込みコンテナ イメージ ストリーミングの最適化が利用されます。これにより、ネットワーク最適化を別途行うことなく、ファイルの読み込み時間を最大にすることができます。

ML モデルを含むコンテナのビルドには時間がかかることがあります。Cloud Build を使用している場合は、ビルドを高速化するためにサイズの大きいマシンを使用するように Cloud Build を構成できます。これを行うには、次の手順でビルド構成ファイルを使用して、イメージをビルドします。

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'IMAGE', '.']
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'IMAGE']
images:
- IMAGE
options:
 machineType: 'E2_HIGHCPU_32'
 diskSizeGb: '500'
 

モデルを含むレイヤがイメージ間で異なる場合(ハッシュが異なる場合)は、イメージごとに 1 つのモデルコピーを作成できます。モデルレイヤが各イメージで固有の場合、イメージごとにモデルのコピーが 1 つ存在する可能性があるため、Artifact Registry の費用が増加する可能性があります。

Cloud Storage にモデルを保存する

Cloud Storage から ML モデルを読み込む際に ML モデルの読み込みを最適化するには、Cloud Storage ボリュームのマウントを使用するか、Cloud Storage API またはコマンドラインを直接使用して、下り(外向き)設定が all-traffic に設定されたダイレクト VPCPrivate Service Connect を使用する必要があります。

ビルド、デプロイ、ランタイム、システム設計に関する考慮事項

以降のセクションでは、ビルド、デプロイ、ランタイム、システム設計に関する考慮事項について説明します。

ビルド時

ビルドを計画する際に考慮すべき事項は次のとおりです。

  • 結果の品質に影響することを証明できる場合を除き、4 ビットの量子化モデルを選択して同時実行を最大化します。量子化により、より小さい高速なモデルが生成され、モデルのサービングに必要な GPU メモリの量が削減されます。また、実行時の並列処理を増やすこともできます。理想的には、モデルはターゲット ビット深度に量子化されるのではなく、ターゲット ビット深度でトレーニングする必要があります。
  • コンテナの起動時間を最短にするために、読み込み時間が短いモデル形式(GGUF など)を選択します。これらの形式はターゲット量子化タイプをより正確に反映し、GPU への読み込みの際に必要な変換が少なくなります。セキュリティ上の理由から、pickle 形式のチェックポイントは使用しないでください。
  • ビルド時に LLM キャッシュを作成してウォームアップします。Docker イメージをビルドするときに、ビルドマシンで LLM を開始します。プロンプト キャッシュを有効にして、一般的なプロンプトやサンプル プロンプトをフィードし、実際に使用できるようにキャッシュをウォームアップします。生成された出力を保存して、実行時に読み込みます。
  • ビルド時に生成した独自の推論モデルを保存します。効率の悪いモデルを読み込み、コンテナ起動時に量子化などの変換を適用する場合と比べると、大幅に時間を節約できます。

デプロイ時

  1. Cloud Run でサービスの同時実行を正確に設定します。
  2. 構成に基づいて起動プローブを調整します。

起動プローブは、コンテナが起動し、トラフィックを受け入れる準備ができているかどうかを判断します。起動プローブを構成する際は、次の重要ポイントを考慮してください。

  • 十分な起動時間: モデルを含むコンテナが完全に初期化され、読み込まれるまでに十分な時間を確保します。
  • モデルの準備状況の確認: アプリケーションがリクエストを処理する準備ができた場合にのみ合格するようプローブを構成します。ほとんどのサービング エンジンは、モデルが GPU メモリに読み込まれたときに自動的にこれを実現し、早すぎるリクエストを防ぎます。

Ollama では、モデルが読み込まれる前に TCP ポートを開くことができます。この問題を解決するには:

  • モデルをプリロードする: 起動時にモデルをプリロードする方法については、Ollama のドキュメントをご覧ください。

実行時

  • サポートされているコンテキストの長さを事前に管理します。サポートするコンテキスト ウィンドウが小さいほど、並列で実行可能なクエリの数が増えます。具体的な方法はフレームワークによって異なります。
  • ビルド時に生成した LLM キャッシュを使用します。プロンプトとプレフィックス キャッシュを生成したときに使用した同じフラグを指定します。
  • 作成した保存済みモデルから読み込みます。モデルの読み込み方法の比較については、モデルの保存と読み込みのトレードオフをご覧ください。
  • フレームワークでサポートされている場合は、量子化された Key-Value キャッシュの使用を検討してください。これにより、クエリあたりのメモリ要件を削減し、より多くの並列処理を構成できます。ただし、品質に影響することもあります。
  • モデルの重み、アクティベーション、Key-Value キャッシュに予約する GPU メモリの量を調整します。メモリ不足エラーが発生しない範囲で、できるだけ高い値に設定します。
  • サービスコード内で同時実行を正しく構成します。サービスコードが Cloud Run サービスの同時実行の設定で動作するように構成されていることを確認します。
  • モデル読み込みの並列化の使用など、コンテナの起動パフォーマンスを改善するオプションがフレームワークにあるかどうかを確認します。

システム設計レベル

  • 必要に応じてセマンティック キャッシュを追加します。クエリとレスポンスをすべてキャッシュに保存すると、一般的なクエリの費用を抑えることができます。
  • プリアンブルのばらつきを制御します。プロンプト キャッシュは、プロンプトが順番に格納される場合にのみ有用です。キャッシュは事実上プレフィックス キャッシュです。シーケンス内での挿入や編集は、キャッシュに保存されていないか、一部しか存在しないことを意味します。

自動スケーリングと GPU

Cloud Run は、CPU 使用率やリクエストの同時実行などの要因に基づいて、各リビジョンのインスタンス数を自動的にスケーリングします。ただし、Cloud Run は GPU 使用率に基づいてインスタンス数を自動的にスケーリングしません。

GPU を使用するリビジョンで、リビジョンの CPU 使用率がそれほど高くない場合は、Cloud Run は、リクエストを同時に実行するためにスケールアウトします。リクエストの同時実行を最適にスケーリングするには、次のセクションで説明するように、インスタンスあたりの最大同時リクエスト数に最適な値を設定する必要があります。

インスタンスあたりの最大同時リクエスト数

インスタンスあたりの最大同時リクエスト数の設定では、Cloud Run が単一インスタンスに一度に送信するリクエストの最大数を制御します。各インスタンス内のコードが良好なパフォーマンスで処理可能な最大同時実行数に合わせて、同時実行を調整する必要があります。

最大同時実行数と AI ワークロード

各インスタンスの GPU で AI 推論ワークロードを実行する場合、コードが良好なパフォーマンスで処理可能な最大同時実行数は、特定のフレームワークと実装の詳細によって異なります。最適な最大同時リクエスト数の設定方法に影響する要因は次のとおりです。

  • GPU に読み込まれるモデル インスタンスの数
  • モデルごとの並列クエリの数
  • バッチ処理の使用
  • 特定のバッチ構成パラメータ
  • GPU 以外の作業量

最大同時リクエスト数が高すぎると、リクエストがインスタンス内で GPU へのアクセスを待機し、レイテンシが増加する可能性があります。最大同時リクエスト数が低すぎると、GPU が十分に利用されず、Cloud Run で必要以上のインスタンスがスケールアウトされる可能性があります。

AI ワークロードの最大同時リクエストを構成するための経験則は次のとおりです。

(Number of model instances * parallel queries per model) + (number of model instances * ideal batch size)

インスタンスが 3 モデル インスタンスを GPU に読み込み、各モデル インスタンスが 4 個の並列クエリを処理できるとします。各モデル インスタンスが処理できる並列クエリの数は 4 であるため、バッチサイズにもこの値を使用するのが理想的です。経験則の計算式 (3 × 4) + (3 × 4) により、最大同時リクエスト数を 24 に設定します。

この式はあくまで目安です。最適な最大同時リクエスト数は、実装の詳細によって異なります。実際に最適なパフォーマンスを実現するには、さまざまな最大同時リクエスト数の設定でサービスの負荷テストを行い、どのオプションが最適であるかを評価することをおすすめします。

スループット、レイテンシ、費用のトレードオフ

最大同時リクエスト数がスループット、レイテンシ、コストに与える影響については、スループット、レイテンシ、コストのトレードオフをご覧ください。GPU を使用するすべての Cloud Run サービスには、常に CPU が割り当てられます。