ベンチマーク・クライアント (Python)#

はじめに

ここで紹介されているベンチマーク・クライアントは Python 3 で記述されています。ベンチマーク・クライアントは、TFServing API および KServe API を使用してモデルサーバーと通信します。ベンチマーク・クライアントを Docker コンテナとして使用することを推奨します。送信前に、クライアントはサーバーからメタデータをダウンロードします。このメタデータには、利用可能なモデル、そのバージョン、および受け入れられた入力および出力形状のリストが含まれています。次に、サービスによって提供されるモデルに一致する形状を持つランダムデータを含むテンソルを生成します。データセットの長さとワークロード期間の両方を個別に指定できます。作成された合成データは、ワークロードの長さが満たされるまでデータセットを反復するループで提供されます。クライアントの主な役割はパフォーマンスの測定であるため、スループットやレイテンシーに関係のないものは無視されます。それらのアクティビティーは、クライアント側で測定されたパフォーマンス・メトリックに影響を及ぼす可能性があるため、クライアントは受信した応答を検証せず、精度も推定しません。

標準データ形式に加えて、クライアントはステートフル・モデル (連続する推論要求間の依存関係を認識する) および選択したファイル形式 (PNG および JPEG) のバイナリー入力もサポートします。

urandom generated input image xrandom generated input image

クライアントは複数の精度をサポートします: FP16FP32FP64INT8INT16INT32INT64UINT8UINT16UINT32UINT64。証明書ありなしの両方のチャネルタイプがサポートされています。シークレット/証明書は別のボリュームにマウントする必要があり、そのパスをコマンドラインで指定します。セキュアな接続は、ビルトインの Nginx 逆プロキシー・ロード・バランサーを使用してパブリックソースから構築できる Nginx OVMS プラグインのベンチマークに使用できます。

単一の Docker コンテナは、異なるプロセスで多数の並列クライアントを実行できます。測定されたメトリック (特にスループット、レイテンシー、カウンター) はすべてのクライアント・プロセスから収集され、それを組み合わせて並列ワークロード全体の JSON 形式/構文で出力できます。Docker コンテナがデーモンモードで実行されている場合、docker logs コマンドで最終的なログを表示できます。結果は Mongo データベースにエクスポートすることもできます。これには、適切な識別メタデータをコマンドラインで指定する必要があります。

2.7 アップデート以降、ベンチマーク・クライアントの測定オプションが導入されました。ビルトイン文字列データ入力による言語モデルのテストと、OVMS での MediaPipe グラフのテストがサポートされます。それぞれ入力データのメソッドを指定する必要があります。データメソッド -d string はサンプル・テキスト・データを作成します。

MediaPipe と統合された OVMS のベンチマークは、gRPC プロトコル経由で KServe API に対して可能です。この場合、numpy 配列で構成される事前に準備された numpy ファイルをクライアントに供給する必要もあります。

shape パラメーターを使用して動的モデルをテストするオプションもあります。

最後の 2 つの使用例については、このドキュメントでさらに説明します。

ベンチマーク・クライアント Docker イメージのビルド#

Docker イメージをビルドし、benchmark_client としてタグ付けするには、次のコマンドを実行します:

git clone https://github.com/openvinotoolkit/model_server.git 
cd model_server/demos/benchmark/python 
docker build .-t benchmark_client

OVMS のデプロイ#

モデルをダウンロードし、適切なディレクトリー・ツリーを作成します。例えば、インテルの Open Model Zoo の resnet50 バイナリーモデルでは次のようになります:

mkdir -p workspace/resnet50-binary-0001/1 
cd workspace/resnet50-binary-0001/1 
wget https://storage.openvinotoolkit.org/repositories/open_model_zoo/2022.1/models_bin/2/resnet50-binary-0001/FP32-INT1/resnet50-binary-0001.xml 
wget https://storage.openvinotoolkit.org/repositories/open_model_zoo/2022.1/models_bin/2/resnet50-binary-0001/FP32-INT1/resnet50-binary-0001.bin 
cd ../../..

