GPU デバイス

GPU プラグインは、インテル® GPU (統合およびディスクリートの両方) 上のディープ・ニューラル・ネットワークを推論する OpenCL* ベースのプラグインです。GPU プラグインの詳細については、以下を参照してください。

GPU プラグインは、インテル® ディストリビューションの OpenVINO™ ツールキットの一部です。システムを構成する方法の詳細については、GPU 構成を参照してください。

デバイスの命名規則

  • デバイスは GPU.X として列挙されます (X={0, 1, 2,...}) (インテル® GPU デバイスのみが考慮されます)。

  • システムに GPU が統合されている場合、id は常に 0 (GPU.0) になります。

  • 他の GPU の順序は事前定義されておらず、GPU ドライバーによって異なります。

  • GPUGPU.0 のエイリアスです。

  • システムに GPU が統合されていない場合、デバイスは 0 から列挙されます。

  • マルチタイル・アーキテクチャー (OpenCL* 用語で複数サブデバイス) を備えた GPU の場合、特定のタイルは GPU.X.Y として指定される場合があります。ここで、X,Y={0, 1, 2,...}, X は GPU デバイスの ID、Y はデバイス X 内のタイル ID です。

使用可能なデバイスのリストと関連付けられたインデックスを出力できる Hello デバイス照会 C++ サンプルを参照してください。以下に出力例を示します (デバイス名のみにカットされています)。

./hello_query_device
Available devices:
    Device: CPU
...
    Device: GPU.0
...
    Device: GPU.1

次に、デバイス名を ov::Core::compile_model() メソッドに渡し、以下で実行します。

    core = ov.Core()
    compiled_model = core.compile_model(model, "GPU")
    ov::Core core;
    auto model = core.read_model("model.xml");
    auto compiled_model = core.compile_model(model, "GPU");
    core = ov.Core()
    compiled_model = core.compile_model(model, "GPU.1")
    ov::Core core;
    auto model = core.read_model("model.xml");
    auto compiled_model = core.compile_model(model, "GPU.1");
    core = ov.Core()
    compiled_model = core.compile_model(model, "GPU.1.0")
    ov::Core core;
    auto model = core.read_model("model.xml");
    auto compiled_model = core.compile_model(model, "GPU.1.0");

サポートされる推論データタイプ

GPU プラグインは、内部プリミティブの推論精度として次のデータタイプをサポートします。

  • 浮動小数点データタイプ:

    • f32

    • f16

  • 量子化データタイプ:

    • u8

    • i8

    • u1

各プリミティブで選択される精度は、IR の演算精度、量子化プリミティブ、および利用可能なハードウェア機能によって異なります。u1/u8/i8 データタイプは量子化された操作にのみ使用され、量子化されていない操作には自動的に選択されません。量子化モデルを取得する方法の詳細については、モデル最適化ガイドを参照してください。

GPU プリミティブの浮動小数点精度は、f16 精度で実行される圧縮 f16 OpenVINO IR 形式を除き、OpenVINO IR の操作精度に基づいて選択されます。

新世代のインテル® Iris® Xe およびインテル® Xe MAX GPU は、i8/u8 モデルのパフォーマンスを加速します。i8/u8 精度のハードウェア・アクセラレーションは、旧世代のプラットフォームでは利用できない場合があります。その場合、モデルは IR から取得された浮動小数点精度で実行されます。u8/i8 アクセラレーションのハードウェア・サポートは、ov::device::capabilities プロパティーで照会できます。

Hello デバイス照会 C++ サンプルでは、検出されたすべてのデバイスでサポートされているデータタイプを出力できます。

サポートされる機能

GPU プラグインは次の機能をサポートしています。

マルチデバイス実行

システムに複数の GPU デバイス (統合インテル® GPU とディスクリートのインテル® GPU) がある場合、サポートされているモデルはすべての GPU デバイスで同時に実行できます。これは、ターゲットデバイスとして MULTI:GPU.1,GPU.0 を指定することで実行されます。

    core = ov.Core()
    compiled_model = core.compile_model(model, "MULTI:GPU.1,GPU.0")
    ov::Core core;
    auto model = core.read_model("model.xml");
    auto compiled_model = core.compile_model(model, "MULTI:GPU.1,GPU.0");

詳細については、マルチデバイス実行を参照してください。

自動バッチ処理

