Amazon SageMaker リアルタイム推論エンドポイントの負荷テストのベストプラクティス

Amazon SageMaker リアルタイム推論エンドポイントの負荷テストのベストプラクティス

ソースノード: 1889926

アマゾンセージメーカー フルマネージドの機械学習 (ML) サービスです。 SageMaker を使用すると、データ サイエンティストと開発者は ML モデルを迅速かつ簡単に構築してトレーニングし、本番環境でホストされている環境に直接デプロイできます。 統合された Jupyter オーサリング ノートブック インスタンスを提供し、探索と分析のためにデータ ソースに簡単にアクセスできるため、サーバーを管理する必要がありません。 また、共通の MLアルゴリズム 分散環境で非常に大きなデータに対して効率的に実行するように最適化されています。

SageMaker リアルタイム推論は、リアルタイム、インタラクティブ、低レイテンシーの要件を持つワークロードに最適です。 SageMaker リアルタイム推論を使用すると、一定量のコンピューティングとメモリを備えた特定のインスタンス タイプによってサポートされる REST エンドポイントをデプロイできます。 SageMaker リアルタイム エンドポイントのデプロイは、多くのお客様にとって本番環境へのパスの最初のステップにすぎません。 エンドポイントのパフォーマンスを最大化して、レイテンシ要件を遵守しながら、XNUMX 秒あたりのトランザクション数 (TPS) を達成できるようにしたいと考えています。 推論のパフォーマンス最適化の大部分は、適切なインスタンス タイプを選択し、エンドポイントをサポートするようにカウントすることです。

この投稿では、SageMaker エンドポイントを負荷テストして、インスタンスの数とサイズに適した構成を見つけるためのベスト プラクティスについて説明します。 これは、レイテンシーと TPS の要件を満たすためにプロビジョニングされたインスタンスの最小要件を理解するのに役立ちます。 そこから、SageMaker エンドポイントのメトリクスとパフォーマンスを追跡して理解する方法について詳しく説明します。 アマゾンクラウドウォッチ メトリック

最初に、単一のインスタンスでモデルのパフォーマンスをベンチマークし、許容可能なレイテンシ要件に従って処理できる TPS を特定します。 次に、調査結果を推定して、本番トラフィックを処理するために必要なインスタンスの数を決定します。 最後に、本番レベルのトラフィックをシミュレートし、リアルタイム SageMaker エンドポイントの負荷テストをセットアップして、エンドポイントが本番レベルの負荷を処理できることを確認します。 この例のコード セット全体は、次の場所にあります。 GitHubリポジトリ.

ソリューションの概要

この投稿では、事前トレーニング済みの ハグフェイス DitilBERTモデル フェイスハブを抱き締める. このモデルは多くのタスクを実行できますが、感情分析とテキスト分類専用のペイロードを送信します。 このサンプル ペイロードを使用して、1000 TPS の達成を目指します。

リアルタイム エンドポイントをデプロイする

この投稿は、モデルのデプロイ方法に精通していることを前提としています。 参照する エンドポイントを作成してモデルをデプロイする エンドポイントのホスティングの背後にある内部構造を理解する。 今のところ、Hugging Face Hub でこのモデルをすばやくポイントし、次のコード スニペットを使用してリアルタイム エンドポイントをデプロイできます。

# Hub Model configuration. https://huggingface.co/models
hub = { 'HF_MODEL_ID':'distilbert-base-uncased', 'HF_TASK':'text-classification'
} # create Hugging Face Model Class
huggingface_model = HuggingFaceModel(
transformers_version='4.17.0',
pytorch_version='1.10.2',
py_version='py38',
env=hub,
role=role,
) # deploy model to SageMaker Inference
predictor = huggingface_model.deploy(
initial_instance_count=1, # number of instances
instance_type='ml.m5.12xlarge' # ec2 instance type
)

負荷テストに使用するサンプル ペイロードを使用して、エンドポイントを簡単にテストしてみましょう。


import boto3
import json
client = boto3.client('sagemaker-runtime')
content_type = "application/json"
request_body = {'inputs': "I am super happy right now."}
data = json.loads(json.dumps(request_body))
payload = json.dumps(data)
response = client.invoke_endpoint(
EndpointName=predictor.endpoint_name,
ContentType=content_type,
Body=payload)
result = response['Body'].read()
result

