マルチデバイス実行

複数のデバイスで推論を実行するには、次の方法を選択できます。

  • 自動デバイス選択モードの CUMULATIVE_THROUGHPUT オプションを使用します。これにより、システム内で利用可能なデバイスを指定することなく使用できます。

  • マルチデバイス実行モードを使用します。これは、自動デバイス選択モードの CUMULATIVE_THROUGHPUT オプションと同じ動作を共有します。違いは、<デバイスリスト>または ov::device::priorities を明示的に設定する必要があることです。

MULTI の仕組み

マルチデバイス実行モード (略して MULTI) は、“仮想” または “プロキシー” デバイスとして機能し、 特定のタイプのハードウェアにバインドされない代わりに、利用可能な計算デバイスに特定の推論要求に割り当て、それらの推論要求が並行して実行されます。

マルチデバイス実行を使用することで得られるメリットは次のとおりです。

  • 複数のデバイスを同時に使用することでスループットが向上します。

  • 複数のデバイスが推論ワークロードを共有するため、パフォーマンスの安定性が向上します。

重要なことは、マルチデバイス・モードではアプリケーションのロジックが変更されないため、すべてのデバイスでモデルを明示的にコンパイルしたり、推論要求を作成してバランスをとる必要がないことです。一般的なデバイスを使用しているように見えますが、実際のハードウェアを内部で処理します。

このモードのパフォーマンスの向上は、複数デバイスを同時に使用することで得られることに注意してください。これは、デバイスをビジー状態に保つのに十分な推論要求をデバイスに供給する必要があることを意味します。そうしないと、MULTI 実行してもあまりメリットが得られません。

マルチデバイス・モードを使用

OpenVINO™ 命名規則に従って、マルチデバイス・モードには “MULTI” というラベルが割り当てられます。使用できる唯一の構成オプションは、デバイスの優先リストです。

プロパティー

プロパティー値

説明

<デバイスリスト>

MULTI: <デバイス名>
(スペースなしのカンマ区切り)
選択可能なデバイスを指定します。
デバイスシーケンスは上位から下位へ優先されます。
優先順位は文字列として直接設定できます。

ov::device::priorities

デバイス名
(スペースなしのカンマ区切り)

MULTI では、推論に使用できるデバイスを定義し、その優先順位を設定するデバイスリストを明示的に指定する必要があります。

OpenVINO™ ランタイムを使用すると、関数呼び出しで “GPU.0” のエイリアスとして “GPU” を使用できます。デバイスの列挙の詳細については、推論デバイスとモードを参照してください。

API では次のコマンドが受け入れられます。

    core = ov.Core()

    # Option 1
    # Pre-configure MULTI globally with explicitly defined devices,
    # and compile the model on MULTI using the newly specified default device list.
    core.set_property(
        device_name="MULTI", properties={device.priorities: "GPU,CPU"}
    )
    compiled_model = core.compile_model(model=model, device_name="MULTI")

    # Option 2
    # Specify the devices to be used by MULTI explicitly at compilation.
    # The following lines are equivalent:
    compiled_model = core.compile_model(model=model, device_name="MULTI:GPU,CPU")
    compiled_model = core.compile_model(
        model=model,
        device_name="MULTI",
        config={device.priorities: "GPU,CPU"},
    )
ov::Core core;

// Read a model in IR, PaddlePaddle, or ONNX format:
std::shared_ptr<ov::Model> model = core.read_model("sample.xml");

// Option 1
// Pre-configure MULTI globally with explicitly defined devices,
// and compile the model on MULTI using the newly specified default device list.
core.set_property("MULTI", ov::device::priorities("GPU.1,GPU.0")); 
ov::CompiledModel compileModel0 = core.compile_model(model, "MULTI");

// Option 2
// Specify the devices to be used by MULTI explicitly at compilation.
// The following lines are equivalent:
ov::CompiledModel compileModel1 = core.compile_model(model, "MULTI:GPU.1,GPU.0");
ov::CompiledModel compileModel2 = core.compile_model(model, "MULTI", ov::device::priorities("GPU.1,GPU.0"));

システムに存在するデバイスを確認するには、デバイス API を使用できます。使用方法については、デバイスのプロパティーと構成の照会を参照してください。

個々のデバイスの構成と最上位のマルチデバイスの作成

