OpenVINO™ 可扩展性机制

英特尔® 发行版 OpenVINO™ 工具套件支持通过各种框架训练的神经网络模型。这些框架包括: TensorFlow、PyTorch、ONNX、PaddlePaddle、Apache MXNet、Caffe 和 Kaldi。支持的操作列表 对于每个支持的框架各有不同。要查看您的框架支持的操作,请参阅 支持的框架操作

OpenVINO 开箱即用产品无法识别列表中未包含的自定义操作。以下两种情况下可能需要自定义操作:

  1. OpenVINO 中尚不支持新框架操作或很少使用的常规框架操作。

  2. 模型作者使用框架扩展功能为某个特定的模型拓扑创建了新的用户操作。

导入支持此类操作的模型需要执行其他步骤。本指南介绍了用于在支持自定义操作的模型上进行推理的工作流程。这便于您为这些自定义操作插入自己的实现。OpenVINO 扩展性 API 支持为这些自定义操作添加支持以及对模型优化器和 OpenVINO 运行时使用一种实现。

定义新的自定义操作基本上包括两个部分:

  1. 在 OpenVINO™ 中定义操作语义,即说明应如何通过使用输入张量并生成输出张量来推理此操作的代码。将在单独的指南中说明如何为 GPUVPU 实现执行内核。

  2. 映射规则可帮助将框架操作表示形式转换为 OpenVINO™ 定义的操作语义。

进行推理需要第一部分。从原始框架模型格式成功导入包含此类操作的模型需要第二部分。可通过几个选项来实现各个部分。以下各部分将详细介绍这些内容。

定义操作语义

如果可以用数学方式将自定义操作表示为现有 OpenVINO™ 操作的组合,并且此类分解提供所需性能,则不需要实现低级操作。在确定此类分解的可行性时,请参阅最新的 OpenVINO 操作集。您可以使用现有操作的任何有效组合。本文档下一部分介绍映射自定义操作的方式。

如果由于包含的许多组成操作性能不佳,导致此类分解并不可行或似乎过于麻烦,则应实施一类新的自定义操作,如 自定义操作指南 中所述。

如果已经具有操作内核的通用 C++ 实现,则您可能优先实施自定义操作类。否则,应首先尝试分解操作(如上所述)。然后,在核实推理的正确性和获得的性能之后,您可以继续选择性地进行裸机 C++ 的实现。

从框架操作进行映射

根据用于导入的模型格式,将以不同方式实现自定义操作映射。您可以选择以下其中一项:

  1. 如果以 ONNX(包括从 ONNX 中的 Pytorch 导出的模型)或 PaddlePaddle 格式表示模型,则应使用 前端扩展 API 中的其中一个类。其中包含数个可与模型优化器中的 --extensions 选项结合使用,或当使用 read_model 方法直接将模型导入 OpenVINO 运行时期间在 C++ 中可用的类。Python API 也可用于运行时模型导入。

  2. 如果以 TensorFlow、Caffe、Kaldi 或 MXNet 格式表示模型,则应使用 模型优化器扩展 。这种方法仅可用于在模型优化器中转换模型。

同时存在两种方法,它们体现在两个方面:用于在 OpenVINO™ 中转换模型的两种不同类型的前端,即新前端(ONNX、PaddlePaddle)和旧前端(TensorFlow、Caffe、Kaldi 和 Apache MXNet)。模型优化器可以使用这两类前端,相比之下,直接通过 read_model 方法导入模型时只能使用新前端。请依照上文提及的相应指南之一,根据框架前端来实现映射。

如果正为 ONNX 或 PaddlePaddle 新前端实施扩展,并计划使用模型优化器中的 --extensions 选项来转换模型,则扩展应:

  1. 仅以 C++ 实现。

  2. 编译为单独的共享库(请参阅本指南后面的部分了解详细操作)。

模型优化器不支持以 Python API 编写的新前端扩展。

本指南的其余部分介绍用于新前端的前端扩展 API 的应用。

注册扩展

应对自定义操作类和新的映射前端扩展类对象进行注册,以使其在 OpenVINO™ 运行时可用。

Note