単一のを使用してエンドポイントをサポートしていることに注意してください アマゾン エラスティック コンピューティング クラウド (Amazon EC2) タイプ ml.m5.12xlarge のインスタンス。48 個の vCPU と 192 GiB のメモリが含まれています。 vCPU の数は、インスタンスが処理できる同時実行数の適切な指標です。 一般に、さまざまなインスタンス タイプをテストして、リソースが適切に使用されているインスタンスがあることを確認することをお勧めします。 SageMaker インスタンスの完全なリストと、それに対応するリアルタイム推論の計算能力については、次を参照してください。 Amazon SageMakerの価格.

追跡する指標

負荷テストに入る前に、SageMaker エンドポイントのパフォーマンスの内訳を理解するために追跡するメトリクスを理解することが不可欠です。 CloudWatch は、エンドポイントのパフォーマンスを説明するさまざまなメトリクスを理解するために SageMaker が使用する主要なログ記録ツールです。 CloudWatch ログを利用して、エンドポイントの呼び出しをデバッグできます。 推論コードに含まれるすべてのロギングおよび印刷ステートメントがここに取り込まれます。 詳細については、次を参照してください。 Amazon CloudWatch の仕組み.

CloudWatch が SageMaker をカバーする XNUMX つの異なるタイプのメトリクスがあります: インスタンスレベルと呼び出しメトリクスです。

インスタンス レベルのメトリクス

考慮すべき最初のパラメーター セットは、インスタンス レベルのメトリックです。 CPUUtilization & MemoryUtilization (GPU ベースのインスタンスの場合、 GPUUtilization)。 ために CPUUtilization、CloudWatch で最初に 100% を超えるパーセンテージが表示される場合があります。 意識することが大事 CPUUtilization、すべての CPU コアの合計が表示されています。 たとえば、エンドポイントの背後にあるインスタンスに 4 つの vCPU が含まれている場合、これは使用率の範囲が最大 400% であることを意味します。 MemoryUtilization一方、0 ~ 100% の範囲です。

具体的には、 CPUUtilization 十分なハードウェアがあるか、過剰なハードウェアがあるかをより深く理解するために。 使用率の低いインスタンス (30% 未満) がある場合は、インスタンス タイプを縮小できる可能性があります。 逆に、使用率が約 80 ~ 90% の場合は、コンピューティング/メモリが大きいインスタンスを選択すると効果的です。 テストから、ハードウェアの約 60 ~ 70% の使用率をお勧めします。

呼び出しメトリック

名前が示すように、呼び出しメトリクスは、エンドポイントへの呼び出しのエンドツーエンドのレイテンシーを追跡できる場所です。 呼び出しメトリクスを利用して、エラー数と、エンドポイントで発生している可能性のあるエラーの種類 (5xx、4xx など) を取得できます。 さらに重要なことは、エンドポイント呼び出しのレイテンシーの内訳を理解できることです。 これの多くは ModelLatency & OverheadLatency 次の図に示すように、メトリック。

レイテンシ

  ModelLatency メトリクスは、SageMaker エンドポイントの背後にあるモデル コンテナ内で推論にかかる時間をキャプチャします。 モデル コンテナーには、推論のために渡したカスタム推論コードまたはスクリプトも含まれていることに注意してください。 この単位は、呼び出しメトリクスとしてマイクロ秒単位でキャプチャされます。通常、CloudWatch (p99、p90 など) 全体でパーセンタイルをグラフ化して、目標レイテンシーを満たしているかどうかを確認できます。 次のようないくつかの要因がモデルとコンテナーのレイテンシーに影響を与える可能性があることに注意してください。

  • カスタム推論スクリプト – 独自のコンテナーを実装したか、カスタム推論ハンドラーを備えた SageMaker ベースのコンテナーを使用したかに関係なく、スクリプトをプロファイリングして、レイテンシーに特に多くの時間を追加している操作をキャッチすることをお勧めします。
  • 通信プロトコル – モデル コンテナー内のモデル サーバーへの REST 接続と gRPC 接続を検討します。
  • モデル フレームワークの最適化 – これはフレームワーク固有です。たとえば、 TensorFlow、TF Serving 固有の調整可能な環境変数が多数あります。 使用しているコンテナーを確認し、スクリプト内またはコンテナーに挿入する環境変数として追加できるフレームワーク固有の最適化があるかどうかを確認してください。

