カスタム OpenVINO 操作#

OpenVINO™ 拡張 API を使用すると、カスタム操作を登録して、OpenVINO™ がそのままではサポートしない操作を含むモデルをサポートできます。この機能は C++ でコードを記述する必要があるため、Python を使用してアプリケーションを開発している場合は、最初に C++ で実装された別の共有ライブラリーを構築し、add_extension API を使用して Python にロードする必要があります。ライブラリーの作成と使用方法の詳細については、拡張機能を使用したライブラリーの作成を参照してください。以降のセクションでは、操作クラスを実装する方法について説明します。

操作クラス#

カスタム操作を追加するには、ov::Op を拡張する新しいクラスを作成します。このクラスは、OpenVINO™ のすべてのグラフ操作の基本クラスである ov::Node から派生します。ov::Op を追加するには、次のファイルをインクルードします:

#include <openvino/op/op.hpp>

カスタム操作を追加するには、次のステップに従います:

  1. グラフユーザーに操作のタイプを識別し、動的なタイプの解決に役立つ NodeTypeInfo オブジェクトを定義する OPENVINO_OP マクロを追加します。操作のタイプ情報は現在、文字列の操作識別子と操作のバージョン文字列で構成されています。

  2. デフォルトのコンストラクターと、オプションで操作入力と属性をパラメーターとして受け取るコンストラクターを実装します。

  3. 形状推論メソッド validate_and_infer_types をオーバーライドします。このメソッドは、操作出力の形状と要素タイプを決定するために、グラフ操作中に複数回呼び出されます。入力形状と入力要素タイプにアクセスするには、ov::Nodeget_input_partial_shape() メソッドと get_input_element_type() メソッドを使用します。set_output_type を使用して、出力の推論された形状と要素タイプを設定します。

  4. clone_with_new_inputs メソッドをオーバーライドします。これにより、グラフ操作ルーチンがこの操作のコピーを作成し、最適化中にそれを別のノードに接続できるようになります。

  5. visit_attributes メソッドをオーバーライドして、操作属性のシリアル化と逆シリアル化を有効にします。AttributeVisitor がメソッドに渡され、実装ではタイプを認識する on_attribute ヘルパーを使用して操作内のすべての属性を調査できます。ヘルパーは、int64_tfloatboolvector などの標準 C++ 型、および既存の OpenVINO 定義タイプに対してすでに実装されています。

  6. evaluate をオーバーライドします。これは、定数ブランチにカスタム操作がある場合、一部のデバイスをこの実装にフォールバックし、定数の折りたたみを適用可能にするオプションのメソッドです。操作に evaluate メソッドが含まれている場合は、has_evaluate メソッドをオーバーライドする必要もあります。このメソッドを使用すると、操作の evaluate メソッドの可用性に関する情報を取得できます。

これに基づいて、操作クラスの宣言は次のようになります:

操作コンストラクター#

OpenVINO™ 操作には 2 つのコンストラクターが含まれています:

  • デフォルトのコンストラクター。属性なしで操作を作成できます

  • 指定された入力と属性を使用して操作を作成および検証するコンストラクター

Identity::Identity(const ov::Output<ov::Node>& arg) : Op({arg}) { 
    constructor_validate_and_infer_types(); 
}

validate_and_infer_types()#

ov::Node::validate_and_infer_types メソッドは、操作の属性を検証して出力形状を計算します。

void Identity::validate_and_infer_types() { 
    // 操作によって形状の終了要素タイプは変更されません 
    set_output_type(0, get_input_element_type(0), get_input_partial_shape(0)); 
}

clone_with_new_inputs()#

ov::Node::clone_with_new_inputs メソッドは、新しい入力を使用して操作のコピーを作成します。

std::shared_ptr<ov::Node> Identity::clone_with_new_inputs(const ov::OutputVector& new_args) const { 
    OPENVINO_ASSERT(new_args.size() == 1, "Incorrect number of new arguments"); 

    return std::make_shared<Identity>(new_args.at(0)); 
}

visit_attributes()#

ov::Node::visit_attributes メソッドを使用すると、すべての操作属性にアクセスできます。

bool Identity::visit_attributes(ov::AttributeVisitor& visitor) { 
    return true; 
}

evaluate() and has_evaluate()#

ov::Node::evaluate メソッドを使用すると、演算に定数フォールディングを適用できます。

bool Identity::evaluate(ov::TensorVector& outputs, 
const ov::TensorVector& inputs) 
    const { const 
    auto& in = inputs[0]; auto& out = outputs[0]; 
    if (out.data() == in.data()) // Nothing to do 
        return true; 
    out.set_shape(in.get_shape()); 
    memcpy(out.data(), in.data(), in.get_byte_size()); 
    return true; 
} 

bool Identity::has_evaluate() const { 
    return true; 
}