ヘテロジニアス実行

ヘテロジニアス実行により、複数のデバイス上で 1 つのモデルの推論を実行できます。以下を目的としています。

  • アクセラレーターの能力を利用してモデルの最も重い部分を処理し、CPU などのフォールバック・デバイスでサポートされていない操作を実行します。

  • 1 回の推論中に、利用可能なすべてのハードウェアをより効率良く利用します。

ヘテロジニアス・モードによる実行は、次の 2 つの独立したステップに分割できます。

  1. ハードウェア・アフィニティーを操作に設定します (ov::Core::query_model は Hetero デバイスによって内部的に使用されます)。

  2. モデルをヘテロジニアス・デバイスにコンパイルするには、モデルを分割し、(ov::device::priorities 経由で) 指定されたデバイス上でコンパイルし、ヘテロジニアス・モードで実行することを前提としています。モデルはアフィニティーに従ってサブグラフに分割され、同じアフィニティーを持つ接続された操作セットが専用のサブグラフになります。各サブグラフは専用デバイス上でコンパイルされ、複数の ov::CompiledModel オブジェクトが作成され、自動的に割り当てられた中間テンソルを介して接続されます。

この 2 つのステップは相互接続されておらず、アフィニティーは、手動モードまたは自動モードの 2 つの方法 (以下で説明) または組み合わせて使用する方法のいずれかに設定できます。

ヘテロデバイスの定義と構成

OpenVINO™ 命名規則に従って、Hetero 実行プラグインには "HETERO" というラベルが割り当てられます。追加のパラメーターなしで定義すると、デフォルトが使用されるか、次のセットアップ・オプションでさらに構成することができます。

パラメーター名 & C++ プロパティー

プロパティー値

説明

“MULTI_DEVICE_PRIORITIES”
ov::device::priorities

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

選択可能なデバイスをリスト。
デバイスシーケンスは上位から下位へ優先されます。

アフィニティーを割り当てる手動モードと自動モード

手動モード

"affinity" キーを指定した ov::Node::get_rt_info を使用して、モデル内のすべての操作に対してアフィニティーを明示的に設定することを前提としています。

特定の操作を特定のデバイスに割り当てる場合、そのデバイスが実際にその操作をサポートすることを確認してください ランダムに操作を選択し、アフィニティーを設定すると、モデルの精度が低下する可能性があります。これを回避するには、操作に組み込まれる定数操作など、関連する操作または操作のサブグラフを同じアフィニティーに設定するようにします。

    for op in model.get_ops():
        rt_info = op.get_rt_info()
        rt_info["affinity"] = "CPU"
for (auto && op : model->get_ops()) {
    op->get_rt_info()["affinity"] = "CPU";
}

自動モード

専用デバイス (GPUCPU など) からのサポートに従って、どの操作がどのデバイスに割り当てられるか自動的に決定し、モデル照会ステップはモデルのコンパイル中にヘテロデバイスによって暗黙的に呼び出されます。

自動モードでは、“greedy (貪欲)” な動作により、指定した優先順位 (例: ov::device::priorities("GPU,CPU")) に従って、特定のデバイス向けのすべての操作がそのデバイスに割り当てられます。このレイヤーの前後に他の特別な操作がなければ、特定の操作を推論できないなど、デバイスの特性は考慮されていません。デバイスプラグインが HETERO デバイスによって構築されたサブグラフトポロジーをサポートしていない場合、アフィニティーを手動で設定する必要があります。

    import openvino.device as device

    compiled_model = core.compile_model(model, device_name="HETERO:GPU,CPU")
    # device priorities via configuration property
    compiled_model = core.compile_model(
        model, device_name="HETERO", config={device.priorities: "GPU,CPU"}
    )
auto compiled_model = core.compile_model(model, "HETERO:GPU,CPU");
// or with ov::device::priorities with multiple args
compiled_model = core.compile_model(model, "HETERO", ov::device::priorities("GPU", "CPU"));
// or with ov::device::priorities with a single argument
compiled_model = core.compile_model(model, "HETERO", ov::device::priorities("GPU,CPU"));

手動モードと自動モードを組み合わせて使用

状況によっては、自動的に設定されたアフィニティーの手動調整を検討する必要があるかもしれません。通常、サブグラフの総数を最小限に抑えてメモリー転送を最適化します。これを行うには、自動的に割り当てられたアフィニティーを次のように “修正” する必要があります。

    # This example demonstrates how to perform default affinity initialization and then
    # correct affinity manually for some layers
    device = "HETERO:GPU,CPU"

    # query_model result contains mapping of supported operations to devices
    supported_ops = core.query_model(model, device)

    # update default affinities manually for specific operations
    supported_ops["operation_name"] = "CPU"

    # set affinities to a model
    for node in model.get_ops():
        affinity = supported_ops[node.get_friendly_name()]
        node.get_rt_info()["affinity"] = "CPU"

    # load model with manually set affinities
    compiled_model = core.compile_model(model, device)