OverheadLatency SageMaker がリクエストを受信して​​からクライアントにレスポンスを返すまでの時間から、モデルのレイテンシを差し引いて測定されます。 この部分は大部分が制御不能であり、SageMaker のオーバーヘッドにかかる時間に該当します。

全体としてのエンドツーエンドのレイテンシーは、さまざまな要因に依存し、必ずしも合計ではありません。 ModelLatency さらに OverheadLatency. たとえば、クライアントが InvokeEndpoint インターネット経由の API 呼び出し。クライアントの観点からすると、エンドツーエンドのレイテンシはインターネット + ModelLatency + OverheadLatency. そのため、エンドポイント自体を正確にベンチマークするためにエンドポイントの負荷テストを行う場合は、エンドポイント メトリック (ModelLatency, OverheadLatency, InvocationsPerInstance) SageMaker エンドポイントを正確にベンチマークします。 エンドツーエンドのレイテンシに関連する問題は、個別に分離できます。

エンドツーエンドのレイテンシーについて考慮すべきいくつかの質問:

  • エンドポイントを呼び出しているクライアントはどこですか?
  • クライアントと SageMaker ランタイムの間に中間層はありますか?

自動スケーリング

この投稿では特に Auto Scaling については触れていませんが、ワークロードに基づいて正しい数のインスタンスをプロビジョニングするためには、Auto Scaling は重要な考慮事項です。 トラフィック パターンに応じて、 自動スケーリング ポリシー SageMaker エンドポイントに。 次のようなさまざまなスケーリング オプションがあります。 TargetTrackingScaling, SimpleScaling, StepScaling. これにより、エンドポイントはトラフィック パターンに基づいて自動的にスケールインおよびスケールアウトできます。

一般的なオプションはターゲット トラッキングです。ここでは、定義した CloudWatch メトリクスまたはカスタム メトリクスを指定し、それに基づいてスケールアウトできます。 自動スケーリングの頻繁な利用は、 InvocationsPerInstance メトリック。 特定の TPS でボトルネックを特定した後、多くの場合、それをメトリックとして使用して、より多くのインスタンスにスケールアウトし、トラフィックのピーク負荷を処理できるようにすることができます。 自動スケーリング SageMaker エンドポイントの詳細な内訳を取得するには、以下を参照してください。 Amazon SageMaker で自動スケーリング推論エンドポイントを設定する.

負荷テスト

Locust を使用して大規模な負荷テストを行う方法を示していますが、エンドポイントの背後にあるインスタンスのサイズを適切にしようとしている場合は、 SageMaker推論レコメンダー より効率的なオプションです。 サードパーティの負荷テスト ツールを使用すると、さまざまなインスタンスにエンドポイントを手動でデプロイする必要があります。 Inference Recommender を使用すると、ロード テスト対象のインスタンス タイプの配列を渡すだけで、SageMaker が起動します。 jobs これらのインスタンスごとに。

イナゴ

この例では、 イナゴは、Python を使用して実装できるオープンソースの負荷テスト ツールです。 Locust は、他の多くのオープンソースの負荷テスト ツールに似ていますが、いくつかの特定の利点があります。

  • セットアップが簡単 – この投稿で説明するように、特定のエンドポイントとペイロード用に簡単にリファクタリングできるシンプルな Python スクリプトを渡します。
  • 分散型でスケーラブル – イナゴはイベントベースで、 げんき フードの下。 これは、高度に同時実行されるワークロードをテストし、何千もの同時ユーザーをシミュレートするのに非常に役立ちます。 Locust を実行する単一のプロセスで高い TPS を達成できますが、 分布荷重生成 この投稿で説明するように、複数のプロセスとクライアント マシンにスケールアウトできる機能です。
  • イナゴのメトリクスと UI – Locust は、エンドツーエンドのレイテンシも測定基準として捉えます。 これは、CloudWatch メトリクスを補足して、テストの全体像を描くのに役立ちます。 これはすべて、同時ユーザー、ワーカーなどを追跡できる Locust UI でキャプチャされます。