モデルのディレクトリーは次のようになります:

workspace
 └── resnet50-binary-0001 
     └── 1 
         ├── resnet50-binary-0001.bin 
         └── resnet50-binary-0001.xml

ベンチマーク・クライアントをビルドして実行する前に、OVMS を起動します (詳細な展開オプションについてはドキュメントを参照してください):

docker run -u $(id -u) -p 9000:9000 -p 8000:8000 -d -v ${PWD}/workspace:/workspace openvino/model_server --model_path \ 
    /workspace/resnet50-binary-0001 --model_name resnet50-binary-0001 --port 9000 --rest_port 8000

選択されたコマンド#

利用可能なオプションを確認するには、-h--help スイッチを使用します:

  docker run benchmark_client --help 

Client 2.7 
NO_PROXY=localhost no_proxy=localhost python3 /ovms_benchmark_client/main.py --help 
usage: main.py [-h] [-i ID] [-c CONCURRENCY] [-a SERVER_ADDRESS] 
               [-p GRPC_PORT] [-r REST_PORT] [-l] [-b [BS ...]] 
               [-s [SHAPE ...]][-d [DATA ...]] [-j] [-m MODEL_NAME] 
               [-k DATASET_LENGTH] [-v MODEL_VERSION] [-n STEPS_NUMBER] 
               [-t DURATION] [-u WARMUP] [-w WINDOW] [-e ERROR_LIMIT] 
               [-x ERROR_EXPOSITION] [--max_throughput MAX_THROUGHPUT] 
               [--max_value MAX_VALUE] [--min_value MIN_VALUE] [--xrand XRAND] 
               [--dump_png] [--step_timeout STEP_TIMEOUT] 
               [--metadata_timeout METADATA_TIMEOUT] [-Y DB_ENDPOINT] 
               [-y [DB_METADATA ...]][--print_all] [-ps] [--print_time] 
               [--report_warmup] [--certs_dir CERTS_DIR] [-q STATEFUL_LENGTH] 
               [--stateful_id STATEFUL_ID] [--stateful_hop STATEFUL_HOP] 
               [--sync_interval SYNC_INTERVAL] 
               [--quantile_list [QUANTILE_LIST ...]] 
               [--hist_factor HIST_FACTOR] [--hist_base HIST_BASE] 
               [--internal_version] [--unbuffered] [--api {TFS,KFS,REST}] 

This is benchmarking client which uses TFS/KFS API to communicate with OVMS/TFS/KFS-based-services.

バージョンは、--internal_version スイッチで確認できます:

 docker run benchmark_client --internal_version 

Client 2.7 
NO_PROXY=localhost no_proxy=localhost python3 /ovms_benchmark_client/main.py --internal_version 2.7

クライアントは、提供されたモデルのメタデータをダウンロードできます。いずれのモデルとバージョンが提供されているか、またそのステータスが不明な場合は、--list_models スイッチでこの情報を一覧表示できます (短縮形式の -l も使用できます):

docker run --network host benchmark_client -a localhost -r 8000 --list_models 

Client 2.7 
NO_PROXY=localhost no_proxy=localhost python3 /ovms_benchmark_client/main.py -a localhost -r 8000 --list_models 
          XW worker: Finished execution.If you want to run inference remove --list_models. 
          XI worker: try to send request to endpoint: http://localhost:8000/v1/config 
          XI worker: received status code is 200. 
          XI worker: found models and their status: 
          XI worker: model: resnet50-binary-0001, version: 1 - AVAILABLE

サンプル・ベンチマーク#

名前、モデル形状、および入力と出力のデータタイプに関する情報も、同じリストスイッチを使用し、コマンドラインに -m <model-name>-v <model-version> を追加することで、利用可能なすべてのモデルにダウンロードできます。オプション -i は、アプリケーション・インスタンスの名前を持つプリフィクスを標準出力に追加するためにのみ使用されます。次に例を示します:

