TVM简介

article/2025/10/3 20:22:49

TVM与LLVM的架构非常相似。TVM针对不同的深度学习框架和硬件平台,实现了统一的软件栈,以尽可能高效的方式,将不同框架下的深度学习模型部署到硬件平台上。

如果从编译器的视角来看待如何解决这个问题,各种框架写的网络可以根据特定的规则转化成某种统一的表示形式,在统一表示的基础上进行一些可重用的图优化,之后再用不同的后端来生成对应不同设备的代码,这就是目前各家都在尝试的设计思路了。

TensorFlow 的 XLA 会把高级代码抽象成 XLA HLO 的表示,做目标无关优化之后再用对应后端来生成更深一层的代码。

NVIDIA 的 TensorRT 的优化策略也是在图转化之后的统一表示上做,例如根据设定好的规则来做一些相邻计算单元的合并(Kernel Fusion)等等,但TensorRT最重要的Kernel部分的实现未开源。

TVM软件栈

TVM系统概览

工作流程

  1. 从已有的深度学习框架中获取一个模型并将此模型转换为计算图表示(深度学习框架的前端主要提供计算图表示以及自动梯度的功能);
  2. 图中 Section 3 使用一些方法优化当前的计算图得到优化后的计算图;
  3. 图中 Section 4 针对计算图中每个融合的算子生成有效的代码,生成过程中结合了张量表达式以及硬件优化原语,在算子级进行优化;
  4. 由于优化空间非常大,图中 Section 5 基于机器学习技术实现自动优化;
  5. 系统打包生成的代码到部署模块中。

Optimizing Computational Graphs(计算图级优化)

Optimizing Computational Graphs

Operator Fusion

Operator Fusion,可以将多个算子合并为一个kernel,以此节省存储中间结果的空间。例如,卷积、BN以及激活函数算子之间的融合,本质上是将三个算子的数学表达式代入并化简。

卷积: y c o n v = w ∗ x + b y_{conv} = w * x + b yconv=wx+b

BN: y b n = γ ∗ ( y c o n v − m e a n ) / v a r + β y_{bn} = \gamma * (y_{conv} - mean) / \sqrt{var} + \beta ybn=γ(yconvmean)/var +β

