TVM 架构设计

article/2025/10/3 19:27:59

TVM 架构设计

本文面向希望了解TVM体系结构和/或,积极参与项目开发的开发人员。

主要内容如下:

示例编译流程,概述了TVM将模型的高级概念,转换为可部署模块的步骤。

逻辑架构组件部分,描述逻辑组件。针对每个逻辑组件,按组件的名称进行组织。

可以随时查看,开发人员如何指导有用的开发技巧。

提供了架构的一些补充视图。检查一个单一的端到端编译流程,讨论关键的数据结构和转换。这个基于runtime的视图,主要关注运行编译器时,每个组件之间的交互。将检查代码库的逻辑模块及关系。设计了静态总体视图。

Example Compilation Flow

研究编译器中的一个示例编译流。下图显示了流程,在高层,包含几个步骤:

导入:前端组件将模型摄取到IRModule中,IRModule包含内部表示模型的函数集合。

转换:编译器将一个IRModule,转换成另一个功能上等价或近似等价的IRModule(如在量化的情况下)。许多转换都是独立于目标(后端)的。还允许target影响转换管道的配置。

目标转换:编译器将IRModule(codegen),转换为目标指定的可执行格式。目标转换结果封装为runtime.Module,可以在目标runtime环境中导出、加载和执行。

Runtime执行:用户将runtime.Module,在支持的runtime环境中,运行编译的函数。

在这里插入图片描述
Key data structures

设计和理解复杂系统的最佳方法之一,识别关键数据结构和操作(转换)这些数据结构的API。一旦确定了关键的数据结构,可以将系统分解成逻辑组件,这些组件要么定义关键数据结构的集合,要么定义数据结构之间的转换。

IRModule是整个堆栈中,使用的主要数据结构。IRModule(中间表示模块)包含一组函数。支持函数的两个主要变体。

relay::Function函数是高级函数程序表示。一个relay功能通常对应于端到端模型。可以查看relay功能作为一个计算图,对控制流、递归和复杂的数据结构,有额外的支持。

tir::PrimFunc是一个低级程序表示,包括循环嵌套选择、多维加载/存储、线程和向量/张量指令在内的元素。通常用来表示执行模型中(可能是融合)层的算子程序。

在编译过程中,一个relay函数,可以降为多个tir::PrimFunc函数,与一个调用这些tir::PrimFunc函数的顶层函数。

Transformations

已经介绍了关键的数据结构,谈谈转换。每种转换,都可以达到以下目的之一:

优化:将一个程序转换成一个等效的,可能更优化的版本。

降低:将程序转换为更接近目标的低级表示。

Relay/转换包含优化模型的过程集合。这些优化包括常见的程序优化,如常量折叠和死代码消除,及张量计算特定的过程,如布局转换和缩放因子折叠。

将端到端部的Relay(例如,MobileNet),端到端部的优化(融合操作),称这些函数段。这个过程帮助将原始问题,分为两个子问题:

每个子功能的编译和优化。

整体执行结构:需要对生成的子函数,执行一系列调用,执行整个模型。

使用低级tir,编译和优化每个子函数。对于特定的目标,可以直接进入目标转换阶段,使用外部代码生成器。

有几种不同的方法(在Relay/后端),处理对整个执行问题的调用。对于具有已知形状,没有控制流的简单模型,可以降低到将执行结构,存储在图形中的图形runtime。支持用于动态执行的虚拟机后端。调度支持提前编译,将高级执行结构,编译成可执行的和生成的原始函数。所有这些执行模式,都被一个统一的runtime.Module接口,将在后面部分讨论。

tir/转换包含tir级功能的转换过程。许多tir pass的目的是降低。有一些过程,可以将多维访问,变为一维指针访问,将内部函数扩展为特定于目标的内部函数,及修饰函数入口,满足runtime调用约定。有一些优化过程,如访问索引简化和死代码消除。

许多低级优化,可以在目标阶段由LLVM、cudac和其它目标编译器处理。将寄存器分配等低级优化,留给下游编译器,只关注那些没有覆盖的优化。

Search-space and Learning-based Transformations

到目前为止,所描述的转换过程是确定的和基于规则的。TVM堆栈的一个设计目标,支持针对不同硬件平台的高性能代码优化。需要研究尽可能多的优化选择,包括但不限于多维张量访问、循环平铺行为、特殊加速器内存层次结构和线程。