docker run --network host benchmark_client -a localhost -r 8000 -l -m resnet50-binary-0001 -p 9000 -i id 

Client 2.7 
NO_PROXY=localhost no_proxy=localhost python3 /ovms_benchmark_client/main.py -a localhost -r 8000 -l -m resnet50-binary-0001 -p 9000 -i id 
          XW id: Finished execution.If you want to run inference remove --list_models. 
          XI worker: try to send request to endpoint: http://localhost:8000/v1/config 
          XI worker: received status code is 200. 
          XI id: found models and their status: 
          XI id: model: resnet50-binary-0001, version: 1 - AVAILABLE 
          XI id: request for metadata of model resnet50-binary-0001... 
          XI id: Metadata for model resnet50-binary-0001 is downloaded... 
          XI id: set version of model resnet50-binary-0001: 1 
          XI id: inputs: 
          XI id: 0: 
          XI id:  name: 0 
          XI id:  dtype: DT_FLOAT 
          XI id:  tensorShape: {'dim': [{'size': '1'}, {'size': '3'}, {'size': '224'}, {'size': '224'}]} 
          XI id: outputs: 
          XI id:  1463: 
          XI id:   name: 1463 
          XI id:   dtype: DT_FLOAT 
          XI id:   tensorShape: {'dim': [{'size': '1'}, {'size': '1000'}]}

指定したモデル名が、--list_models パラメーターを使用するときに表示されるモデル名と同じであることを確認してください。モデルバージョンは必須ではありませんが、特定のモデル名に対して複数のバージョンが利用可能な場合は追加できます。

導入されたベンチマーク・クライアントは、単一のワークロード内で複数の異なるバッチサイズでの要求の生成をサポートします。このパラメーターを指定するには、スイッチ -b--bs を使用できます。

ワークロードは、その長さが反復番号 -n--steps_number または期間の長さ -t--duration で指定される場合にのみ生成できます。ウォームアップ時間ウィンドウに関するレポートも表示するには、--report_warmup スイッチを使用します。8 つの要求の例は次のように生成されます (標準出力にメトリックを表示するには --print_all を忘れずに追加してください):

docker run --network host benchmark_client -a localhost -r 8000 -m resnet50-binary-0001 -p 9000 -n 8 --report_warmup --print_all 