Locust をさらに理解するには、 ドキュメント.

アマゾン EC2 セットアップ

互換性のある環境であれば、Locust をセットアップできます。 この投稿では、EC2 インスタンスをセットアップし、そこに Locust をインストールしてテストを実施します。 c5.18xlarge EC2 インスタンスを使用します。 クライアント側の計算能力も考慮する必要があります。 クライアント側でコンピューティング能力が不足している場合、これはしばしばキャプチャされず、SageMaker エンドポイント エラーと間違われます。 テストする負荷を処理できる十分な計算能力のある場所にクライアントを配置することが重要です。 EC2 インスタンスでは、Ubuntu Deep Learning AMI を使用していますが、マシンに Locust を適切にセットアップできる限り、任意の AMI を利用できます。 EC2 インスタンスを起動して接続する方法を理解するには、チュートリアルを参照してください。 Amazon EC2 Linux インスタンスの使用を開始する.

Locust UI はポート 8089 経由でアクセスできます。これを開くには、EC2 インスタンスのインバウンド セキュリティ グループ ルールを調整します。 また、ポート 22 を開き、EC2 インスタンスに SSH で接続できるようにします。 EC2 インスタンスにアクセスしている特定の IP アドレスにソースのスコープを絞ることを検討してください。

セキュリティグループ

EC2 インスタンスに接続したら、Python 仮想環境をセットアップし、CLI を介してオープンソースの Locust API をインストールします。

virtualenv venv #venv is the virtual environment name, you can change as you desire
source venv/bin/activate #activate virtual environment
pip install locust

これで、エンドポイントの負荷テストのために Locust を使用する準備が整いました。

イナゴ試験

すべての Locust 負荷テストは、 イナゴファイル あなたが提供すること。 この Locust ファイルは、負荷テストのタスクを定義します。 ここで Boto3 を定義します invoke_endpoint API 呼び出し。 次のコードを参照してください。

config = Config(
retries = { 'max_attempts': 0, 'mode': 'standard'
}
) self.sagemaker_client = boto3.client('sagemaker-runtime',config=config)
self.endpoint_name = host.split('/')[-1]
self.region = region
self.content_type = content_type
self.payload = payload

上記のコードでは、特定のモデル呼び出しに合わせて呼び出しエンドポイント呼び出しパラメーターを調整します。 私たちは、 InvokeEndpoint Locust ファイルで次のコードを使用する API。 これが負荷テストの実行ポイントです。 使用している Locust ファイルは locust_script.py.

def send(self): request_meta = { "request_type": "InvokeEndpoint", "name": "SageMaker", "start_time": time.time(), "response_length": 0, "response": None, "context": {}, "exception": None,
}
start_perf_counter = time.perf_counter() try:
response = self.sagemaker_client.invoke_endpoint(
EndpointName=self.endpoint_name,
Body=self.payload,
ContentType=self.content_type
)
response_body = response["Body"].read()

Locust スクリプトの準備ができたので、分散型 Locust テストを実行して単一インスタンスのストレス テストを実行し、インスタンスが処理できるトラフィック量を調べます。

Locust 分散モードは、単一プロセスの Locust テストよりも少しニュアンスが異なります。 分散モードでは、XNUMX つのプライマリ ワーカーと複数のワーカーがあります。 プライマリ ワーカーは、リクエストを送信している同時ユーザーを生成および制御する方法をワーカーに指示します。 私たちの中で 配布された.sh スクリプトを実行すると、デフォルトで 240 人のユーザーが 60 人のワーカーに分散されることがわかります。 注意してください --headless Locust CLI のフラグは、Locust の UI 機能を削除します。

#replace with your endpoint name in format https://<<endpoint-name>>
export ENDPOINT_NAME=https://$1 export REGION=us-east-1
export CONTENT_TYPE=application/json
export PAYLOAD='{"inputs": "I am super happy right now."}'
export USERS=240
export WORKERS=60
export RUN_TIME=1m
export LOCUST_UI=false # Use Locust UI .
.
. locust -f $SCRIPT -H $ENDPOINT_NAME --master --expect-workers $WORKERS -u $USERS -t $RUN_TIME --csv results &
.
.
. for (( c=1; c<=$WORKERS; c++ ))
do
locust -f $SCRIPT -H $ENDPOINT_NAME --worker --master-host=localhost &
done

