relay的流程;
pass功能;
pu上跑通单元测例 tests/python/relay/test_pass_inline.py, 明确pass原理;
能否使用inline针对一个网络生成一个call func ,这种方式能很好支持当前bangc优化和代码生成
Relay Build
-----------
Compile the graph to llvm target with given input specification.
relay的流程
1 从Tensorflow、PyTorch或Onnx等框架导入模型。导入层是 TVM 可以从其他框架(如 Tensorflow、PyTorch 或 ONNX)中提取模型的地方。TVM 为每个前端提供的支持水平会随着我们不断改进开源项目而变化。如果在将模型导入 TVM 时遇到问题,需要尝试将其转换为 ONNX。
2 翻译为Relay(TVM 的高级模型语言)。已导入 TVM 的模型用Relay表示。Relay是神经网络的函数语言和中间表示(IR)。它支持:
- 支持传统的数据流(DataFlow)风格编程。 支持functional-style scoping,并融合了编程语言领域的一些知识,带了一些新的特性(支持Let表达式,支持递归等等)
- 支持数据流风格和函数式风格混合编程。
- Relay不再使用计算图作为深度学习的描述语言,而是定义了一门专门的函数式编程语言,用来描述深度学习网络
Relay 应用图级优化来优化模型。
3 降低(Lower)至张量表达式(TE) 表示。降低是指将较高级别的表示转换为较低级别的表示。在应用高级优化之后,Relay 运行 FuseOps pass 将模型划分为许多小的子图,并将子图降低为 TE 表示。张量表达式 (TE) 是一种用于描述张量计算的领域特定语言。TE 还提供了一些调度原语来指定作低级循环优化,例如平铺、矢量化、并行化、展开和融合。为了帮助将 Relay 表示转换为 TE 表示的过程,TVM 包括一个张量算子库 (TOPI),它具有常用张量算子(例如,conv2d、转置)的预定义模板。
4 使用自动调整模块AutoTVM或AutoScheduler搜索最佳时间表。调度为 TE 中定义的运算符或子图指定作低级循环优化。自动调整模块搜索最佳时间表并将其与成本模型和设备上的测量值进行比较。
5 为模型编译选择最佳配置。 调音后, 自动调优模块生成 JSON 格式的调优记录。 这一步 为每个子图选择最佳时间表。
6 Lower to Tensor Intermediate Representation (TIR),TVM 的低级 中间表示。 选择最佳配置后 基于调整步骤,每个 TE 子图被降低到 TIR 并且是 通过低级优化传递进行优化。 接下来,优化的 TIR 是 降低到硬件平台的目标编译器。 这是生成优化模型的最终代码生成阶段 可以部署到生产中。 TVM 支持几种不同的 编译器后端包括:
- LLVM,它可以针对任意微处理器架构,包括 标准 x86 和 ARM 处理器、AMDGPU 和 NVPTX 代码生成,以及任何 LLVM支持的其他平台。
- 专门的编译器,比如 NVCC,NVIDIA 的编译器。
- 嵌入式和专用目标,通过 TVM 实现 自带 Codegen (BYOC) 框架。
7 编译成机器码。 在这个过程结束时, 特定于编译器的生成代码可以降级为机器代码。
这几行代码展示了TVM的编译流程,在这个编译流程里面不仅包含了基于Relay IR进行的优化策略来去除冗余的算子(也叫Pass)还包含了将Relay程序编译成特定后端(这里是llvm)可以执行的代码(codegen)。
target = "llvm"
target_host = "llvm"
dev = tvm.cpu(0)
with tvm.transform.PassContext(opt_level=3):
lib = relay.build(mod, target=target, target_host=target_host, params=params)
ralay位于TVM软件栈的位置:
Relay的函数式静态类型中间表示(IR)统一并概括了现有的DL IRs,以表示最先进的模型。
Relay’s functional, statically typed intermediate representation (IR) unifies and generalizes existing DL IRs to express state-of-the-art models.
TVM 可以将模型编译为可链接的对象模块,然后可以使用轻量级 TVM 运行时运行,该运行时提供 C API 以动态地 加载模型,以及其他语言的入口点,例如 Python 和 Rust。 TVM 还可以构建一个捆绑部署,其中运行时是 与模型结合在一个包中。
Relay简介
Relay的设计目标有以下几点:
Pass
Pass是TVM中基于Relay IR进行的一系列优化,类似于onnx-simplifier里面用到的onnxoptimizer,它可以简化计算图,去除一些冗余的算子,提高模型的推理效率。TVM将所有的pass都抽象到了tvm/include/tvm/ir/transform.h这个文件中,主要包含PassContext,PassInfo,Pass,以及Sequential。
这里的PassContext即是上面Python接口对应的C++实现,它包含了Pass执行依赖的一些参数如优化level,依赖的其它特定Pass以及设置不使用某种指定Pass等。PassInfo是用来记录Pass信息的类,包含Pass的opy_level,name,以及当前Pass需要哪些前置Pass。而Pass这个类就执行pass的主体,这是一个基类,每种Pass具体的C++代码实现在tvm/src/relay/transforms中,它们都会继承Pass这个基类。最后,Sequential是一个container,装载所有Pass。
需要说明一下,不是所有的Pass都定义在tvm/src/relay/transforms这里,比如下面的第一个例子就在tvm/src/relay/backend/vm这个文件夹里。
paper研读:
Relay: A High-Level Compiler for Deep Learning
The scenario above highlights the three-pronged extensibility challenge for DL IRs:
- Expressivity: It should be straightforward to write models involving control flow, first-class functions and data structures (e.g., trees, graphs, and lists).
- Composability: It should be straightforward to add and compose new optimizations with existing ones (e.g., quantization, operator fusion, and partial evaluation).
- Portability: It should be straightforward to add new hardware targets (e.g., TPU, Inferentia)
上面的场景突出了DL IRs面临的三个方面的可扩展性挑战:
1.表达能力:编写涉及控制流、一级函数和数据结构(如树、图和列表)的模型应该很简单。
2.可组合性:添加新的优化并与现有优化组合(例如量化、算子融合和部分评估)应该很简单。3.可移植性:应该很简单就能够添加新的硬件目标(例如TPU、推断)
Previous IRs have struggled to address these challenges, treating each component of the framework as a disconnected set of programming tasks. Operators are defined in low-level
languages like C++, connected by a dataflow graph, and then scripted in a host language like Python. Consequently, program analyses cannot cross language boundaries between
components, inhibiting optimization and deployment. Learning from previous IRs, we have designed Relay, which features a principled approach to addressing extensibility and
improves expressivity, composability, and portability over previous frameworks.
We make the following contributions:
• The Relay IR, a tensor-oriented, statically typed functional IR, which we describe in Section 3. Relay’s design is motivated by the insight that functional IRs, used by languages
from the ML family can be readily adapted to support DL.With its expressive semantics, including control flow, data structures, and first-class functions, Relay can represent entire state-of-the-art models.
• The insight that common features in ML frameworks, such as quantization and shape inference, can be reframed as standard compiler passes. By using this reframing we can
tap into decades of traditional compilers research to design composable optimization passes.
• A platform-agnostic representation of operators and domain specific optimizations which work in concert to provide portability across hardware backends.
之前的IRs一直在努力应对这些挑战,将框架的每个组成部分视为一个不相连的编程任务集。操作符是用C等低级语言定义的,通过数据流图连接,然后用Python等宿主语言编写脚本。因此,程序分析不能跨越组件之间的语言边界,从而抑制优化和部署。从以前的IRs中学习,我们设计了Relay,它采用了一种有原则的方法来解决可扩展性问题,并与以前的框架相比提高了表达性、可组合性和可移植性。我们做出以下贡献:<