Client 2.7 
NO_PROXY=localhost no_proxy=localhost python3 /ovms_benchmark_client/main.py -a localhost -r 8000 -m resnet50-binary-0001 -p 9000 -n 8 --report_warmup --print_all 
          XI worker: request for metadata of model resnet50-binary-0001... 
          XI worker: Metadata for model resnet50-binary-0001 is downloaded... 
          XI worker: set version of model resnet50-binary-0001: 1 
          XI worker: inputs: 
          XI worker:  0: 
          XI worker:   name: 0 
          XI worker:   dtype: DT_FLOAT 
          XI worker:   tensorShape: {'dim': [{'size': '1'}, {'size': '3'}, {'size': '224'}, {'size': '224'}]} 
          XI worker: outputs: 
          XI worker:  1463: 
          XI worker:   name: 1463 
          XI worker:   dtype: DT_FLOAT 
          XI worker:   tensorShape: {'dim': [{'size': '1'}, {'size': '1000'}]} 
          XI worker: new random range: 0.0, 255.0 
          XI worker: batchsize sequence: [1] 
          XI worker: dataset length (0): 1 
          XI worker: --> dim: 1 
          XI worker: --> dim: 3 
          XI worker: --> dim: 224 
          XI worker: --> dim: 224 
          XI worker: Generated data shape: (1, 3, 224, 224) 
          XI worker: start workload... 
          XI worker: stop warmup: 9408188.83686497 
          XI worker: stop window: inf 
          XI worker: Workload started! 
          XI worker: Warmup normally stopped: 9408188.848778868 
          XI worker: Window normally start: 9408188.848811286 
          XI worker: Window stopped: 9408188.893217305 
          XI worker: total_duration: 0.0563836432993412 
          XI worker: total_batches: 8 
          XI worker: total_frames: 8 
          XI worker: start_timestamp: 9408188.836864596 
          XI worker: stop_timestamp: 9408188.89324824 
          XI worker: pass_batches: 8 
          XI worker: fail_batches: 0 
          XI worker: pass_frames: 8 
          XI worker: fail_frames: 0 
          XI worker: first_latency: 0.011858431622385979 
          XI worker: pass_max_latency: 0.011858431622385979 
          XI worker: fail_max_latency: 0.0 
          XI worker: brutto_batch_rate: 141.88512007867135 
          XI worker: brutto_frame_rate: 141.88512007867135 
          XI worker: netto_batch_rate: 142.7839056346449 
          XI worker: netto_frame_rate: 142.7839056346449 
          XI worker: frame_passrate: 1.0 
          XI worker: batch_passrate: 1.0 
          XI worker: mean_latency: 0.00700359046459198 
          XI worker: mean_latency2: 5.376289226632219e-05 
          XI worker: stdev_latency: 0.002170855331568294 
          XI worker: cv_latency: 0.309963202809113 
          XI worker: pass_mean_latency: 0.00700359046459198 
          XI worker: pass_mean_latency2: 5.376289226632219e-05 
          XI worker: pass_stdev_latency: 0.002170855331568294 
          XI worker: pass_cv_latency: 0.309963202809113 
          XI worker: fail_mean_latency: 0.0 
          XI worker: fail_mean_latency2: 0.0 
          XI worker: fail_stdev_latency: 0.0 
          XI worker: fail_cv_latency: 0.0 
          XI worker: window_total_duration: 0.044406019151210785 
          XI worker: window_total_batches: 8 
          XI worker: window_total_frames: 8 
          XI worker: window_start_timestamp: 9408188.848811286 
          XI worker: window_stop_timestamp: 9408188.893217305 
          XI worker: window_pass_batches: 8 
          XI worker: window_fail_batches: 0 
          XI worker: window_pass_frames: 8 
          XI worker: window_fail_frames: 0 
          XI worker: window_first_latency: 0.011858431622385979 
          XI worker: window_pass_max_latency: 0.011858431622385979 
          XI worker: window_fail_max_latency: 0.0 
          XI worker: window_brutto_batch_rate: 180.15575710037206 
          XI worker: window_brutto_frame_rate: 180.15575710037206 
          XI worker: window_netto_batch_rate: 142.7839056346449 
          XI worker: window_netto_frame_rate: 142.7839056346449 
          XI worker: window_frame_passrate: 1.0 
          XI worker: window_batch_passrate: 1.0 
          XI worker: window_mean_latency: 0.00700359046459198 
          XI worker: window_mean_latency2: 5.376289226632219e-05 
          XI worker: window_stdev_latency: 0.002170855331568294 
          XI worker: window_cv_latency: 0.309963202809113 
          XI worker: window_pass_mean_latency: 0.00700359046459198 
          XI worker: window_pass_mean_latency2: 5.376289226632219e-05 
          XI worker: window_pass_stdev_latency: 0.002170855331568294 
          XI worker: window_pass_cv_latency: 0.309963202809113 
          XI worker: window_fail_mean_latency: 0.0 
          XI worker: window_fail_mean_latency2: 0.0 
          XI worker: window_fail_stdev_latency: 0.0 
          XI worker: window_fail_cv_latency: 0.0 
          XI worker: window_hist_latency_1: 1 
          XI worker: window_hist_latency_0: 7 
          XI worker: warmup_total_duration: 0.011916300281882286 
          XI worker: warmup_total_batches: 0 
          XI worker: warmup_total_frames: 0 
          XI worker: warmup_start_timestamp: 9408188.836862568 
          XI worker: warmup_stop_timestamp: 9408188.848778868 
          XI worker: warmup_pass_batches: 0 
          XI worker: warmup_fail_batches: 0 
          XI worker: warmup_pass_frames: 0 
          XI worker: warmup_fail_frames: 0 
          XI worker: warmup_first_latency: inf 
          XI worker: warmup_pass_max_latency: 0.0 
          XI worker: warmup_fail_max_latency: 0.0 
          XI worker: warmup_brutto_batch_rate: 0.0 
          XI worker: warmup_brutto_frame_rate: 0.0 
          XI worker: warmup_netto_batch_rate: 0.0 
          XI worker: warmup_netto_frame_rate: 0.0 
          XI worker: warmup_frame_passrate: 0.0 
          XI worker: warmup_batch_passrate: 0.0 
          XI worker: warmup_mean_latency: 0.0 
          XI worker: warmup_mean_latency2: 0.0 
          XI worker: warmup_stdev_latency: 0.0 
          XI worker: warmup_cv_latency: 0.0 
          XI worker: warmup_pass_mean_latency: 0.0 
          XI worker: warmup_pass_mean_latency2: 0.0 
          XI worker: warmup_pass_stdev_latency: 0.0 
          XI worker: warmup_pass_cv_latency: 0.0 
          XI worker: warmup_fail_mean_latency: 0.0 
          XI worker: warmup_fail_mean_latency2: 0.0 
          XI worker: warmup_fail_stdev_latency: 0.0 
          XI worker: warmup_fail_cv_latency: 0.0