./distributed.sh huggingface-pytorch-inference-2022-10-04-02-46-44-677 #to execute Distributed Locust test

最初に、エンドポイントをサポートする単一のインスタンスで分散テストを実行します。 ここでの考え方は、XNUMX つのインスタンスを完全に最大化して、レイテンシ要件内に収まりながら目標 TPS を達成するために必要なインスタンス数を把握したいというものです。 UI にアクセスする場合は、 Locust_UI 環境変数を True に設定し、EC2 インスタンスのパブリック IP を取得して、ポート 8089 を URL にマップします。

次のスクリーンショットは、CloudWatchメトリクスを示しています。

CloudWatch メトリクス

最終的に、最初は 200 の TPS を達成しましたが、次のスクリーンショットに示すように、EC5 クライアント側のログで 2xx エラーに気付き始めました。

これは、インスタンス レベルのメトリクスを見て確認することもできます。具体的には CPUUtilization.

CloudWatch メトリクスここで気づきます CPUUtilization ほぼ 4,800% です。 ml.m5.12x.large インスタンスには 48 個の vCPU (48 * 100 = 4800~) があります。 これはインスタンス全体を飽和させており、5xx エラーの説明にも役立ちます。 また、 ModelLatency.

単一のインスタンスが倒され、観測している 200 TPS を超える負荷を維持するためのコンピューティング能力がないように見えます。 目標 TPS は 1000 なので、インスタンス数を 5 に増やしてみましょう。特定の時点の後に 200 TPS でエラーが観察されたため、本番環境ではこれをさらに増やす必要があるかもしれません。

エンドポイント設定

Locust UI と CloudWatch ログの両方で、TPS がほぼ 1000 で、XNUMX つのインスタンスがエンドポイントをサポートしていることがわかります。

イナゴ

CloudWatch メトリクスこのハードウェア設定でもエラーが発生し始めた場合は、必ず監視してください CPUUtilization エンドポイント ホスティングの背後にある全体像を理解する。 スケールアップまたはスケールダウンが必要かどうかを判断するには、ハードウェアの使用率を把握することが重要です。 コンテナ レベルの問題によって 5xx エラーが発生することがありますが、 CPUUtilization が低い場合、それはハードウェアではなく、コンテナーまたはモデル レベルでこれらの問題を引き起こしている可能性があることを示しています (たとえば、ワーカー数の適切な環境変数が設定されていないなど)。 一方、インスタンスが完全に飽和状態になっていることに気付いた場合は、現在のインスタンス フリートを増やすか、より小さなフリートでより大きなインスタンスを試す必要があることを示しています。

5 TPS を処理するためにインスタンス数を 100 に増やしましたが、 ModelLatency メトリックはまだ高いです。 これは、インスタンスが飽和しているためです。 一般に、インスタンスのリソースを 60 ~ 70% 使用することを目指すことをお勧めします。

クリーンアップ

負荷テストの後、SageMaker コンソールまたは エンドポイントの削除 Boto3 API 呼び出し。 さらに、EC2 インスタンスまたは必要なクライアント設定を停止して、追加料金が発生しないようにしてください。

まとめ

この投稿では、SageMaker リアルタイム エンドポイントを負荷テストする方法について説明しました。 また、パフォーマンスの内訳を理解するためにエンドポイントの負荷テストを行う際に評価すべき指標についても説明しました。 必ずチェックしてください SageMaker推論レコメンダー インスタンスの適切なサイジングとパフォーマンスの最適化手法について理解を深めるため。


著者について

マーク・カープ SageMaker サービスチームの ML アーキテクトです。 彼は、顧客が大規模な ML ワークロードを設計、展開、管理するのを支援することに重点を置いています。 余暇には、旅行や新しい場所の探索を楽しんでいます。

ラム・ベギラージュ SageMaker サービスチームの ML アーキテクトです。 彼は、お客様が Amazon SageMaker で AI/ML ソリューションを構築および最適化するのを支援することに重点を置いています。 余暇には、旅行と執筆が大好きです。

タイムスタンプ:

より多くの AWS機械学習