很难定义一个启发式,做出所有的选择。相反,将采取基于搜索和学习的方法。首先定义一组,可以转换程序的操作。示例操作包括循环转换、内联、矢量化。称这些动作为调度原语。调度原语的集合,定义了一个搜索空间,可以对程序进行优化。然后系统搜索不同的可能的调度序列,选择最佳的调度组合。搜索过程,通常由机器学习算法指导。

一旦搜索完成,就可以记录一个(可能是融合)算子的最佳调度序列。编译器就可以查找最佳调度序列,应用到程序中。值得注意的是,这个调度应用程序阶段与基于规则的转换完全相同,能够与传统过程,共享相同的接口约定。

使用基于搜索的优化方法,处理初始的tir函数生成问题。该模块的这一部分,称为AutoTVM(auto_scheduler)。随着继续开发TVM堆栈,将基于学习的转换扩展到更多领域。

Target Translation

目标转换阶段,将IRModule转换为相应的目标可执行格式。对于x86和ARM这样的后端,使用llvmirbuilder构建内存llvmir。

可以生成源代码级语言,如cudac和OpenCL。支持通过外部代码生成器,将Relay函数(子图),直接转换为特定目标。最后的代码生成阶段,尽可能轻量级。绝大多数转换和降低,都应该在目标转换阶段之前执行。

还提供了一个目标结构,指定编译目标。目标平移阶段之前的变换,受到目标的影响-例如,目标的向量长度,改变矢量化行为。

Runtime Execution

TVMruntime的主要目标,提供一个最小的API,用于加载和执行编译后的工件,语言包括Python、C++、Read、Go、java和JavaScript。下面的代码片段,在Python中,显示了这样一个示例:

import tvm

Example runtime execution program in python, with type annotated

mod: tvm.runtime.Module = tvm.runtime.load_module(“compiled_artifact.so”)

arr: tvm.runtime.NDArray = tvm.nd.array([1, 2, 3], ctx=tvm.gpu(0))

fun: tvm.runtime.PackedFunc = mod[“addone”]

fun(a)

print(a.asnumpy())

tvm.runtime.Module封装编译结果。一个runtime.Module包含按名称获取PackedFuncs的GetFunction方法。

tvm.runtime.PackedFunc,两个生成函数的类型删除函数接口。一个runtime.PackedFunc,可以使用以下类型获取参数和返回值:POD类型(int,float),string,runtime.PackedFunc, runtime.Module, runtime.NDArray,及其它子类runtime.Object。

tvm.runtime.Module,tvm.runtime.PackedFunc是模块化runtime的强大机制。例如,为了在CUDA上获得上述addone函数,可以使用LLVM生成主机端代码,计算启动参数(例如线程组的大小),然后从CUDA驱动程序API支持的CUDAModule,调用另一个PackedFunc。同样的机制,可以用于OpenCL内核。

上面的例子只处理一个简单的addone函数。下面的代码片段,给出了使用相同接口的,端到端模型执行示例:

import tvm

Example runtime execution program in python, with types annotated

factory: tvm.runtime.Module = tvm.runtime.load_module(“resnet18.so”)

Create a stateful graph execution module for resnet18 on gpu(0)

gmod: tvm.runtime.Module = factory"resnet18"

data: tvm.runtime.NDArray = get_input_data()

set input

gmod[“set_input”](0, data)

execute the model

gmod"run"

get the output

result = gmod"get_output".asnumpy()

主要的收获是runtime.Module 和 runtime.PackedFunc足以封装算子级程序(如addone)和端到端模型。

总结与讨论

总之,编译流程中的关键数据结构:

IRModule: contains relay.Function and tir.PrimFunc

runtime.Module: contains runtime.PackedFunc

编译的大部分内容,关键数据结构之间的转换。

Relay/转换和tir/转换,基于规则的确定性转换

auto_scheduler和autotvm包含基于搜索的转换

最后,编译流程示例,只是TVM堆栈的一个典型用例。将这些关键数据结构和转换,表示为Python和C++ API。可以像使用numpy一样使用TVM,只是感兴趣的数据结构,从numpy.ndarray 到 tvm.IRModule。以下是一些用例:

使用python API直接构造IRModule。

组成一组自定义的变换(例如自定义量化)。

使用TVM的PythonAPI直接操作IR。

Logical Architecture Components
在这里插入图片描述

上图显示了项目中的主要逻辑组件。有关组件及其关系的信息,请阅读以下部分。

tvm/支持

支持模块包含架构,设计最常用的实用程序,如通用的arena分配器、socket和日志记录。

tvm/runtime间

runtime是TVM堆栈的基础。提供了加载和执行已编译工件的机制。runtime定义了一组稳定的标准C API,与诸如Python和Rust这样的前端语言交互。

Object是TVM runtime中,除了runtime::PackedFunc之外,主要数据结构之一。一个引用计数的基类,具有类型索引,支持runtime类型检查和向下转换。目标系统允许开发人员向runtime,引入新的数据结构,例如数组、映射和新的IR数据结构。

除了部署用例,编译器本身,大量使用TVM的runtime机制。所有的IR数据结构,都是runtime::Object的子类,可以从Python前端,直接访问和操作。使用PackedFunc机制,向前端开发各种API。

对不同硬件后端的runtime支持,定义在runtime的子目录中(例如Runtime/opencl)。这些特定于硬件的runtime模块,定义了用于设备内存分配和设备函数序列化的API。

runtime/rpc实现了对PackedFunc的rpc支持。可以使用RPC机制,将交叉编译的库,发送到远程设备,对执行性能进行基准测试。Rpc架构设计,支持从通用的硬件后端收集数据,进行基于学习的优化。

TVM Runtime System
Debugger
Putting the VM in TVM: The Relay Virtual Machine
Introduction to Module Serialization
tvm/node

node模块在IR数据结构的runtime::Object的基础上,添加了其它特性。主要特性包括反射、序列化、结构等价和哈希。

有了node模块,就可以在Python中,直接访问TVM的IRNode的任何字段。

x = tvm.tir.Var(“x”, “int32”)

y = tvm.tir.Add(x, x)

a and b are fields of a tir.Add node

we can directly use the field name to access the IR structures

assert y.a == x

可以将任意IR节点序列化为JSON格式,将加载回。保存/存储和检查IR节点的能力,编译器更容易访问提供了基础。

tvm/ir

tvm/ir文件夹包含所有ir功能变体的,统一数据结构和接口。tvm/ir中的组件,由tvm/relay和tvm/tir共享,值得注意的是

IRModule
Type
PassContext and Pass
Op
功能的不同变体(例如,relay.Function and tir.PrimFunc),可以共存于一个IRModule中。虽然这些变体可能没有相同的内容表示形式,但使用相同的数据结构,表示类型。使用相同的数据结构,表示这些变量的函数(类型)标签。统一类型系统允许一个函数变量,调用另一个函数,只要明确定义了调用协议。这为未来的多功能变量优化,打开了大门。

提供了一个统一的PassContext,配置pass行为,提供了通用的复合过程,执行pass管道。下面的代码片段给出了PassContext配置的示例。

configure the behavior of the tir.UnrollLoop pass

with tvm.transform.PassContext(config={“tir.UnrollLoop”: { “auto_max_step”: 10 }}):

code affected by the pass context

Op是表示所有系统定义的,基本算子/内部函数的公共类。开发人员可以向系统注册新的算子,以及附加属性(例如,算子是否是基本元素级的)。

Pass Infrastructure
tvm/target

The target module contains all the code generators that translate an IRModule to a target runtime.Module. It also provides a common Target class that describes the target.

The compilation pipeline can be customized according to the target by querying the attribute information in the target and builtin information registered to each target id(cuda, opencl).

tvm/tir

TIR contains the definition of the low-level program representations. We use tir::PrimFunc to represent functions that can be transformed by TIR passes. Besides the IR data structures, the tir module also defines a set of builtin intrinsics and their attributes via the common Op registry, as well as transformation passes in tir/transform.

tvm/arith
This module is closely tied to the TIR. One of the key problems in the low-level code generation is the analysis of the indices’ arithmetic properties — the positiveness, variable bound, and the integer set that describes the iterator space. arith module provides a collection of tools that do (primarily integer) analysis. A TIR pass can use these analyses to simplify and optimize the code.