GPU プラグインは、現在のハードウェア・プラットフォームとモデルに関する ov::max_batch_size および ov::optimal_batch_size メトリックをレポートできます。したがって、ov::optimal_batch_size> 1 で、ov::hint::performance_mode(ov::hint::PerformanceMode::THROUGHPUT) が設定されていると、自動バッチ処理はデフォルトで有効になります。あるいは、BATCH:GPU などのデバイス概念によって明示的に有効にすることもできます。

    core = ov.Core()
    compiled_model = core.compile_model(model, "BATCH:GPU")
    ov::Core core;
    auto model = core.read_model("model.xml");
    auto compiled_model = core.compile_model(model, "BATCH:GPU");
    import openvino.properties.hint as hints

    core = ov.Core()
    compiled_model = core.compile_model(
        model,
        "GPU",
        {
            hints.performance_mode: hints.PerformanceMode.THROUGHPUT,
        },
    )
    ov::Core core;
    auto model = core.read_model("model.xml");
    auto compiled_model = core.compile_model(model, "GPU", ov::hint::performance_mode(ov::hint::PerformanceMode::THROUGHPUT));

詳細は自動バッチ処理をご覧ください。

マルチストリーム実行

n_streams > 1ov::num_streams(n_streams) または ov::hint::performance_mode(ov::hint::PerformanceMode::THROUGHPUT) プロパティーが GPU プラグインに設定されている場合、モデルに対して複数のストリームが作成されます。GPU プラグインの場合、各ストリームには固有のホストスレッドと関連する OpenCL* キューがあります。これは、受信した推論要求を同時に処理できることを意味します。

カーネルを異なるキューに同時にスケジュールしても、カーネルが GPU デバイス上で実際に並行して実行されるわけではありません。実際の動作はハードウェア・アーキテクチャーに依存するため、場合によっては実行が GPU ドライバー内でシリアル化されることがあります。

同じモデルを複数の推論で並行して実行する、モデルまたはアプリケーションの複数のインスタンスよりもマルチストリーム機能が優先されます。これは、GPU プラグインのストリーム実装がストリーム間での重み付けメモリー共有をサポートしており、他のアプローチと比較してメモリー消費量が少なくなる可能性があるためです。

詳細は最適化ガイドをご覧ください。

動的形状

現在、GPU の動的形状のサポートはプレビュー機能であり、次の制限があります。

  • 主に NLP モデル (自然言語処理) をサポートします。すべての操作と最適化パスが動的形状をサポートしているわけではありません。その結果、特定のモデルがクラッシュしたり、パフォーマンスが大幅に低下する可能性があります。

  • ホストデバイスのランタイム・オーバーヘッドは支配的であるため、動的形状は、個々の GPU では静的形状よりもパフォーマンスが低下する可能性があります。

  • 動的ランクはサポートされていません。

動的形状の概要と使用方法については、動的形状ガイドを参照してください。動的形状の実行をサポートするため、次の基本インフラが実装されています。

  • 実行時の形状推論: 実行時に新しい入力形状に対する各プリミティブの出力形状を推論します。

  • 形状に依存しないカーネル: 任意の形状を実行できる新しいカーネル。形状に依存しないカーネルが利用できない場合、実行時に形状ごとにカーネルがコンパイルされます。

  • 非同期カーネルコンパイル: 形状に依存しないカーネルが利用可能な場合でも、GPU プラグインは指定された形状に最適なカーネルをコンパイルし、将来の使用に備えてメモリー内キャッシュに保存します。

  • メモリー内キャッシュ: 実行時にコンパイルされたカーネルと、特定のカーネル用に並べ替えられた重みを保存します。

動的バッチ境界

境界付きバッチ動的形状の場合、内部動作が異なることに注意してください。これは、バッチ次元のみが動的であり、上限が固定されていることを意味します。

一般的な動的形状は単一のコンパイル済みモデル上で実行できますが、境界付き動的バッチの場合、GPU プラグインは、動的動作をエミュレートするため、2 の累乗に等しいバッチサイズで log2(N) 個の低レベル実行グラフを作成します (N - は上限です)。これはバッチ次元に限定されます)。その結果、特定のバッチサイズで受信した推論要求は、内部ネットワークの最小限の組み合わせによって実行されます。例えば、バッチサイズ 33 は、バッチサイズ 32 と 1 の 2 つの内部ネットワークで実行される場合があります。このアプローチはパフォーマンス上の理由から採用されていますが、内部ネットワークの複数のコピーにはより多くのメモリーが必要となり、コンパイル時間も長くなります。

以下のコードは、制限された動的バッチの例を示しています。

    core = ov.Core()

    C = 3
    H = 224
    W = 224

    model.reshape([(1, 10), C, H, W])

    # compile model and create infer request
    compiled_model = core.compile_model(model, "GPU")
    infer_request = compiled_model.create_infer_request()

    # create input tensor with specific batch size
    input_tensor = ov.Tensor(model.input().element_type, [2, C, H, W])

    # ...

    results = infer_request.infer([input_tensor])
// Read model
ov::Core core;
auto model = core.read_model("model.xml");