動的モデルのベンチマーク#

動的モデルをテストするには、-s (shape) パラメーターを指定する必要があります。動的モデルを使用できますが、一部の静的モデルでは動的形状を指定することもできます。最初にモデルをワークスペースにダウンロードします。

mkdir -p workspace/face-detection-retail-0005/1 
cd workspace/face-detection-retail-0005/1 
wget https://storage.openvinotoolkit.org/repositories/open_model_zoo/2023.0/models_bin/1/face-detection-retail-0005/FP32/face-detection-retail-0005.bin 
wget https://storage.openvinotoolkit.org/repositories/open_model_zoo/2023.0/models_bin/1/face-detection-retail-0005/FP32/face-detection-retail-0005.xml 
cd ../../..

次に、動的入力形状を指定して OVMS を起動します。

docker run -u $(id -u) -p 9000:9000 -p 8000:8000 -d -v ${PWD}/workspace:/workspace openvino/model_server --model_path /workspace/face-detection-retail-0005 --model_name face-detection-retail-0005 --shape "(-1,3,-1,-1)" --port 9000 --rest_port 8000

指定した形状の要求を生成するには、入力形状を明示的に設定する必要があります。これは、-s または --shape パラメーターで必要な数値を指定します。

docker run --network host benchmark_client -a localhost -r 8000 -m face-detection-retail-0005 -p 9000 -n 8 -s 1 3 300 300 --print_all 

Client 2.7 
NO_PROXY=localhost no_proxy=localhost python3 /ovms_benchmark_client/main.py -a localhost -r 8000 -m face-detection-retail-0005 -p 9000 -n 8 -s 1 3 300 300 --print_all 
          XI worker: request for metadata of model face-detection-retail-0005... 
          XI worker: Metadata for model face-detection-retail-0005 is downloaded... 
          XI worker: set version of model face-detection-retail-0005: 1 
          XI worker: inputs: 
          XI worker:  input.1: 
          XI worker:   name: input.1 
          XI worker:   dtype: DT_FLOAT 
          XI worker:   tensorShape: {'dim': [{'size': '-1'}, {'size': '3'}, {'size': '-1'}, {'size': '-1'}]} 
          XI worker: outputs: 
          XI worker:  527: 
          XI worker:   name: 527 
          XI worker:   dtype: DT_FLOAT 
          XI worker:   tensorShape: {'dim': [{'size': '1'}, {'size': '1'}, {'size': '-1'}, {'size': '7'}]} 
          XI worker: new random range: 0.0, 255.0 
          XI worker: batchsize sequence: [1] 
          XI worker: dataset length (input.1): 1 
          XI worker: --> dim: 1 
          XI worker: --> dim: 3 
          XI worker: --> dim: 300 
          XI worker: --> dim: 300 
          XI worker: Generated data shape: (1, 3, 300, 300) 
          XI worker: start workload... 