代入表达式,融合后的新卷积:
w ′ = γ / v a r ∗ w w^{'} = \gamma / \sqrt{var} * w w=γ/var w
b ′ = γ / v a r ∗ ( b − m e a n ) + β b^{'} = \gamma / \sqrt{var} * (b - mean) + \beta b=γ/var (bmean)+β

新的卷积就可以完成BN的工作。

Data Layout Transformation

不同的硬件设备可能具有截然不同的内存层次结构,因此,融合算子与优化数据布局的策略对于优化内存访问至关重要。

在目标硬件平台中,给定内存层次结构的约束,为每个操作符指定首选的数据布局,若数据布局不匹配,改变计算图中张量的数据布局方式以适应目标硬件设备并提升执行效率。

常见的速数据布局方式有行式存储和列式存储,实际场景下,会使用一个更加复杂的数据布局,以达到深度学习加速器的数据布局要求,更好地在目标硬件平台上执行。
数据布局转换
数据布局对性能影响巨大。

在 NCHW 的布局下,利用 SIMD 加速 3x3 的 depth-wise 卷积。首先,读取数据时,需要一次性读取四个 float 作为第一行的数据,后两行的读取也是相似的;此时,读取出的三行数据已经足够计算两列输出,即,可以复用部分数据;而后,为了提高数据复用,会再读取出第四行数据,一次计算两行两列,即,可以引入循环展开;然而,残留的 5~25 和 21~25 亮度眼边界无法利用 SIMD 计算,只能逐一循环读写完成计算;按照这样的方式,就可以相应完成后几个通道的计算。

但是, NCHW 布局下,无法充分利用 SIMD 进行加速,同时,实现优化分支越多,占用包大小也就越多。

数据布局转换
在 NC/4HW4 布局下,利用 SIMD 加速的情况。这里的 “C/4” 指的是按照 4 个通道对齐的方式重排数据。重排所有输入和权重数据后,每次 SIMD 读写都天然是 4 个通道的输入数据和 4 个通道的权重数据。这样,不论 kernel、stride、dilation 怎么变化,我们都可以简单地使用 for 循环和 SIMD 的一套通用优化完成卷积计算。既不会有边缘数据无法加速的问题,也不会对包大小造成影响。

Generating Tensor Operations(算子级优化)

Tensor Expression and Schedule Space

Tensor Expression 支持常见的算术运算和数学运算,并涵盖了常见的算子。该语言没有指定循环结构和许多其他执行细节,并且它提供了为各种后端添加硬件感知优化的灵活性。根据解耦计算和调度的原则,用调度表示从张量表达式到底层代码的映射。

Tensor Expression的最初的想法来源于 Halide,核心在于把代码的计算和调度分开。

为了在硬件后端实现高性能,必须支持足够的调度原语,以涵盖在不同硬件后端上的各种优化。

用于不同硬件后端的调度原语CPU调度GPU调度加速器调度
[Halide] Loop TransformationsYesYesYes
[Halide] Thread BindingYesYesYes
[Halide] Compute LocalityYesYesYes
[TVM] Special Memory ScopeNoYesYes
[TVM] TensorizationYesYesYes
[TVM] Latency HidingNoNoYes

例如一段最原始的 TVM 代码:

C = tvm.compute((n,), lambda i: A[i] + B[i])
s = tvm.create_schedule(C.op)

生成得到的 C 代码是:

for (int i = 0; i < n; ++i)
{C[i] = A[i] + B[i];
}

加上额外的调度控制:

C = tvm.compute((n,), lambda i: A[i] + B[i])
s = tvm.create_schedule(C.op)
xo, xi = s[C].split(s[C].axis[0], factor=32)

再生成的代码就变成了:

for (int xo = 0; xo < ceil(n / 32); ++xo)
{for (int xi = 0; xi < 32; ++xi){int i = xo * 32 + xi;if (i < n){C[i] = A[i] + B[i];}}
}

甚至于还可以支持绑定中间的 xo 和 xi 到特定的变量上:

C = tvm.compute((n,), lambda i: A[i] + B[i])
s = tvm.create_schedule(C.op)
xo, xi = s[C].split(s[C].axis[0], factor=32)
s[C].recorder(xi, xo)
s[C].bind(xo, tvm.thread_axis(“blockIdx.x”)
s[C].bind(xi, tvm.thread_axis(“threadIdx.x”)

这样出来的代码就可以用在 CUDA kernel 里面了:

int i = threadIdx.x * 32 + blockIdx.x;
if (i < n)
{C[i] = A[i] + B[i];
}

Nested Parallelism with Cooperation

现代 GPU 与专用加速器的内存可被多个计算核心共享,传统的无共享嵌套并行模式已不再是最优方法。为优化内核,在共享内存负载上的线程合作很有必要。

将Memory Scopes的概念引入调度空间,以便将计算阶段标记为 Shared。如果没有显式的Memory Scopes,自动范围推断将把计算阶段标记为 thread-local。

Tensorization

最新的硬件带来了超越向量运算的新指令集,如 TPU 中的 GEMM 算子和英伟达 Volta 架构中的 Tensor Core。因此在调度过程中,我们必须将计算分解为张量算术内联函数,而非标量或向量代码。

把矩阵-向量运算变成矩阵-矩阵运算,4x8 的矩阵乘上 8x1 的向量变成两个 4x4 和 4x1 的矩阵乘积。

Explicit Memory Latency Hiding

尽管在现代 CPU 与 GPU 上,同时拥有多线程和自动缓存管理的传统架构隐藏了延迟问题,但专用的加速器设计通常是采用精简控制流和将复杂性分配到编译器堆栈上面的方案。所以设计涉及到隐藏内存访问延迟的调度器时必须要非常仔细。

Automating Optimization

给定丰富的调度原语集,剩下的问题是为模型的每一层找到最优的算子实现。

系统需要选择调度优化,比如修改循环顺序或优化内存层次结构,以及特定调度的参数,比如平铺大小和循环展开因子。这些选择的组合为每个硬件后端都创建了一个很大的算子实现的搜索空间。

  1. Schedule Space Specification
  2. ML-Based Cost Model
  3. Schedule Exploration

TVM论文地址


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

相关文章

TVM概述

TVM TVM是陈天奇领导的一个DL加速框架项目。它处于DL框架&#xff08;如tensorflow、pytorch&#xff09;和硬件后端&#xff08;如CUDA、OpenCL&#xff09;之间&#xff0c;兼顾了前者的易用性和后者的执行效率。 官网&#xff1a; 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 下期预告&#xff1a;3. TVM 技术栈全解析&a…

TVM 学习指南(个人版)

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

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

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

P29 JTextArea文本域

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

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

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

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.*; /*由于会使用到复原和事件驱动功能&#xff0c;因此需要将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…

7、Java Swing JTextArea:文本域组件。 JScrollPane:滚动窗口

文本域与文本框的最大区别就是文本域允许用户输入多行文本信息。在 Swing 中使用 JTextArea 类实现一个文本域&#xff0c; JTextArea常用构造方法如下&#xff1a; JTextArea()----创建一个默认的文本域。JTextArea(int rows,int columns)----创建一个具有指定行数和列数的文…

Swing014——JTextArea:文本域组件

一、API简介 二、实例 package component;import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; impor…

AUC和ROC

AUC&#xff08;Area Under Curve&#xff09;被定义为ROC曲线下的面积&#xff0c;显然这个面积的数值不会大于1。又由于ROC曲线一般都处于yx这条直线的上方&#xff0c;所以AUC的取值范围在0.5和1之间。使用AUC值作为评价标准是因为很多时候ROC曲线并不能清晰的说明哪个分类器…

如何理解西瓜书中AUC和Lrank

首先AUC的定义就是ROC曲线的面积。这是西瓜书上给的定义式子 很容易看出是微积分的思想。 为什么说AUC越大ROC越理想呢&#xff1f;首先思考一下ROC的定义是什么&#xff0c;从定义入手一切都很简单。只不过是概念多了可能会把你给绕糊涂了。ROC曲线是这样画出来的&#xff1a…

模型评估指标AUC

模型评估指标AUC 、 AUC&#xff08;Area Under Curve&#xff09;被定义为ROC曲线下与坐标轴围成的面积&#xff0c;显然这个面积的数值不会大于1。又由于ROC曲线一般都处于yx这条直线的上方&#xff0c;所以AUC的取值范围在0.5和1之间。AUC越接近1.0&#xff0c;检测方法真实…

AUC与ROC

ROC曲线 含义 ROC曲线用来衡量阈值对模型的影响&#xff0c;在模型输入不变的情况下改变判断标准而获得不同的结果。是一条描述随着判断阈值变化而得到不同真阳率和假阳率结果的曲线。 例子 为了直观理解&#xff0c;我们做出以下三个假设&#xff1a; 假设1 感冒有三种…

ROC与AUC理解

ROC与AUC 简介ROC曲线ROC的动机ROC曲线特殊点 ROC曲线的绘制为什么使用ROCROC曲线使用多个实例概率/得分相同 AUC(Area Under ROC Curve)AUC判断分类器优劣的标准&#xff1a;AUC的物理意义损失公式AUC值的计算对于auc物理意义的理解&#xff1a; sklearn使用参考 简介 ROC:&a…

AUC的两种计算方式

1.什么是AUC&#xff1f; 推荐 搜索场景下的auc理解_凝眸伏笔的博客-CSDN博客_搜索auc 随机抽出一对样本&#xff08;一个正样本&#xff0c;一个负样本&#xff09;&#xff0c;然后用训练得到的分类器来对这两个样本进行预测&#xff0c;预测得到正样本的概率大于负样本概率…

AUC到底是什么?

前言 上一篇单值AUC计算优化里&#xff0c;提到了AUC&#xff0c;AUC的全名是Area Under Curve&#xff0c;就是ROC曲线下的面积&#xff0c;上一篇文中提到了AUC是评估模型整体排序能力的&#xff0c;但是具体是什么没有进行展开介绍&#xff0c;考虑到可能很多人对这么个玩意…

matlab计算auc,ROC和AUC介绍以及如何计算AUC

ROC(Receiver Operating Characteristic)曲线和AUC常被用来评价一个二值分类器(binary classifier)的优劣,对两者的简单介绍见这里。这篇博文简单介绍ROC和AUC的特点,以及更为深入地,讨论如何作出ROC曲线图以及计算AUC。 ROC曲线 需要提前说明的是,我们这里只讨论二值分类器…

加了权重样本的AUC如何计算

加了权重样本的AUC如何计算&#xff1f;对理解roc_auc_score函数里sample_weight参数以及xgb模型赋予样本权重再评估都有帮助哦&#xff5e; 一、 roc_auc_score函数中有个参数是sample_weight&#xff0c;可以给样本设置权重。一直不太理解加上weight怎么来计算AUC&#xff…