tvm/te
The name te stands for “tensor expression”. This is a domain-specific language module that allows us to construct tir::PrimFunc variants quickly by writing tensor expressions. Importantly, a tensor expression itself is not a self-contained function that can be stored into IRModule. Instead, it is a fragment of IR that we can stitch together to build an IRModule.

te/schedule provides a collection of scheduling primitives to control the function being generated. In the future, we might bring some of these scheduling components to the a tir::PrimFunc itself.

InferBound Pass
Hybrid Frontend Developer Guide
tvm/topi
While possible to construct operators directly via TIR or tensor expressions (TE) for each use case it is tedious to do so. topi (Tensor operator inventory) provides a set of pre-defined operators (in TE or TIR) defined by numpy and found in common deep learning workloads. We also provide a collection of common schedule templates to obtain performant implementations across different target platforms.

tvm/relay
Relay is the high-level functional IR used to represent full models. Various optimizations are defined in relay.transform. The Relay compiler defines multiple dialects, and each dialect is designed to support specific styles of optimization. Notable ones include QNN(for importing pre-quantized models), VM(for lowering to dynamic virtual machine), memory(for memory optimization).

Introduction to Relay IR
Relay Operator Strategy
Convert Layout Pass
tvm/autotvm
AutoTVM and AutoScheduler are both components which automate search based program optimization. This is rapidly evolving and primarily consists of:

Cost models and feature extraction.
A record format for storing program benchmark results for cost model construction.
A set of search policies over program transformations.
Automated program optimization is still an active research field. As a result, we have attempted to modularize the design so that researchers may quickly modify a component or apply their own algorithms via the Python bindings, and customize the search and plugin their algorithms from the Python binding.

Benchmark Performance Log Format
Frontends
Frontends ingest models from different frameworks into the TVM stack. tvm.relay.frontend is the namespace for model ingestion APIs.

TensorFlow Frontend
Security Guide


http://chatgpt.dhexx.cn/article/I7JrRwDY.shtml

相关文章

TVM的安装过程

最近在看深度学习编译器相关的工作,其中FlexTensor给我留下了比较深刻的印象,加上这项工作是开源的,所以想看看这份工作的源码。首先是怎么把工程跑起来,FlexTensor倚仗TVM做代码生成,所以首先得安装TVM。 首先给出官…

TVM系列 - 图优化 - 算子融合