...

ベンチマーク結果のまとめ#

ベンチマーク結果の概要は、コマンドオプション -ps で表示できます。

docker run --network host benchmark_client -a localhost -r 8000 -m face-detection-retail-0005 -p 9000 -s 2 3 300 300 -t 20 -u 2 -w 10 -ps

Sample output log with results summary:


Client 2.7 
NO_PROXY=localhost no_proxy=localhost python3 /ovms_benchmark_client/main.py -a localhost -r 8000 -m face-detection-retail-0005 -p 9000 -s 2 3 300 300 -t 20 -u 2 -w 10 -ps 
          XI worker: start workload...

### Benchmark Parameters ### 
 Model: face-detection-retail-0005
 Input shape: ['2', '3', '300', '300']
 Request concurrency: 1 Test Duration (s):
 Total (t): 20.00 | Warmup (u): 2.00 | Window (w): 10.00 

### Benchmark Summary ###
 ## General Metrics ##
 Duration(s): Total: 20.01 | Window: 10.01
 Batches: Total: 1781 | Window: 891 

 ## Latency Metrics (ms) ##
 Mean: 11.20 | stdev: 0.74 | p50: 12.78 | p90: 15.26 | p95: 15.56

 ## Throughput Metrics (fps) ##
 Frame Rate (FPS): Brutto: 89.01 | Netto: 89.24
 Batch Rate (batches/s): Brutto: 89.01 | Netto: 89.24

MediaPipe ベンチマーク#

Mediapipe servable を含む config.json を使用して OVMS コンテナを起動します。OVMS は MediaPipe を有効にしてビルドする必要があります。

cp -r ${PWD}/sample_data ${PWD}/workspace/sample_data 
docker run -u $(id -u) -p 9000:9000 -p 8000:8000 -d -v ${PWD}/workspace:/workspace openvino/model_server --port 9000 --rest_port 8000 --config_path /workspace/sample_data/config.json

ベンチマークの要求は、numpy ファイルの配列を基に準備されます。このデータファイルは、スイッチ -d <data-file>.npy を指定することによってベンチマーク・クライアントに供給されます。KServe API が設定されている場合は、単一のモデルやパイプラインに対しても numpy データが使用できることに注意してください。Python 3 を使用して、配列の形状と精度を指定してサンプルデータを作成できます。この例では、生成された .npy ファイルを workspace/sample_data ディレクトリーに保存する必要があります。

python -c 'import numpy as np ; \ 
    arr = np.ones((1,3,224,224),dtype=np.float32); \ 
    np.save("workspace/sample_data/resnet50-binary-0001.npy", arr)'

MediaPipe グラフファイルと servable を config.json で指定すると、モデル名の代わりにその名前で呼び出します: -m <mediapipe-servable-name>。Mediapipe グラフは KServe API 経由でのみ公開されるため、--api KFS を設定する必要があります。

docker run -v ${PWD}/workspace:/workspace --network host benchmark_client -a localhost -r 8000 -m resnet50-binary-0001_mediapipe -p 9000 -n 8 --api KFS -d /workspace/sample_data/resnet50-binary-0001.npy --report_warmup --print_all

他の多くのクライアント・オプションとベンチマークの例は、追加の PDF ドキュメントに記載されています。