针对自定义加速器进行编译 - 3.5 简体中文

Vitis AI 用户指南 (UG1414)

Document ID
UG1414
Release Date
2023-09-28
Version
3.5 简体中文

基于 XIR 的编译器可在独立于框架的 XIR 计算图的关联环境中工作,此 XIR 计算图是从深度学习框架生成的。解析器用于移除 CNN 模型中特定于框架的属性,并将这些模型转换为基于 XIR 的计算图。编译器可将计算图拆分为多个子计算图、利用异构最优化并为子计算图生成最优化的机器代码。

图 1. 编译流程

如果模型包含 DPU 不支持的运算,则创建的部分子计算图将被映射到 CPU。FPGA 非常强大,可支持您创建特定 IP 以加速这些运算,从而获得更好的端到端性能。为了使用基于 XIR 的工具链来支持对 IP 进行自定义加速,请使用流水线指定的插件来扩展 XIR 和编译器。

Plugin.hpp 中,已声明推断类插件。插件将在编译器启动前按序执行,以对计算图进行编译,供 DPU 使用。首先为每个运算符创建子级子计算图,且插件会选取要加速的运算符。它会将这些运算符合并为更大的子计算图、将其映射到自定义 IP,并为运行时 (VART::Runner) 附上必要的信息(例如,有关子计算图的指令)。

实现插件

  1. 实现 Plugin::partition()

    std::set<xir::Subgraph*> partition(xir::Graph* graph) 中,使用下列帮助函数选取所需运算,并将其合并为器件级子计算图。

    • xir::Subgraph* filter_by_name(xir::Graph* graph, const std::string& name) 用于返回含特定名称的子计算图
    • std::set<xir::Subgraph*> filter_by_type(xir::Graph* graph, const std::string& type) 用于返回特定类型的子计算图。
    • std::set<xir::Subgraph*> filter_by_template(xir::Graph* graph, xir::GraphTemplate* temp) 用于返回含特定结构的子计算图。
      图 2. 按模板筛选
    • std::set<xir::Subgraph*> filter(xir::Graph* graph, std::function<std::set<xir::Subgraph*>(std::set<xir::Subgraph*>)> func) 支持您按自定义函数对子计算图进行筛选。此方法可帮助您查找所有未编译的子计算图。

    如需合并子级子计算图,请使用 merge_subgraph() 帮助函数。但此函数只能合并相同级别的子计算图。如果子计算图列表无法合并为单一子计算图,那么帮助函数会尽可能将其合并。

  2. 请在 Plugin::partition() 函数中为所选取的子计算图指定名称、器件和运行器。
  3. 实现 Plugin::compile(xir::Subgraph*)。针对 partition() 函数返回的所有子计算图都会调用该函数。您可附加有关子计算图的信息以供运行时使用。

构建插件

创建外部 get_plugin() 函数,并将实现构建到共享库中。

extern "C" plugin* get_plugin() { return new YOURPLUGIN(); }

使用插件

您可在 vai_c 命令行选项中使用 --options '{"plugins": "plugin0,plugin1"}' 将插件库传递到编译器。执行插件时,编译器会打开库,并通过加载名为“get_plugin”的外部函数来创建插件实例。如果指定多个插件,则将按命令行选项定义的顺序来执行这些插件。DPU 和 CPU 编译将在所有插件都实现后再执行。