TVM系列 - 图优化 - 算子融合 图优化综述 声明一下,本文所有的理解都是基于个人理解。 图优化算是一个推理框架前端比较成熟的操作了,一般来说,针对模型做图优化有两个目的(对于通用框架来说,就加速减少计算一个目的…

TVM 从入门到精通 | 安装 TVM (Part 2)

本文首发自:公众号 HyperAI超神经 内容一览:TVM 共有三种安装方法:从源码安装、使用 Docker 镜像安装和 NNPACK Contrib 安装。本文讲解如何通过 Docker 镜像 和 NNPACK Contrib 安装。 关键词:TVM Docker 基础教程 欢迎回…

初识 TVM

如有图像或公式显示错误,可以访问我的个人博客:https://www.wanglichun.tech/2019/11/15/tvm/ 笔者也是最近偶然的机会才开始接触TVM,使用过后发现,经过auto-tuning后的TVM模型在速度是竟然超过了TensorRT,并且笔者使用的是MXNet…

TVM(端到端深度学习编译器)简介

TVM-算子编译器前后端 前言TVM出现背景TVM是什么为什么用TVM,TVM解决了什么当前问题:TVM解决了 TVM如何解决具体实现手段如何设计搜索空间Search Space优化策略图优化 - 算子融合图优化 - Layout Transform张量优化 - 矩阵乘法 GEMM张量优化 - 调度算法张…

tvm学习笔记(五):tvm工作原理

一、总体流程: TVM的工作流程:首先,将网络表示成统一的表示形式(Intermediate Representation),并进行一些可重用的图优化;然后,利用不同的后端生成对应设备代码,如图1所…

TVM系列 - 量化

TVM系列 - 量化 TVM量化原理TVM量化现状TVM量化原理介绍TVM量化代码解析 TVM量化原理 关于量化的方式其实已经有足够的文章去了解目前最主流的两种:离线量化及训练时量化(大家应该能理解,其实就是伪量化),而tvm的作者…

TVM-初识TVM

目录 TVM简介那么TVM是什么?TVM做了哪些工作 TVM简介 随着深度学习的发展,深度学习的能力可以说是越来越强大,识别率节节攀升,与此同时,深度学习框架也变得越来越多,目前比较主流的深度学习框架包括&#…

【TVM系列二】TVM介绍

文章同步更新在公众号 AIPlayer,欢迎扫码关注,共同进步 目录 一、TVM的工作流程 1、整体流程 2、关键数据结构 3、Transformations 4、搜索空间和基于机器学习的转换 5、目标代码转化 二、逻辑架构组件 三、运行TVM实例 1、交叉编译runtime 2、…

TVM:简介

TVM:简介概述 Apache TVM 是一个用于 CPU、GPU 和机器学习加速器的开源机器学习编译器框架。它旨在使机器学习工程师能够在任何硬件后端上高效地优化和运行计算。本教程的目的是通过定义和演示关键概念,引导您了解 TVM 的所有主要功能。新用户应该能够从…

TVM简介

TVM与LLVM的架构非常相似。TVM针对不同的深度学习框架和硬件平台,实现了统一的软件栈,以尽可能高效的方式,将不同框架下的深度学习模型部署到硬件平台上。 如果从编译器的视角来看待如何解决这个问题,各种框架写的网络可以根据特…

TVM概述

TVM TVM是陈天奇领导的一个DL加速框架项目。它处于DL框架(如tensorflow、pytorch)和硬件后端(如CUDA、OpenCL)之间,兼顾了前者的易用性和后者的执行效率。 官网: https://tvm.apache.org/ 代码&#xf…

TVM[2] —— TVM简介和发展

TVM[2] —— TVM简介和发展 文章目录 TVM[2] —— TVM简介和发展1. TVM 简介1.1 是什么1.2 做什么1.3 基本步骤 2. TVM 的发展2.1 现状——四类抽象2.2 问题——两向boundary2.3 未来——从箭头到圈2.4 New Capabilities with Unity 下期预告:3. TVM 技术栈全解析&a…

TVM 学习指南(个人版)

文章目录 0x0. 前言0x1. 前端0x1.1 Tensor IR(TIR)0x1.2 了解tvm.ir基础设施0x1.3 Relay IR0x1.4 RelaxD0:数据流块作为第一优先级的构造D1:形状推导作为第一优先级的计算D1a: match_shapeD1b. 从符号整数元组构造ShapeShape传播的方法Implications for …

一步一步解读神经网络编译器TVM(一)——一个简单的例子

TOC 前言 这是一个TVM教程系列,计划从TVM的使用说明,再到TVM的内部源码?为大家大致解析一下TVM的基本工作原理。因为TVM的中文资料比较少,也希望贡献一下自己的力量,如有描述方面的错误,请及时指出。 那啥是TVM&am…

P29 JTextArea文本域

P29 JTextArea文本域 1.概述2.代码实例3.效果演示 系统:Win10 Java:1.8.0_333 IDEA:2020.3.4 Gitee:https://gitee.com/lijinjiang01/JavaSwing 1.概述 JTextArea:文本区域。JTextArea 用来编辑多行的文本。JTextArea…

java 刷新jtextarea_Java JTextArea不能实时刷新的问题

相信JTextArea用法都了解吧, JTextArea textArea new JTextArea();生成一块空白的区域, 我的需求就是点击发送邮件按钮后,后台的执行日志能输出到textArea中。 但是我点击发送按钮的时候,由于邮件的附件要好久,界面一…

java 获得jtextarea_java JTextArea中获得光标所在行数

[java]代码库import java.awt.BorderLayout; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextAre…

java jtextarea 事件_JTextArea事件处理

[java]代码库import java.awt.*; import java.awt.event.*; import javax.swing.*; /*由于会使用到复原和事件驱动功能,因此需要将javax.swing.undo和javax.swing.event两个package包含进来 */ import javax.swing.undo.*; import javax.swing.event.*; /*JTextArea…

JTextArea用法

JTextArea用法 import java.awt.Color; import java.awt.Font; import java.awt.Point; import java.awt.Dimension; import javax.swing.BorderFactory; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JFrame; import javax.swing.Imag…