// This example demonstrates how to perform default affinity initialization and then
// correct affinity manually for some layers
const std::string device = "HETERO:GPU,CPU";

// query_model result contains mapping of supported operations to devices
auto supported_ops = core.query_model(model, device);

// update default affinities manually for specific operations
supported_ops["operation_name"] = "CPU";

// set affinities to a model
for (auto&& node : model->get_ops()) {
    auto& affinity = supported_ops[node->get_friendly_name()];
    // Store affinity mapping using op runtime information
    node->get_rt_info()["affinity"] = affinity;
}

// load model with manually set affinities
auto compiled_model = core.compile_model(model, device);

重要なことは、モデル内の操作の "affinity" がすでに初期化されている場合、自動モードは機能しないことです。

フォールバック・デバイスを構成

各種ヘテロ実行デバイスに異なるデバイス固有の構成オプションを持たせたい場合は、特別なヘルパー・プロパティー ov::device::properties を使用できます。

    import openvino.hint as hints

    core.set_property("HETERO", {device.priorities: "GPU,CPU"})
    core.set_property("GPU", {properties.enable_profiling: True})
    core.set_property("CPU", {hints.inference_precision: ov.Type.f32})
    compiled_model = core.compile_model(model=model, device_name="HETERO")
auto compiled_model = core.compile_model(model, "HETERO",
    // GPU with fallback to CPU
    ov::device::priorities("GPU", "CPU"),
    // profiling is enabled only for GPU
    ov::device::properties("GPU", ov::enable_profiling(true)),
    // FP32 inference precision only for CPU
    ov::device::properties("CPU", ov::hint::inference_precision(ov::element::f32))
);

上の例では、GPU デバイスはプロファイル・データを有効にするように構成され、デフォルトの実行精度を使用しますが、CPU には fp32 で推論を実行する構成プロパティーがあります。

難解なトポロジーの処理

一部のトポロジーは一部のデバイスでのヘテロ実行に適しておらず、実行を妨げる場合もあります。例えば、プライマリー・デバイスでサポートされていないアクティベーション操作を持つモデルは、ヘテロジニアスによって複数のサブグラフのセットに分割され、最適な実行ができなくなります。ヘテロジニアス・モードでモデルの 1 つのサブグラフから別の部分にデータを送信するのに時間がかかる場合、ヘテロジニアス実行に適していない可能性があります。その場合、最も重い部分を手動で定義し、アフィニティーを設定して、1 回の推論中に頻繁にデータを送受信するのを避けることができます。

ヘテロジニアス実行のパフォーマンス分析

OPENVINO_HETERO_VISUALIZE 環境変数を有効にすると、デバイスごとの操作のアノテーションを含む GraphViz.dot ファイルをダンプできます。

ヘテロジニアス実行モードでは、次の 2 つのファイルを生成できます。

  • hetero_affinity_<model name>.dot - 操作ごとのアフィニティーのアノテーション。

  • hetero_subgraphs_<model name>.dot - グラフごとのアフィニティーのアノテーション。

GraphViz ユーティリティーまたはファイル・コンバーターを使用して画像を表示できます。Ubuntu オペレーティング・システムでは、xdot を使用できます。

  • sudo apt-get install xdot

  • xdot hetero_subgraphs.dot

パフォーマンス・データ (サンプル・アプリケーションでは -pc オプション) を使用して、各サブグラフのパフォーマンス・データを取得できます。

CPU へのフォールバックを使用して HDDL (サポートされなくなったデバイス) で実行されている Googlenet v1 の出力例を示します。

subgraph1: 1. input preprocessing (mean data/HDDL):EXECUTED layerType:          realTime: 129   cpu: 129  execType:
subgraph1: 2. input transfer to DDR:EXECUTED                layerType:          realTime: 201   cpu: 0    execType:
subgraph1: 3. HDDL execute time:EXECUTED                    layerType:          realTime: 3808  cpu: 0    execType:
subgraph1: 4. output transfer from DDR:EXECUTED             layerType:          realTime: 55    cpu: 0    execType:
subgraph1: 5. HDDL output postprocessing:EXECUTED           layerType:          realTime: 7     cpu: 7    execType:
subgraph1: 6. copy to IE blob:EXECUTED                      layerType:          realTime: 2     cpu: 2    execType:
subgraph2: out_prob:          NOT_RUN                       layerType: Output   realTime: 0     cpu: 0    execType: unknown
subgraph2: prob:              EXECUTED                      layerType: SoftMax  realTime: 10    cpu: 10   execType: ref
Total time: 4212 microseconds

サンプルの使い方

OpenVINO™ サンプルプログラムでは、-d オプションを使用してヘテロジニアス実行を行うことができます。

./hello_classification <path_to_model>/squeezenet1.1.xml <path_to_pictures>/picture.jpg HETERO:GPU,CPU

説明:

  • HETERO はヘテロジニアス実行の略称です

  • GPU,CPU は、GPU を優先し CPU にフォールバックするポリシーを指します。

3 つ以上のデバイスを指定することもできます: -d HETERO:GPU,CPU