前述したように、MULTI を使用した推論の実行は、最上位に “MULTI” デバイスを作成する前に個別のデバイスを構成することによってセットアップできます。パフォーマンス上の理由を考慮する場合もあります。

    core = ov.Core()
    cpu_config = {streams.num : 4}
    gpu_config = {streams.num : 8}

    # When compiling the model on MULTI, configure CPU and GPU
    # (devices, priorities, and device configurations; gpu_config and cpu_config will load during compile_model() ):
    compiled_model = core.compile_model(
        model=model,
        device_name="MULTI:GPU,CPU",
        config={
            device.properties: {'CPU': cpu_config, 'GPU': gpu_config}
        }
    )

    # Optionally, query the optimal number of requests:
    nireq = compiled_model.get_property(
        properties.optimal_number_of_infer_requests
    )
ov::Core core;

// Read a network in IR, PaddlePaddle, or ONNX format:
std::shared_ptr<ov::Model> model = core.read_model("sample.xml");

// When compiling the model on MULTI, configure GPU and CPU 
// (devices, priorities, and device configurations):
ov::CompiledModel compileModel = core.compile_model(model, "MULTI",
    ov::device::priorities("GPU", "CPU"),
    ov::device::properties("GPU", gpu_config),
    ov::device::properties("CPU", cpu_config));

// Optionally, query the optimal number of requests:
uint32_t nireq = compileModel.get_property(ov::optimal_number_of_infer_requests);

個々のデバイス設定をすべて 1 つの構成ファイルに結合して MULTI で解析できるようにロードすることもできます。次のセクションの例を参照してください。

最適な推論要求数の照会

MULTI を使用する場合、含まれるデバイスを自身で集計する必要はなく、デバイスの構成プロパティーを使用して最適な要求数を直接照会できます。

ov::Core core;

// // Read a model and compile it on MULTI
ov::CompiledModel compileModel = core.compile_model("sample.xml", "MULTI:GPU,CPU");

// query the optimal number of requests
uint32_t nireq = compileModel.get_property(ov::optimal_number_of_infer_requests);

OpenVINO サンプルでのマルチデバイスの使用とパフォーマンス・ベンチマーク

マルチデバイス実行がどのように使用されているかを確認し、そのパフォーマンスをテストするには、要求や CPU スレッド数などを追加設定することなく、プラグインの最適なパフォーマンスを示す OpenVINO のベンチマーク・アプリケーションを参照してください。CPU + GPU のパフォーマンスを評価するコマンドを次に示します。

./benchmark_app –d MULTI:CPU,GPU –m <model> -i <input> -niter 1000

詳細については、ベンチマーク・ツールを参照してください。

リストされているデバイスの一部が FP16 IR をサポートしていない場合でも、FP32 に変換せずに FP16 IR を使い続けることができます。変換は自動的に行われます。

ov::optimal_number_of_infer_requests プロパティーのサポート、GPU ストリーム/スロットルの使用など、MULTI 向けに完全に最適化されたデモはまだありません。

マルチデバイス実行のパフォーマンスに関する考慮事項

MULTI 実行モードを使用して最高のパフォーマンスを得るには、いくつかの推奨事項を考慮する必要があります。

  • 通常、MULTI は、デバイス候補リストの先頭に最速のデバイスが指定されている場合に最高のパフォーマンスを発揮します。これは、要求レベルの並列処理が十分でない場合は (例えば、要求数がすべてのデバイスを飽和させるのに十分でない場合)、特に重要です。

  • スループット指向の実行モードと同様に、最適な推論要求の数を ov:compiled_model のインスタンスから直接照会することを強く推奨します。詳細については、前述の benchmark_app のコードを参照してください。

  • 特定デバイスの組み合わせ (CPU + GPU など) での実行は、特定のノブを使用するとパフォーマンスが向上します。詳細は、benchmark_app のコードを参照してください。具体的な例は、GPU ドライバーのポーリングを無効にすることです。これにより、デバイスからホストへの推論完了の低速通信のバランスをとるため、複数の GPU ストリームが必要になります。

  • MULTI ロジックは常に、デバイスに依存しない推論要求とユーザー側の推論要求、および実際にバックグラウンドでスケジュールされているデバイス固有の ‘ワーカー’ の要求間でデータコピーを節約しようとします。コピーの節約を容易にするために、要求を作成された順序で実行することを推奨します。

  • アクセラレーターのパフォーマンスは MULTI とうまく組み合わされますが、CPU と GPU の実行によって特定のパフォーマンスの問題が発生する可能性があります。これは、デバイスが電力や帯域幅などのリソースを共有していることが原因です。CPU 推論のため CPU スレッドを節約する GPU スロットリングのヒントを有効にするのは、この問題に対処する推奨されるソリューションです。