model->reshape({{ov::Dimension(1, 10), ov::Dimension(C), ov::Dimension(H), ov::Dimension(W)}});  // {1..10, C, H, W}

// compile model and create infer request
auto compiled_model = core.compile_model(model, "GPU");
auto infer_request = compiled_model.create_infer_request();
auto input = model->get_parameters().at(0);

// ...

// create input tensor with specific batch size
ov::Tensor input_tensor(input->get_element_type(), {2, C, H, W});

// ...

infer_request.set_tensor(input, input_tensor);
infer_request.infer();

動的形状のパフォーマンスとメモリー消費に関する注意事項

  • 推論中の余剰 CPU 使用率:

    • 新しい入力形状の形状推論

    • 最適なカーネルのため実行時にカーネルをコンパイル

    • 実行時に形状の融合が許可されていない場合の融合サブグラフの解除

  • メモリー内キャッシュのメモリー消費量の増加

    • 以前使用した形状の最適なカーネルと重みは、将来の使用に備えてメモリー内キャッシュに保存されます。

パフォーマンス向上のための推奨事項

  • 可能な限り静的な形状を使用

    • 静的モデルは、定数伝播、融合、並べ替えの最適化など、より積極的な最適化から恩恵を受けます。動的モデルと静的モデルで同じ形状を使用すると、動的モデルのパフォーマンスが悪化します。したがって、シナリオが許せば、動的モデルを静的モデルに再構成することを推奨します。

  • 可能な限り、境界のある動的形状を使用する

    • 現在の形状が以前の形状の最大値より大きい場合、GPU プラグインはメモリーを再割り当てする必要があり、追加のオーバーヘッドが発生します。

    • 境界のある動的形状を使用すると、オーバーヘッドを軽減するのに役立ちます。例えば、{ov::Dimension(-1), ov::Dimension(-1)} の代わりに {ov::Dimension(1, 10), ov::Dimension(1, 384)} を使用します。

    • 前述したように、制限された動的バッチは異なる方法で処理されることに注意してください。

  • OpenVINO model_cache などの永続キャッシュを使用して、実行時の再コンパイルのオーバーヘッドを削減します

    • GPU プラグインはメモリー内キャッシュをデプロイして、以前使用した形状のコンパイル済みカーネルを保存しますが、メモリー内キャッシュのサイズは有限です。したがって、OpenVINO model_cache などの永続キャッシュを使用することを推奨します。詳細は、モデルのキャッシュ概要を参照してください。

  • 推論シーケンスが長いほど、推論中に長いコンパイル時間を要するため、より良いスループットが得られます。

    • プリミティブに形状に依存しないカーネルがあり、現在の形状の静的形状カーネルがメモリー内キャッシュに存在しない場合は、形状に依存しないカーネルが使用されます。次に、前述したように、現在の形状に最適なカーネルも、将来の使用に備えて非同期で並行にコンパイルされます。アプリケーション・プロセスが CompiledModel オブジェクトを削除し、GPU プラグインが使用できなくなった場合、最適なカーネル生成のため待機しているコンパイルタスクはすべてキャンセルされます。ただし、アプリケーション・プロセスでキューに投入された非同期コンパイルタスクに十分な時間が与えられる場合、最適なカーネルが利用可能になりスループットが向上します。例えば、{[1, 1], ..., [1, 50], [1, 1], ... , [1, 50], [1, 1], ..., [1, 50], [1, 1], ..., [1, 50]} の 200 個の入力を実行すると、{[1, 1], ..., [1, 50], [1, 1], ... , [1,50]} の 100 個の入力を実行するよりも優れたスループットを達成できる可能性があります。

前処理の高速化

GPU プラグインには、次の追加の前処理オプションがあります。

  • ov::preprocess::InputTensorInfo::set_memory_type() 前処理メソッドの ov::intel_gpu::memory_type::surface および ov::intel_gpu::memory_type::buffer の値。これらの値は、適切なカーネルを生成するため、実行時に設定される入力 Tensor のタイプに関するヒントをプラグインに提供することを目的としています。

    model = get_model()
    using namespace ov::preprocess;
    auto p = PrePostProcessor(model);
    p.input().tensor().set_element_type(ov::element::u8)
                      .set_color_format(ov::preprocess::ColorFormat::NV12_TWO_PLANES, {"y", "uv"})
                      .set_memory_type(ov::intel_gpu::memory_type::surface);
    p.input().preprocess().convert_color(ov::preprocess::ColorFormat::BGR);
    p.input().model().set_layout("NCHW");
    auto model_with_preproc = p.build();

このような前処理により、GPU プラグインは、ov::intel_gpu::ocl::ClImage2DTensor (または派生) が ov::InferRequest::set_tensor()ov::InferRequest::set_tensors() メソッドを介して各 NV12 プレーンに渡されることを期待します。

