OpenVINO™ での GPU 動作¶
この Jupyter ノートブックは、ローカルへのインストール後にのみ起動できます。
目次¶
このチュートリアルでは、OpenVINO でインテル® GPU を操作する概要を説明します。クエリーデバイスを使用してシステム GPU を一覧表示し、そのプロパティーを確認する方法を示し、いくつかの主要なプロパティーについて説明します。パフォーマンスのヒントを使用して GPU でモデルをコンパイルする方法と、MULTI または CUMULATIVE_THROUGHPUT を使用して複数の GPU を使用する方法を示します。
このチュートリアルでは、さまざまな構成で GPU パフォーマンスを比較するのに実行できる Benchmark_app のコマンド例も示します。また、GPU 上でモデルをコンパイルし、それを使用して推論を実行する、基本的なエンドツーエンド・アプリケーションのコードも提供します。
はじめに¶
元々、グラフィック・プロセッシング・ユニット (GPU) は、コンピューター・グラフィックスのレンダリングを高速化する特殊なチップとして開発が始まりました。少数ですが強力なコアを備えた CPU とは対照的に、GPU は多くの特殊なコアを備えているため、より単純なタスクに並列化できるワークロードに最適です。現在、そのようなワークロードの 1 つはディープラーニングであり、GPU は操作を複数のコアに分割することでニューラル・ネットワークの推論を簡単に高速化できます。
OpenVINO は、インテルの統合 GPU (ほとんどのインテル® Core™ デスクトップおよびモバイル・プロセッサーに付属)、またはインテル® Arc™ A シリーズ・グラフィックス・カードやインテル® データセンター GPU Flex シリーズなどのインテルのディスクリート GPU 製品での推論をサポートします。開始するには、まず 1 つ以上のインテル GPU を搭載したシステムに OpenVINO をインストールします。GPU 構成手順に従って、GPU で動作するように OpenVINO を構成します。次に、OpenVINO で GPU を使用して推論を高速化する方法を学習します。
必要なパッケージをインストール¶
%pip install -q "openvino-dev>=2023.1.0"
%pip install -q tensorflow
# Fetch `notebook_utils` module
import urllib.request
urllib.request.urlretrieve(
url='https://raw.githubusercontent.com/openvinotoolkit/openvino_notebooks/main/notebooks/utils/notebook_utils.py',
filename='notebook_utils.py'
)
('notebook_utils.py', <http.client.HTTPMessage at 0x7f2d0c5baa40>)
デバイス照会による GPU のチェック¶
このセクションでは、利用可能な GPU を一覧表示し、そのプロパティーを確認する方法を説明します。いくつかの主要なプロパティーも定義されます。
core.available_devices で GPU をリスト¶
OpenVINO ランタイムは、推論に使用できるデバイスを確認する available_devices
メソッドを提供します。次のコードは、インテル GPU が表示される互換性のある OpenVINO デバイスのリストを出力します。
import openvino as ov
core = ov.Core()
core.available_devices
['CPU', 'GPU']
GPU デバイスの番号は 0 から始まることに注意してください。システムに ID がある場合、統合 GPU は常に ID 0
を取得します。例えば、システムに CPU、統合型およびディスクリート GPU が搭載されている場合、['CPU', 'GPU.0', 'GPU.1']
のようなリストが表示されることが予想されます。使用を簡素化するために、“GPU.0” は “GPU” で表すこともできます。詳細については、デバイスの命名規則セクションを参照してください。
GPU がシステムに正しくインストールされているにもかかわらずリストに表示されない場合は、ここで説明されている手順に従って、OpenVINO で動作するように GPU ドライバーを構成します。GPU が OpenVINO で動作するようになったら、次のセクションに進みます。
core.get_property でプロパティーを確認¶
GPU に関する情報を取得するには、デバイスのプロパティーを使用できます。OpenVINO では、デバイスにはその特性と構成を説明するプロパティーがあります。各プロパティーには、get_property
メソッドで照会できる名前と関連する値があります。
デバイス名などのプロパティーの値を取得するには、次のように get_property
メソッドを使用します。
device = "GPU"
core.get_property(device, "FULL_DEVICE_NAME")
'Intel(R) Graphics [0x46a6] (iGPU)'
各デバイスには、SUPPORTED_PROPERTIES
と呼ばれる特定のプロパティーもあり、デバイスで使用可能なすべてのプロパティーを表示できます。core.get_property("GPU", "SUPPORTED_PROPERTIES")
によって返された辞書を単純にループし、そのプロパティーを照会することで、各プロパティー値を確認できます。
print(f"{device} SUPPORTED_PROPERTIES:\n")
supported_properties = core.get_property(device, "SUPPORTED_PROPERTIES")
indent = len(max(supported_properties, key=len))
for property_key in supported_properties:
if property_key not in ('SUPPORTED_METRICS', 'SUPPORTED_CONFIG_KEYS', 'SUPPORTED_PROPERTIES'):
try:
property_val = core.get_property(device, property_key)
except TypeError:
property_val = 'UNSUPPORTED TYPE'
print(f"{property_key:<{indent}}: {property_val}")
GPU SUPPORTED_PROPERTIES:
AVAILABLE_DEVICES : ['0']
RANGE_FOR_ASYNC_INFER_REQUESTS: (1, 2, 1)
RANGE_FOR_STREAMS : (1, 2)
OPTIMAL_BATCH_SIZE : 1
MAX_BATCH_SIZE : 1
CACHING_PROPERTIES : {'GPU_UARCH_VERSION': 'RO', 'GPU_EXECUTION_UNITS_COUNT': 'RO', 'GPU_DRIVER_VERSION': 'RO', 'GPU_DEVICE_ID': 'RO'}
DEVICE_ARCHITECTURE : GPU: v12.0.0
FULL_DEVICE_NAME : Intel(R) Graphics [0x46a6] (iGPU)
DEVICE_UUID : UNSUPPORTED TYPE
DEVICE_TYPE : Type.INTEGRATED
DEVICE_GOPS : UNSUPPORTED TYPE
OPTIMIZATION_CAPABILITIES : ['FP32', 'BIN', 'FP16', 'INT8']
GPU_DEVICE_TOTAL_MEM_SIZE : UNSUPPORTED TYPE
GPU_UARCH_VERSION : 12.0.0
GPU_EXECUTION_UNITS_COUNT : 96
GPU_MEMORY_STATISTICS : UNSUPPORTED TYPE
PERF_COUNT : False
MODEL_PRIORITY : Priority.MEDIUM
GPU_HOST_TASK_PRIORITY : Priority.MEDIUM
GPU_QUEUE_PRIORITY : Priority.MEDIUM
GPU_QUEUE_THROTTLE : Priority.MEDIUM
GPU_ENABLE_LOOP_UNROLLING : True
CACHE_DIR :
PERFORMANCE_HINT : PerformanceMode.UNDEFINED
COMPILATION_NUM_THREADS : 20
NUM_STREAMS : 1
PERFORMANCE_HINT_NUM_REQUESTS : 0
INFERENCE_PRECISION_HINT : <Type: 'undefined'>
DEVICE_ID : 0
主要なプロパティーの簡単な説明¶
最後のコマンドに見られるように、各デバイスにはいくつかのプロパティーがあります。主要なプロパティーの一部は次のとおりです。
FULL_DEVICE_NAME
- GPU の製品名、および統合 GPU かディスクリート GPU (iGPU または dGPU) 。OPTIMIZATION_CAPABILITIES
- この GPU でサポートされるモデルのデータタイプ (INT8、FP16、FP32 など)。GPU_EXECUTION_UNITS_COUNT
- GPU のアーキテクチャーで利用可能な実行コア。これは GPU の処理能力の相対的な尺度です。RANGE_FOR_STREAMS
- 並列推論要求の実行に使用できる、GPU 上で利用可能な処理ストリームの数。LATENCY または THROUGHPUT モードでモデルをコンパイルする場合、OpenVINO は低レイテンシーまたは高スループットを実現する最適なストリーム数を自動的に選択します。PERFORMANCE_HINT
- デバイス固有の設定を気にせずに、レイテンシーやスループットなどの特定のパフォーマンス・メトリックに合わせてデバイスを調整する高レベルの方法。CACHE_DIR
- コンパイル時間を短縮するモデルのキャッシュデータが保存されるディレクトリー。
デバイスとプロパティーの詳細については、デバイス・プロパティーの照会ページを参照してください。
GPU でのモデルのコンパイル¶
これで、システム内の GPU を一覧表示し、そのプロパティーを確認する方法が分かりました。OpenVINO GPU プラグインを使用してモデルをコンパイルおよび実行するのに簡単に使用できます。
モデルのダウンロードと変換¶
このチュートリアルでは ssdlite_mobilenet_v2
モデルを使用します。ssdlite_mobilenet_v2
モデルはオブジェクト検出に使用されます。このモデルは、91 カテゴリーのオブジェクトを含む Common Objects in Context (COCO) データセットのバージョンでトレーニングされました。詳細についてはこちらを参照してください。
モデルをダウンロードしてアンパック¶
モデルを含むアーカイブをダウンロードするには、notebook_utils
の download_file
関数を使用します。ディレクトリー構造が自動的に作成され、選択したモデルがダウンロードされます。パッケージがすでにダウンロードされている場合、この手順はスキップされます。
import sys
import tarfile
from pathlib import Path
sys.path.append("../utils")
import notebook_utils as utils
# A directory where the model will be downloaded.
base_model_dir = Path("./model").expanduser()
model_name = "ssdlite_mobilenet_v2"
archive_name = Path(f"{model_name}_coco_2018_05_09.tar.gz")
# Download the archive
downloaded_model_path = base_model_dir / archive_name
if not downloaded_model_path.exists():
model_url = f"http://download.tensorflow.org/models/object_detection/{archive_name}"
utils.download_file(model_url, downloaded_model_path.name, downloaded_model_path.parent)
# Unpack the model
tf_model_path = base_model_dir / archive_name.with_suffix("").stem / "frozen_inference_graph.pb"
if not tf_model_path.exists():
with tarfile.open(downloaded_model_path) as file:
file.extractall(base_model_dir)
model/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz: 0%| | 0.00/48.7M [00:00<?, ?B/s]
IOPub message rate exceeded. The notebook server will temporarily stop sending output to the client in order to avoid crashing it. To change this limit, set the config variable --NotebookApp.iopub_msg_rate_limit. Current values: NotebookApp.iopub_msg_rate_limit=1000.0 (msgs/sec) NotebookApp.rate_limit_window=3.0 (secs)
モデルを OpenVINO IR 形式に変換¶
FP16
精度でモデルを OpenVINO IR に変換するには、モデル変換 API を使用します。モデルは、model/ir_model/
ディレクトリーに保存されます。モデル変換の詳細については、このページを参照してください。
from openvino.tools.mo.front import tf as ov_tf_front
precision = 'FP16'
# The output path for the conversion.
model_path = base_model_dir / 'ir_model' / f'{model_name}_{precision.lower()}.xml'
trans_config_path = Path(ov_tf_front.__file__).parent / "ssd_v2_support.json"
pipeline_config = base_model_dir / archive_name.with_suffix("").stem / "pipeline.config"
model = None
if not model_path.exists():
model = ov.tools.mo.convert_model(input_model=tf_model_path,
input_shape=[1, 300, 300, 3],
layout='NHWC',
transformations_config=trans_config_path,
tensorflow_object_detection_api_pipeline_config=pipeline_config,
reverse_input_channels=True)
ov.save_model(model, model_path, compress_to_fp16=(precision == "FP16"))
print("IR model saved to {}".format(model_path))
else:
print("Read IR model from {}".format(model_path))
model = core.read_model(model_path)
[ WARNING ] The Preprocessor block has been removed. Only nodes performing mean value subtraction and scaling (if applicable) are kept.
IR model saved to model/ir_model/ssdlite_mobilenet_v2_fp16.xml
モデルの準備ができたら、read_model
メソッドを使用してモデルを読み取る必要があります。次に、compile_model
メソッドを使用して、モデルをコンパイルするデバイスの名前 (この場合は “GPU”) を指定します。
compiled_model = core.compile_model(model, device)
システムに複数の GPU がある場合は、 “GPU.0”、“GPU.1” などを使用して、GPU を指定できます。available_devices
メソッドによって返されるデバイス名はいずれも有効なデバイス指定子です。“AUTO” を使用すると、推論に最適なデバイス (通常は GPU) が自動的に選択されます。AUTO プラグインの詳細については、自動デバイス選択ページと AUTO デバイス・チュートリアルをご覧ください。
使用されるモデルによっては、デバイス固有の最適化やネットワーク・コンパイルにより、コンパイルステップに時間がかかることがあり、特に大規模なモデルの場合は、それらが使用されるアプリケーションでユーザー・エクスペリエンスが低下する可能性があります。この問題を解決するために、OpenVINO は、サポートされているデバイスでモデルをコンパイルするとすぐにモデルをキャッシュし、事前にキャッシュフォルダーを設定するだけで、後の compile_model
呼び出しでそのモデルを再利用することができます。例えば、コンパイルした同じモデルをキャッシュするには、次のようにします。
import time
from pathlib import Path
# Create cache folder
cache_folder = Path("cache")
cache_folder.mkdir(exist_ok=True)
start = time.time()
core = ov.Core()
# Set cache folder
core.set_property({'CACHE_DIR': cache_folder})
# Compile the model as before
model = core.read_model(model=model_path)
compiled_model = core.compile_model(model, device)
print(f"Cache enabled (first time) - compile time: {time.time() - start}s")
Cache enabled (first time) - compile time: 1.692436695098877s
キャッシュの影響を知るために、キャッシュを有効にした場合と無効にした場合のコンパイル時間を測定できます。
start = time.time()
core = ov.Core()
core.set_property({'CACHE_DIR': 'cache'})
model = core.read_model(model=model_path)
compiled_model = core.compile_model(model, device)
print(f"Cache enabled - compile time: {time.time() - start}s")
start = time.time()
core = ov.Core()
model = core.read_model(model=model_path)
compiled_model = core.compile_model(model, device)
print(f"Cache disabled - compile time: {time.time() - start}s")
Cache enabled - compile time: 0.26888394355773926s
Cache disabled - compile time: 1.982884168624878s
実際の時間短縮は環境や使用されているモデルによって異なりますが、アプリケーションを最適化する際には必ず考慮する必要があります。詳細については、モデルキャッシュのドキュメントを参照してください。
デバイスとパイプラインの構成を簡素化するため、OpenVINO は推論に使用するバッチサイズと並列スレッドの数を自動的に設定する高レベルのパフォーマンス・ヒントを提供します。“LATENCY” パフォーマンス・ヒントは推論時間を高速化するように最適化され、“THROUGHPUT” パフォーマンス・ヒントは全体的な帯域幅または FPS を高くするように最適化されます。
“LATENCY” パフォーマンス・ヒントを使用するには、以下のようにモデルをコンパイルする際に {"PERFORMANCE_HINT": "LATENCY"}
を追加します。GPU の場合、これによりバッチサイズと並列ストリームの数が自動的に最小化され、すべてのコンピューティング・リソースが単一の推論をできるだけ早く完了することに集中できるようになります。
compiled_model = core.compile_model(model, device, {"PERFORMANCE_HINT": "LATENCY"})
“THROUGHPUT” パフォーマンス・ヒントを使用するには、モデルをコンパイルするときに {"PERFORMANCE_HINT": "THROUGHPUT"}
を追加します。GPU の場合、これにより複数の処理ストリームが作成され、すべての実行コアが効率良く利用されることで使用可能なメモリーを埋めるバッチサイズが最適化されます。
compiled_model = core.compile_model(model, device, {"PERFORMANCE_HINT": "THROUGHPUT"})
上記のレイテンシーとスループットのヒントは優れており、適切に使用すると良好な結果となる可能性がありますが、通常は、AUTO プラグインまたは上記のようにデバイス名を手動で指定することにより、1 つのデバイスのみを使用します。統合型 GPU とディスクリート GPU など複数のデバイスがある場合、リソースの使用率を向上するため両方を同時に使用できます。これを実現するために、OpenVINO は MULTI と呼ばれる仮想デバイスを提供します。これは、各デバイスの機能を活用して推論をデバイス間で分割する方法が判明している既存のデバイスの組み合わせです。
例えば、統合 GPU とディスクリート GPU の両方、および CPU を同時に使用する場合、次のようにモデルをコンパイルします。
compiled_model = core.compile_model(model=model, device_name="MULTI:GPU.1,GPU.0,CPU")
MULTI が機能するには、常にデバイスリストを明示的に指定する必要があることに注意してください。そうしないと、MULTI は推論に使用できるデバイスを認識できません。ただし、OpenVINO で複数のデバイスを使用する方法はこれだけではありません。“CUMULATIVE_THROUGHPUT” と呼ばれるパフォーマンス・ヒントがあります。これは MULTI と同様に機能しますが、AUTO によって自動的に選択されたデバイスを使用します。この方法では、使用するデバイスを手動で指定する必要がありません。以下は、MULTI と同等の “CUMULATIVE_THROUGHPUT” の使用法を示す例です。
compiled_model = core.compile_model(model=model, device_name="AUTO", config={"PERFORMANCE_HINT": "CUMULATIVE_THROUGHPUT"})
重要: “THROUGHPUT”、“MULTI” および “CUMULATIVE_THROUGHPUT” モードは、非同期推論パイプラインにのみ適用されます。この記事の最後の例では、並列処理を利用してスループットを向上させる非同期パイプラインを設定する方法を示します。詳細については、OpenVINO での非同期推論および非同期推論ノートブックを参照してください。
benchmark_app とのパフォーマンス比較¶
モデルのコンパイルに利用できるさまざまなオプションを考えると、特定のアプリケーションで最適な設定を知るのは難しい場合があります。ありがたいことに、OpenVINO ではパフォーマンス・ベンチマーク・ツールである benchmark_app
が提供されています。
benchmark_app
の基本的な構文は次のとおりです。
benchmark_app -m PATH_TO_MODEL -d TARGET_DEVICE -hint {throughput,cumulative_throughput,latency,none}
ここで、TARGET_DEVICE
は、available_devices
メソッドによって表示される任意のデバイス、および前述の MULTI および AUTO デバイスであり、hint は括弧内の値のいずれかになります。
benchmark_app を実行するにはモデルパスのみが必要ですが、デバイス引数とヒント引数の両方が役立ちます。より高度な使用法については、benchmark_app -h
を実行するか、ドキュメントで確認できます。次の例は、レイテンシーに重点を置いて GPU を使用し、単純なモデルをベンチマークする方法を示しています。
!benchmark_app -m {model_path} -d GPU -hint latency
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading OpenVINO Runtime
[ INFO ] OpenVINO:
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ] Device info:
[ INFO ] GPU
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ]
[Step 3/11] Setting device configuration
[Step 4/11] Reading model files
[ INFO ] Loading model files
[ INFO ] Read model took 14.02 ms
[ INFO ] Original model I/O parameters:
[ INFO ] Model inputs:
[ INFO ] image_tensor , image_tensor:0 (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 5/11] Resizing model to match image sizes and given batch
[ INFO ] Model batch size: 1
[Step 6/11] Configuring input of the model
[ INFO ] Model inputs:
[ INFO ] image_tensor , image_tensor:0 (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 7/11] Loading the model to the device
[ INFO ] Compile model took 1932.50 ms
[Step 8/11] Querying optimal runtime parameters
[ INFO ] Model:
[ INFO ] NETWORK_NAME: frozen_inference_graph
[ INFO ] OPTIMAL_NUMBER_OF_INFER_REQUESTS: 1
[ INFO ] PERF_COUNT: False
[ INFO ] MODEL_PRIORITY: Priority.MEDIUM
[ INFO ] GPU_HOST_TASK_PRIORITY: Priority.MEDIUM
[ INFO ] GPU_QUEUE_PRIORITY: Priority.MEDIUM
[ INFO ] GPU_QUEUE_THROTTLE: Priority.MEDIUM
[ INFO ] GPU_ENABLE_LOOP_UNROLLING: True
[ INFO ] CACHE_DIR:
[ INFO ] PERFORMANCE_HINT: PerformanceMode.LATENCY
[ INFO ] COMPILATION_NUM_THREADS: 20
[ INFO ] NUM_STREAMS: 1
[ INFO ] PERFORMANCE_HINT_NUM_REQUESTS: 0
[ INFO ] INFERENCE_PRECISION_HINT: <Type: 'undefined'>
[ INFO ] DEVICE_ID: 0
[Step 9/11] Creating infer requests and preparing input tensors
[ WARNING ] No input files were given for input 'image_tensor'!. This input will be filled with random values!
[ INFO ] Fill input 'image_tensor' with random values
[Step 10/11] Measuring performance (Start inference asynchronously, 1 inference requests, limits: 60000 ms duration)
[ INFO ] Benchmarking in inference only mode (inputs filling are not included in measurement loop).
[ INFO ] First inference took 6.17 ms
[Step 11/11] Dumping statistics report
[ INFO ] Count: 12710 iterations
[ INFO ] Duration: 60006.58 ms
[ INFO ] Latency:
[ INFO ] Median: 4.52 ms
[ INFO ] Average: 4.57 ms
[ INFO ] Min: 3.13 ms
[ INFO ] Max: 17.62 ms
[ INFO ] Throughput: 211.81 FPS
完全を期すために、使用するデバイスとヒントを変えて実行したい比較のいくつかをリストします。実際のパフォーマンスは、使用するハードウェアによって異なる場合があることに注意してください。一般に、GPU は CPU よりも優れていると期待されますが、それぞれに十分なワークがある限り、複数の GPU は単一の GPU よりも優れているはずです。
CPU と GPU とレイテンシーのヒント¶
!benchmark_app -m {model_path} -d CPU -hint latency
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading OpenVINO Runtime
[ INFO ] OpenVINO:
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ] Device info:
[ INFO ] CPU
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ]
[Step 3/11] Setting device configuration
[Step 4/11] Reading model files
[ INFO ] Loading model files
[ INFO ] Read model took 30.38 ms
[ INFO ] Original model I/O parameters:
[ INFO ] Model inputs:
[ INFO ] image_tensor , image_tensor:0 (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 5/11] Resizing model to match image sizes and given batch
[ INFO ] Model batch size: 1
[Step 6/11] Configuring input of the model
[ INFO ] Model inputs:
[ INFO ] image_tensor , image_tensor:0 (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 7/11] Loading the model to the device
[ INFO ] Compile model took 127.72 ms
[Step 8/11] Querying optimal runtime parameters
[ INFO ] Model:
[ INFO ] NETWORK_NAME: frozen_inference_graph
[ INFO ] OPTIMAL_NUMBER_OF_INFER_REQUESTS: 1
[ INFO ] NUM_STREAMS: 1
[ INFO ] AFFINITY: Affinity.CORE
[ INFO ] INFERENCE_NUM_THREADS: 14
[ INFO ] PERF_COUNT: False
[ INFO ] INFERENCE_PRECISION_HINT: <Type: 'float32'>
[ INFO ] PERFORMANCE_HINT: PerformanceMode.LATENCY
[ INFO ] PERFORMANCE_HINT_NUM_REQUESTS: 0
[Step 9/11] Creating infer requests and preparing input tensors
[ WARNING ] No input files were given for input 'image_tensor'!. This input will be filled with random values!
[ INFO ] Fill input 'image_tensor' with random values
[Step 10/11] Measuring performance (Start inference asynchronously, 1 inference requests, limits: 60000 ms duration)
[ INFO ] Benchmarking in inference only mode (inputs filling are not included in measurement loop).
[ INFO ] First inference took 4.42 ms
[Step 11/11] Dumping statistics report
[ INFO ] Count: 15304 iterations
[ INFO ] Duration: 60005.72 ms
[ INFO ] Latency:
[ INFO ] Median: 3.87 ms
[ INFO ] Average: 3.88 ms
[ INFO ] Min: 3.49 ms
[ INFO ] Max: 5.95 ms
[ INFO ] Throughput: 255.04 FPS
!benchmark_app -m {model_path} -d GPU -hint latency
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading OpenVINO Runtime
[ INFO ] OpenVINO:
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ] Device info:
[ INFO ] GPU
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ]
[Step 3/11] Setting device configuration
[Step 4/11] Reading model files
[ INFO ] Loading model files
[ INFO ] Read model took 14.65 ms
[ INFO ] Original model I/O parameters:
[ INFO ] Model inputs:
[ INFO ] image_tensor , image_tensor:0 (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 5/11] Resizing model to match image sizes and given batch
[ INFO ] Model batch size: 1
[Step 6/11] Configuring input of the model
[ INFO ] Model inputs:
[ INFO ] image_tensor , image_tensor:0 (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 7/11] Loading the model to the device
[ INFO ] Compile model took 2254.81 ms
[Step 8/11] Querying optimal runtime parameters
[ INFO ] Model:
[ INFO ] NETWORK_NAME: frozen_inference_graph
[ INFO ] OPTIMAL_NUMBER_OF_INFER_REQUESTS: 1
[ INFO ] PERF_COUNT: False
[ INFO ] MODEL_PRIORITY: Priority.MEDIUM
[ INFO ] GPU_HOST_TASK_PRIORITY: Priority.MEDIUM
[ INFO ] GPU_QUEUE_PRIORITY: Priority.MEDIUM
[ INFO ] GPU_QUEUE_THROTTLE: Priority.MEDIUM
[ INFO ] GPU_ENABLE_LOOP_UNROLLING: True
[ INFO ] CACHE_DIR:
[ INFO ] PERFORMANCE_HINT: PerformanceMode.LATENCY
[ INFO ] COMPILATION_NUM_THREADS: 20
[ INFO ] NUM_STREAMS: 1
[ INFO ] PERFORMANCE_HINT_NUM_REQUESTS: 0
[ INFO ] INFERENCE_PRECISION_HINT: <Type: 'undefined'>
[ INFO ] DEVICE_ID: 0
[Step 9/11] Creating infer requests and preparing input tensors
[ WARNING ] No input files were given for input 'image_tensor'!. This input will be filled with random values!
[ INFO ] Fill input 'image_tensor' with random values
[Step 10/11] Measuring performance (Start inference asynchronously, 1 inference requests, limits: 60000 ms duration)
[ INFO ] Benchmarking in inference only mode (inputs filling are not included in measurement loop).
[ INFO ] First inference took 8.79 ms
[Step 11/11] Dumping statistics report
[ INFO ] Count: 11354 iterations
[ INFO ] Duration: 60007.21 ms
[ INFO ] Latency:
[ INFO ] Median: 4.57 ms
[ INFO ] Average: 5.16 ms
[ INFO ] Min: 3.18 ms
[ INFO ] Max: 34.87 ms
[ INFO ] Throughput: 189.21 FPS
CPU と GPU とスループットのヒント¶
!benchmark_app -m {model_path} -d CPU -hint throughput
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading OpenVINO Runtime
[ INFO ] OpenVINO:
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ] Device info:
[ INFO ] CPU
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ]
[Step 3/11] Setting device configuration
[Step 4/11] Reading model files
[ INFO ] Loading model files
[ INFO ] Read model took 29.56 ms
[ INFO ] Original model I/O parameters:
[ INFO ] Model inputs:
[ INFO ] image_tensor:0 , image_tensor (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 5/11] Resizing model to match image sizes and given batch
[ INFO ] Model batch size: 1
[Step 6/11] Configuring input of the model
[ INFO ] Model inputs:
[ INFO ] image_tensor:0 , image_tensor (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 7/11] Loading the model to the device
[ INFO ] Compile model took 158.91 ms
[Step 8/11] Querying optimal runtime parameters
[ INFO ] Model:
[ INFO ] NETWORK_NAME: frozen_inference_graph
[ INFO ] OPTIMAL_NUMBER_OF_INFER_REQUESTS: 5
[ INFO ] NUM_STREAMS: 5
[ INFO ] AFFINITY: Affinity.CORE
[ INFO ] INFERENCE_NUM_THREADS: 20
[ INFO ] PERF_COUNT: False
[ INFO ] INFERENCE_PRECISION_HINT: <Type: 'float32'>
[ INFO ] PERFORMANCE_HINT: PerformanceMode.THROUGHPUT
[ INFO ] PERFORMANCE_HINT_NUM_REQUESTS: 0
[Step 9/11] Creating infer requests and preparing input tensors
[ WARNING ] No input files were given for input 'image_tensor'!. This input will be filled with random values!
[ INFO ] Fill input 'image_tensor' with random values
[Step 10/11] Measuring performance (Start inference asynchronously, 5 inference requests, limits: 60000 ms duration)
[ INFO ] Benchmarking in inference only mode (inputs filling are not included in measurement loop).
[ INFO ] First inference took 8.15 ms
[Step 11/11] Dumping statistics report
[ INFO ] Count: 25240 iterations
[ INFO ] Duration: 60010.99 ms
[ INFO ] Latency:
[ INFO ] Median: 10.16 ms
[ INFO ] Average: 11.84 ms
[ INFO ] Min: 7.96 ms
[ INFO ] Max: 37.53 ms
[ INFO ] Throughput: 420.59 FPS
!benchmark_app -m {model_path} -d GPU -hint throughput
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading OpenVINO Runtime
[ INFO ] OpenVINO:
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ] Device info:
[ INFO ] GPU
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ]
[Step 3/11] Setting device configuration
[Step 4/11] Reading model files
[ INFO ] Loading model files
[ INFO ] Read model took 15.45 ms
[ INFO ] Original model I/O parameters:
[ INFO ] Model inputs:
[ INFO ] image_tensor , image_tensor:0 (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 5/11] Resizing model to match image sizes and given batch
[ INFO ] Model batch size: 1
[Step 6/11] Configuring input of the model
[ INFO ] Model inputs:
[ INFO ] image_tensor , image_tensor:0 (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 7/11] Loading the model to the device
[ INFO ] Compile model took 2249.04 ms
[Step 8/11] Querying optimal runtime parameters
[ INFO ] Model:
[ INFO ] NETWORK_NAME: frozen_inference_graph
[ INFO ] OPTIMAL_NUMBER_OF_INFER_REQUESTS: 4
[ INFO ] PERF_COUNT: False
[ INFO ] MODEL_PRIORITY: Priority.MEDIUM
[ INFO ] GPU_HOST_TASK_PRIORITY: Priority.MEDIUM
[ INFO ] GPU_QUEUE_PRIORITY: Priority.MEDIUM
[ INFO ] GPU_QUEUE_THROTTLE: Priority.MEDIUM
[ INFO ] GPU_ENABLE_LOOP_UNROLLING: True
[ INFO ] CACHE_DIR:
[ INFO ] PERFORMANCE_HINT: PerformanceMode.THROUGHPUT
[ INFO ] COMPILATION_NUM_THREADS: 20
[ INFO ] NUM_STREAMS: 2
[ INFO ] PERFORMANCE_HINT_NUM_REQUESTS: 0
[ INFO ] INFERENCE_PRECISION_HINT: <Type: 'undefined'>
[ INFO ] DEVICE_ID: 0
[Step 9/11] Creating infer requests and preparing input tensors
[ WARNING ] No input files were given for input 'image_tensor'!. This input will be filled with random values!
[ INFO ] Fill input 'image_tensor' with random values
[Step 10/11] Measuring performance (Start inference asynchronously, 4 inference requests, limits: 60000 ms duration)
[ INFO ] Benchmarking in inference only mode (inputs filling are not included in measurement loop).
[ INFO ] First inference took 9.17 ms
[Step 11/11] Dumping statistics report
[ INFO ] Count: 19588 iterations
[ INFO ] Duration: 60023.47 ms
[ INFO ] Latency:
[ INFO ] Median: 11.31 ms
[ INFO ] Average: 12.15 ms
[ INFO ] Min: 9.26 ms
[ INFO ] Max: 36.04 ms
[ INFO ] Throughput: 326.34 FPS
単一 GPU と複数 GPU¶
!benchmark_app -m {model_path} -d GPU.1 -hint throughput
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading OpenVINO Runtime
[ INFO ] OpenVINO:
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ] Device info:
[ INFO ] GPU
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ]
[Step 3/11] Setting device configuration
[ WARNING ] Device GPU.1 does not support performance hint property(-hint).
[ ERROR ] Config for device with 1 ID is not registered in GPU plugin
Traceback (most recent call last):
File "/home/adrian/repos/openvino_notebooks/venv/lib/python3.9/site-packages/openvino/tools/benchmark/main.py", line 329, in main
benchmark.set_config(config)
File "/home/adrian/repos/openvino_notebooks/venv/lib/python3.9/site-packages/openvino/tools/benchmark/benchmark.py", line 57, in set_config
self.core.set_property(device, config[device])
RuntimeError: Config for device with 1 ID is not registered in GPU plugin
!benchmark_app -m {model_path} -d AUTO:GPU.1,GPU.0 -hint cumulative_throughput
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading OpenVINO Runtime
[ INFO ] OpenVINO:
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ] Device info:
[ INFO ] AUTO
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ] GPU
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ]
[Step 3/11] Setting device configuration
[ WARNING ] Device GPU.1 does not support performance hint property(-hint).
[Step 4/11] Reading model files
[ INFO ] Loading model files
[ INFO ] Read model took 26.66 ms
[ INFO ] Original model I/O parameters:
[ INFO ] Model inputs:
[ INFO ] image_tensor , image_tensor:0 (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 5/11] Resizing model to match image sizes and given batch
[ INFO ] Model batch size: 1
[Step 6/11] Configuring input of the model
[ INFO ] Model inputs:
[ INFO ] image_tensor , image_tensor:0 (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 7/11] Loading the model to the device
[ ERROR ] Config for device with 1 ID is not registered in GPU plugin
Traceback (most recent call last):
File "/home/adrian/repos/openvino_notebooks/venv/lib/python3.9/site-packages/openvino/tools/benchmark/main.py", line 414, in main
compiled_model = benchmark.core.compile_model(model, benchmark.device)
File "/home/adrian/repos/openvino_notebooks/venv/lib/python3.9/site-packages/openvino/runtime/ie_api.py", line 399, in compile_model
super().compile_model(model, device_name, {} if config is None else config),
RuntimeError: Config for device with 1 ID is not registered in GPU plugin
!benchmark_app -m {model_path} -d MULTI:GPU.1,GPU.0 -hint throughput
[Step 1/11] Parsing and validating input arguments
[ INFO ] Parsing input parameters
[Step 2/11] Loading OpenVINO Runtime
[ INFO ] OpenVINO:
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ] Device info:
[ INFO ] GPU
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ] MULTI
[ INFO ] Build ................................. 2022.3.0-9052-9752fafe8eb-releases/2022/3
[ INFO ]
[ INFO ]
[Step 3/11] Setting device configuration
[ WARNING ] Device GPU.1 does not support performance hint property(-hint).
[Step 4/11] Reading model files
[ INFO ] Loading model files
[ INFO ] Read model took 14.84 ms
[ INFO ] Original model I/O parameters:
[ INFO ] Model inputs:
[ INFO ] image_tensor:0 , image_tensor (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 5/11] Resizing model to match image sizes and given batch
[ INFO ] Model batch size: 1
[Step 6/11] Configuring input of the model
[ INFO ] Model inputs:
[ INFO ] image_tensor:0 , image_tensor (node: image_tensor) : u8 / [N,H,W,C] / [1,300,300,3]
[ INFO ] Model outputs:
[ INFO ] detection_boxes:0 (node: DetectionOutput) : f32 / [...] / [1,1,100,7]
[Step 7/11] Loading the model to the device
[ ERROR ] Config for device with 1 ID is not registered in GPU plugin
Traceback (most recent call last):
compiled_model = benchmark.core.compile_model(model, benchmark.device)
File "/home/adrian/repos/openvino_notebooks/venv/lib/python3.9/site-packages/openvino/runtime/ie_api.py", line 399, in compile_model
super().compile_model(model, device_name, {} if config is None else config),
RuntimeError: Config for device with 1 ID is not registered in GPU plugin
GPU を使用した基本的なアプリケーション¶
OpenVINO の GPU を使用したエンドツーエンドの物体検出の例を示します。アプリケーションは、 “THROUGHPUT” ヒントを使用して GPU 上でモデルをコンパイルし、ビデオをロードしてすべてのフレームを前処理して、モデルが期待する形状に変換します。フレームがロードされると、非同期パイプラインが設定され、推論が実行されて各フレームで見つかった検出が保存されます。次に、検出は対応するフレーム上に描画され、ビデオとして保存され、アプリケーションの最後に表示されます。
必要なパッケージをインポート¶
import time
from pathlib import Path
import cv2
import numpy as np
from IPython.display import Video
import openvino as ov
# Instantiate OpenVINO Runtime
core = ov.Core()
core.available_devices
['CPU', 'GPU']
モデルをコンパイル¶
# Read model and compile it on GPU in THROUGHPUT mode
model = core.read_model(model=model_path)
device_name = "GPU"
compiled_model = core.compile_model(model=model, device_name=device_name, config={"PERFORMANCE_HINT": "THROUGHPUT"})
# Get the input and output nodes
input_layer = compiled_model.input(0)
output_layer = compiled_model.output(0)
# Get the input size
num, height, width, channels = input_layer.shape
print('Model input shape:', num, height, width, channels)
Model input shape: 1 300 300 3
ビデオフレームのロードと前処理¶
# Load video
video_file = "https://storage.openvinotoolkit.org/repositories/openvino_notebooks/data/data/video/Coco%20Walking%20in%20Berkeley.mp4"
video = cv2.VideoCapture(video_file)
framebuf = []
# Go through every frame of video and resize it
print('Loading video...')
while video.isOpened():
ret, frame = video.read()
if not ret:
print('Video loaded!')
video.release()
break
# Preprocess frames - convert them to shape expected by model
input_frame = cv2.resize(src=frame, dsize=(width, height), interpolation=cv2.INTER_AREA)
input_frame = np.expand_dims(input_frame, axis=0)
# Append frame to framebuffer
framebuf.append(input_frame)
print('Frame shape: ', framebuf[0].shape)
print('Number of frames: ', len(framebuf))
# Show original video file
# If the video does not display correctly inside the notebook, please open it with your favorite media player
Video(video_file)
Loading video...
Video loaded!
Frame shape: (1, 300, 300, 3)
Number of frames: 288
モデル出力クラスの定義¶
# Define the model's labelmap (this model uses COCO classes)
classes = [
"background", "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train",
"truck", "boat", "traffic light", "fire hydrant", "street sign", "stop sign",
"parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant",
"bear", "zebra", "giraffe", "hat", "backpack", "umbrella", "shoe", "eye glasses",
"handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite",
"baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
"plate", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
"sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair",
"couch", "potted plant", "bed", "mirror", "dining table", "window", "desk", "toilet",
"door", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave", "oven",
"toaster", "sink", "refrigerator", "blender", "book", "clock", "vase", "scissors",
"teddy bear", "hair drier", "toothbrush", "hair brush"
]
非同期パイプラインのセットアップ¶
コールバック定義¶
# Define a callback function that runs every time the asynchronous pipeline completes inference on a frame
def completion_callback(infer_request: ov.InferRequest, frame_id: int) -> None:
global frame_number
stop_time = time.time()
frame_number += 1
predictions = next(iter(infer_request.results.values()))
results[frame_id] = predictions[:10] # Grab first 10 predictions for this frame
total_time = stop_time - start_time
frame_fps[frame_id] = frame_number / total_time
非同期パイプラインの作成¶
# Create asynchronous inference queue with optimal number of infer requests
infer_queue = ov.AsyncInferQueue(compiled_model)
infer_queue.set_callback(completion_callback)
# Perform inference on every frame in the framebuffer
results = {}
frame_fps = {}
frame_number = 0
start_time = time.time()
for i, input_frame in enumerate(framebuf):
infer_queue.start_async({0: input_frame}, i)
infer_queue.wait_all() # Wait until all inference requests in the AsyncInferQueue are completed
stop_time = time.time()
# Calculate total inference time and FPS
total_time = stop_time - start_time
fps = len(framebuf) / total_time
time_per_frame = 1 / fps
print(f'Total time to infer all frames: {total_time:.3f}s')
print(f'Time per frame: {time_per_frame:.6f}s ({fps:.3f} FPS)')
Total time to infer all frames: 1.366s
Time per frame: 0.004744s (210.774 FPS)
# Set minimum detection threshold
min_thresh = .6
# Load video
video = cv2.VideoCapture(video_file)
# Get video parameters
frame_width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(video.get(cv2.CAP_PROP_FPS))
fourcc = int(video.get(cv2.CAP_PROP_FOURCC))
# Create folder and VideoWriter to save output video
Path('./output').mkdir(exist_ok=True)
output = cv2.VideoWriter('output/output.mp4', fourcc, fps, (frame_width, frame_height))
# Draw detection results on every frame of video and save as a new video file
while video.isOpened():
current_frame = int(video.get(cv2.CAP_PROP_POS_FRAMES))
ret, frame = video.read()
if not ret:
print('Video loaded!')
output.release()
video.release()
break
# Draw info at the top left such as current fps, the devices and the performance hint being used
cv2.putText(frame, f"fps {str(round(frame_fps[current_frame], 2))}", (5, 20), cv2.FONT_ITALIC, 0.6, (0, 0, 0), 1, cv2.LINE_AA)
cv2.putText(frame, f"device {device_name}", (5, 40), cv2.FONT_ITALIC, 0.6, (0, 0, 0), 1, cv2.LINE_AA)
cv2.putText(frame, f"hint {compiled_model.get_property('PERFORMANCE_HINT')}", (5, 60), cv2.FONT_ITALIC, 0.6, (0, 0, 0), 1, cv2.LINE_AA)
# prediction contains [image_id, label, conf, x_min, y_min, x_max, y_max] according to model
for prediction in np.squeeze(results[current_frame]):
if prediction[2] > min_thresh:
x_min = int(prediction[3] * frame_width)
y_min = int(prediction[4] * frame_height)
x_max = int(prediction[5] * frame_width)
y_max = int(prediction[6] * frame_height)
label = classes[int(prediction[1])]
# Draw a bounding box with its label above it
cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), (0, 255, 0), 1, cv2.LINE_AA)
cv2.putText(frame, label, (x_min, y_min - 10), cv2.FONT_ITALIC, 1, (255, 0, 0), 1, cv2.LINE_AA)
output.write(frame)
# Show output video file
# If the video does not display correctly inside the notebook, please open it with your favorite media player
Video("output/output.mp4", width=800, embed=True)
Video loaded!
結論¶
このチュートリアルでは、OpenVINO で 1 つ以上の GPU を使用し、そのプロパティーを確認し、さまざまなパフォーマンス・ヒントを通じてモデルのパフォーマンスを調整することがいかに容易であるかを示します。また、GPU を使用し、検出された境界ボックスを表示する基本的なオブジェクト検出アプリケーションのウォークスルーも提供します。
これらのトピックの詳細については、対応するドキュメントを参照してください。