本文档基于 模板扩展 编写。该模板基于极简 Identity 操作(作为真实自定义操作的占位符)演示了扩展开发细节。您可以查看全面兼容的完整代码以了解其工作机制。

使用 ov::Core::add_extension 方法将扩展加载到 ov::Core 对象。此方法用于加载包含扩展的库,或从代码中加载扩展。

将扩展加载到核心

可以使用 ov::Core::add_extension 方法从代码中加载扩展:

ov::Core core;

// Use operation type to add operation extension
core.add_extension<TemplateExtension::Identity>();

// or you can add operation extension object which is equivalent form
core.add_extension(ov::OpExtension<TemplateExtension::Identity>());
# Not implemented

Identity 是在 自定义操作指南 中定义的自定义操作类。这足以支持读取 OpenVINO IR,后者使用由模型优化器发出的 Identity 扩展操作。要将原始模型直接加载到运行时,请添加一个映射扩展:

// Register mapping for new frontends: FW's "TemplateIdentity" operation to TemplateExtension::Identity
core.add_extension(ov::frontend::OpExtension<TemplateExtension::Identity>("Identity"));

// Register more sophisticated mapping with decomposition
core.add_extension(ov::frontend::ConversionExtension(
    "Identity",
    [](const ov::frontend::NodeContext& context) {
        // Arbitrary decomposition code here
        // Return a vector of operation outputs
        return ov::OutputVector{ std::make_shared<TemplateExtension::Identity>(context.get_input(0)) };
    }));
# Not implemented

使用 Python API 时,无法实现自定义 OpenVINO 操作。即使以 C++ 实施自定义 OpenVINO 操作并通过共享库将其加载到运行时,仍然无法添加引用此自定义操作的前端映射扩展。在此情况下,请使用 C++ 共享库方法实现操作语义和框架映射。

当仅使用来自标准 OpenVINO 操作集的操作时,Python 仍可用于映射和分解操作。

创建包含扩展的库

在以下情况下应创建扩展库:

  • 在模型优化器中通过自定义操作转换模型。

  • 在 Python 应用中通过自定义操作加载模型。这同时适用于框架模型和 OpenVINO IR。

  • 在支持从库中加载扩展的工具(例如 benchmark_app)中通过自定义操作加载模型。

例如,如果要创建扩展库以将扩展加载到模型优化器,请执行以下操作:

  1. 为扩展库创建切入点。OpenVINO 提供 OPENVINO_CREATE_EXTENSIONS() 宏,可用于为包含 OpenVINO 扩展的库定义入口点。 此宏应将所有 OpenVINO 扩展的矢量作为参数。

因此,扩展类的声明可能如下所示:

OPENVINO_CREATE_EXTENSIONS(
    std::vector<ov::Extension::Ptr>({

        // Register operation itself, required to be read from IR
        std::make_shared<ov::OpExtension<TemplateExtension::Identity>>(),

        // Register operaton mapping, required when converted from framework model format
        std::make_shared<ov::frontend::OpExtension<TemplateExtension::Identity>>()
    }));
  1. 要配置扩展库的构建过程,请使用以下 CMake 指令码:

set(CMAKE_CXX_STANDARD 11)

set(TARGET_NAME "openvino_template_extension")

find_package(OpenVINO REQUIRED)

set(SRC identity.cpp ov_extension.cpp)

add_library(${TARGET_NAME} MODULE ${SRC})

target_compile_definitions(${TARGET_NAME} PRIVATE IMPLEMENT_OPENVINO_EXTENSION_API)
target_link_libraries(${TARGET_NAME} PRIVATE openvino::runtime)

此 CMake 指令码将使用 find_package CMake 命令查找 OpenVINO。

  1. 要构建扩展库,请运行以下命令:

$ cd src/core/template_extension/new
$ mkdir build
$ cd build
$ cmake -DOpenVINO_DIR=<OpenVINO_DIR> ../
$ cmake --build .
  1. 构建完成后,您可以使用扩展库的路径将扩展加载到 OpenVINO 运行时:

ov::Core core;
// Load extensions library to ov::Core
core.add_extension("openvino_template_extension.so");
core = ov.Core()
# Load extensions library to ov.Core
core.add_extension("libopenvino_template_extension.so")