詳細は、RemoteTensor API を参照してください。

詳細は前処理 API をご覧ください。

モデルのキャッシュ

モデルのキャッシュは、コンパイルされたモデルを自動的にエクスポートして再利用することで、アプリケーションの起動遅延を軽減します。GPU プラグインのキャッシュは、共通の OpenVINO ov::cache_dir プロパティーを介して有効にできます。

これは、ov::cache_dir オプションに関係なく、すべてのプラグイン固有のモデル変換が ov::Core::compile_model() 呼び出しごとに実行されることを意味します。それでも、カーネルのコンパイルはモデルの読み込みプロセスのボトルネックであるため、読み込み時間の大幅な短縮を達成できます。現在、GPU プラグインの実装は静的モデルのみを完全にサポートしています。動的モデルの場合、カーネルキャッシュが使用され、複数の ‘.cl_cache’ ファイルが ‘.blob’ ファイルとともに生成されます。

詳細は、モデルのキャッシュ概要を参照してください。

拡張性

このトピックに関する詳細は、GPU の拡張性を参照してください。

RemoteTensor API を介した GPU コンテキストとメモリー共有

この件に関する情報については、GPU プラグインの RemoteTensor API を参照してください。

サポートされるプロパティー

プラグインは、以下にリストされるプロパティーをサポートしています。

Read-write プロパティー

すべてのパラメーターは、ov::Core::compile_model() を呼び出す前に設定するか、追加の引数として ov::Core::compile_model() に渡す必要があります。

  • ov::cache_dir

  • ov::enable_profiling

  • ov::hint::model_priority

  • ov::hint::performance_mode

  • ov::hint::execution_mode

  • ov::hint::num_requests

  • ov::hint::inference_precision

  • ov::num_streams

  • ov::compilation_num_threads

  • ov::device::id

  • ov::intel_gpu::hint::host_task_priority

  • ov::intel_gpu::hint::queue_priority

  • ov::intel_gpu::hint::queue_throttle

  • ov::intel_gpu::enable_loop_unrolling

  • ov::intel_gpu::disable_winograd_convolution

Read 専用プロパティー

  • ov::supported_properties

  • ov::available_devices

  • ov::range_for_async_infer_requests

  • ov::range_for_streams

  • ov::optimal_batch_size

  • ov::max_batch_size

  • ov::device::full_name

  • ov::device::type

  • ov::device::gops

  • ov::device::capabilities

  • ov::intel_gpu::device_total_mem_size

  • ov::intel_gpu::uarch_version

  • ov::intel_gpu::execution_units_count

  • ov::intel_gpu::memory_statistics

制限事項

GPU プラグインが内部実装を使用して CPU 上でいくつかのプリミティブを暗黙的に実行することがあり、これにより CPU 使用率が増加する可能性があります。以下はそのような操作のリストです。

  • Proposal

  • NonMaxSuppression

  • DetectionOutput

操作の特定のパラメーターとハードウェア構成によって動作は異なります。

重要

微調整されたモデルで作業しているときに、winograd 畳み込みが選択されていると、推論が不正確になり、GPU でのパフォーマンスが低下することがあります。この問題は、winograd 畳み込みを無効にすることで解決できます。

compiled_model = core.compile_model(ov_model, device_name=devStr1, config={ "GPU_DISABLE_WINOGRAD_CONVOLUTION": True })

GPU パフォーマンスのチェックリスト: サマリー

OpenVINO は GPU 実装の OpenCL* カーネルに依存しているため、多くの OpenCL* ヒントが適用できます。

  • モデル変換 API は、FP32 よりも FP16 の推論精度を優先します。最適化オプションについては、最適化ガイドを参照してください。

  • 自動バッチ処理を使用して、個々の推論ジョブをグループ化することも有効です。

  • モデルのロード時間を最小限に抑えるためキャッシュを検討してください。

  • アプリケーションが GPU と並行して CPU 上で推論を実行する場合、またはホストに大きな負荷をかける場合は、OpenCL* ドライバーのスレッドが枯渇しないようにしてください。CPU 構成オプションを使用して、CPU プラグインの推論スレッド数を制限できます。

  • GPU のみのシナリオでも、GPU ドライバーは完了にスピンループによるポーリングを使用して CPU コアを占有する可能性があります。CPU 負荷が懸念される場合は、前述の queue_throttle プロパティーの利用を検討してください。このオプションでは推論レイテンシーが増加する可能性があるため、複数の GPU ストリームまたはスループットのパフォーマンス・ヒントと組み合わせることを検討してください。

  • メディア入力を操作する場合、GPU プラグインのリモート tensor API を考慮してください。