【TVM教程】理解 TensorIR 抽象

深度学习编译器TVM核心:TensorIR创建与优化实战指南 在深度学习模型部署中,高层框架描述与底层硬件高效执行之间存在显著鸿沟,这催生了深度学习编译器的需求。其核心原理在于通过中间表示(IR)将计算图转换为可优化、可移植的底层代码,从而提升硬件利用率与执行效率。TensorIR作为TVM(Tensor Virtual Machine)的关键抽象层,正是这一技术的具体实现,它通过Block和PrimFunc等结构精确描述张量计算,支持循环变换、内存布局优化等底层调度。其技术价值在于赋予开发者对计算内核的精细控制能力,实现跨CPU、GPU等硬件的性能优化。在模型部署、 阅读详情

TVM 现已更新到 0.21.0 版本,TVM 中文文档已经和新版本对齐。

Apache TVM 是一个深度的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。

在线运行 TVM 学习教程→https://go.hyper.ai/PEh1Q

TensorIR 是 Apache TVM 中的张量程序抽象,它是标准的机器学习编译框架之一。张量程序抽象的主要目标是描述循环及其相关的硬件加速选项,包括线程、应用专用硬件指令和内存访问。

为了帮助我们解释,我们使用以下的张量计算序列作为激励示例。具体来说,对于两个 128×128 的矩阵 A 和 B,我们执行以下两个步骤的张量计算。

Y_{i, j} &= \sum_k A_{i, k} \times B_{k, j} \
C_{i, j} &= \mathbb{relu}(Y_{i, j}) = \mathbb{max}(Y_{i, j}, 0)

​上述计算类似于神经网络中常见的典型原始张量函数,即带有 ReLU 激活函数的线性层。我们使用 TensorIR 来表示上述计算,如下所示。

在我们调用 TensorIR 之前,让我们先用原生 Python 代码和 NumPy 来展示计算:

def lnumpy_mm_relu(A: np.ndarray, B: np.ndarray, C: np.ndarray):
    Y = np.empty((128, 128), dtype="float32")
    for i in range(128):
        for j in range(128):
            for k in range(128):
                if k == 0:
                    Y[i, j] = 0
                Y[i, j] = Y[i, j] + A[i, k] * B[k, j]
    for i in range(128):
        for j in range(128):
            C[i, j] = max(Y[i, j], 0)

在理解了底层 NumPy 示例后,我们现在准备引入 TensorIR。下面的代码块展示了 mm_relu 的 TensorIR 实现。该代码使用一种叫做 TVMScript 的语言编写,这是一个嵌入在 Python AST 中的领域特定语言。

@tvm.script.ir_module
class MyModule:
    @T.prim_func
    def mm_relu(A: T.Buffer((128, 128), "float32"),
                B: T.Buffer((128, 128), "float32"),
                C: T.Buffer((128, 128), "float32")):
        Y = T.alloc_buffer((128, 128), dtype="float32")
        for i, j, k in T.grid(128, 128, 128):
            with T.block("Y"):
                vi = T.axis.spatial(128, i)
                vj = T.axis.spatial(128, j)
                vk = T.axis.reduce(128, k)
                with T.init():
                    Y[vi, vj] = T.float32(0)
                Y[vi, vj] = Y[vi, vj] + A[vi, vk] * B[vk, vj]
        for i, j in T.grid(128, 128):
            with T.block("C"):
                vi = T.axis.spatial(128, i)
                vj = T.axis.spatial(128, j)
                C[vi, vj] = T.max(Y[vi, vj], T.float32(0))

接下来,让我们分析一下上述 TensorIR 程序中的元素。

函数参数与缓冲区​

函数参数与 NumPy 函数中的参数相对应。

# TensorIR
def mm_relu(A: T.Buffer((128, 128), "float32"),
            B: T.Buffer((128, 128), "float32"),
            C: T.Buffer((128, 128), "float32")):
    ...
# NumPy
def lnumpy_mm_relu(A: np.ndarray, B: np.ndarray, C: np.ndarray):
    ...

在这里,A、B 和 C 使用了名为 T.Buffer 的类型,该类型的形状参数是 (128, 128),数据类型是 float32。这些附加信息帮助可能的 MLC 进程生成专门化的代码,针对特定的形状和数据类型进行优化。

同样,TensorIR 还使用缓冲区类型来分配中间结果。

# TensorIR
Y = T.alloc_buffer((128, 128), dtype="float32")
# NumPy
Y = np.empty((128, 128), dtype="float32")

循环迭代​

循环迭代也有直接的对应关系。

T.grid 是 TensorIR 中的一种语法,允许我们写出多个嵌套的迭代器。

# TensorIR with `T.grid`
for i, j, k in T.grid(128, 128, 128):
    ...
# TensorIR with `range`
for i in range(128):
    for j in range(128):
        for k in range(128):
            ...
# NumPy
for i in range(128):
    for j in range(128):
        for k in range(128):
            ...

计算块​

一个重要的区别在于计算语句:TensorIR 引入了一个额外的构造,称为 T.block。

# TensorIR
with T.block("Y"):
    vi = T.axis.spatial(128, i)
    vj = T.axis.spatial(128, j)
    vk = T.axis.reduce(128, k)
    with T.init():
        Y[vi, vj] = T.float32(0)
    Y[vi, vj] = Y[vi, vj] + A[vi, vk] * B[vk, vj]
# NumPy
vi, vj, vk = i, j, k
if vk == 0:
    Y[vi, vj] = 0
Y[vi, vj] = Y[vi, vj] + A[vi, vk] * B[vk, vj]

一个块代表 TensorIR 中的一个基本计算单元。重要的是,块包含的信息比标准 NumPy 代码要多。它包含了一组块轴 vi, vj, vk),以及围绕这些轴的计算。

vi = T.axis.spatial(128, i)
vj = T.axis.spatial(128, j)
vk = T.axis.reduce(128, k)

以上三行声明了以下语法中关于块轴的关键属性。

[block_axis] = T.axis.[axis_type]([axis_range], [mapped_value])

这三行表达了以下内容:

  • 它们指定了 vi、vj、vk(在这个例子中,绑定到 i、j、k)。
  • 它们声明了 vi、vj、vk 的原始范围(例如,T.axis.spatial(128, i) 中的 128)。
  • 它们宣布了迭代器的属性(空间轴、归约轴)。

块轴属性​

让我们深入探讨块轴的属性。这些属性表示轴与当前计算的关系。块包含三个轴 vi、vj 和 vk,同时块读取缓冲区 A[vi, vk] 和 B[vk, vj],并写入缓冲区 Y[vi, vj]。严格来说,块对 Y 进行了(归约)更新,我们暂时将其称为写入,因为我们不需要从另一个块获取 Y 的值。

重要的是,对于固定的 vi 和 vj 值,计算块会在 Y 的空间位置生成一个点值(Y[vi, vj]),该值独立于 Y 中其他位置(具有不同的 vi 和 vj 值)。我们可以将 vi 和 vj 称为空间轴,因为它们直接对应于块写入缓冲区空间区域的起始位置。参与归约的轴(vk)被指定为归约轴。

为什么在块中有额外的信息​

一个重要的观察是,额外的信息(块轴的范围及其属性)使得块在执行迭代时是自包含的,独立于外部的 i, j, k 循环。

块轴信息还提供了额外的属性,帮助我们验证外部循环在执行计算时的正确性。例如,下面的代码块会因为循环期望一个大小为 128 的迭代器,但我们只将其绑定到一个大小为 127 的 for 循环,因此会导致错误。

# 错误的程序,由于循环和块迭代不匹配
for i in range(127):
    with T.block("C"):
        vi = T.axis.spatial(128, i)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
        这里出现错误是因为迭代器大小不匹配
        ...

块轴绑定的语法​

在每个块轴直接映射到外部循环迭代器的情况下,我们可以使用 T.axis.remap 在一行中声明块轴。

# SSR 表示每个轴的属性分别为 "spatial", "spatial", "reduce"
vi, vj, vk = T.axis.remap("SSR", [i, j, k])

这等价于:

vi = T.axis.spatial(range_of_i, i)
vj = T.axis.spatial(range_of_j, j)
vk = T.axis.reduce (range_of_k, k)

因此,我们还可以按以下方式编写程序:

@tvm.script.ir_module
class MyModuleWithAxisRemapSugar:
    @T.prim_func
    def mm_relu(A: T.Buffer((128, 128), "float32"),
                B: T.Buffer((128, 128), "float32"),
                C: T.Buffer((128, 128), "float32")):
        Y = T.alloc_buffer((128, 128), dtype="float32")
        for i, j, k in T.grid(128, 128, 128):
            with T.block("Y"):
                vi, vj, vk = T.axis.remap("SSR", [i, j, k])
                with T.init():
                    Y[vi, vj] = T.float32(0)
                Y[vi, vj] = Y[vi, vj] + A[vi, vk] * B[vk, vj]
        for i, j in T.grid(128, 128):
            with T.block("C"):
                vi, vj = T.axis.remap("SS", [i, j])
                C[vi, vj] = T.max(Y[vi, vj], T.float32(
从零手动创建TensorIR:深入TVM底层编译原理与实践 中间表示(IR)是编译器将高级计算描述转换为底层硬件指令的核心抽象层,它通过结构化地表达计算逻辑、数据流和内存访问模式,为自动化优化提供了基础。其原理在于将计算图分解为更细粒度的操作与循环结构,从而显式地暴露并行性和数据局部性。这一技术价值在于实现了计算描述与硬件优化的解耦,使得同一份计算逻辑能够针对不同硬件后端(如CPU、GPU)进行定制化性能调优。在深度学习模型部署与高性能计算领域,IR的应用场景广泛,尤其对于需要极致性能的算子融合、循环变换和内存层次优化至关重要。本文以TVM的TensorIR为例,通 阅读详情

相关推荐

TVM TensorIR实战:从零手写中间表示与调度优化

在深度学习编译器的技术栈中,中间表示(IR)是连接高层计算图与底层硬件指令的关键桥梁。TVM作为业界主流的编译器框架,其新一代TensorIR摒弃了传统表达式自动推导的间接层,以显式描述循环、块和缓冲区的方式,赋予开发者对算子实现细节的绝对控制权。这种设计将计算定义与调度策略彻底解耦,使得面向不同硬件架构的循环分块、向量化、并行化及存储映射等优化操作变得可预测、可复现。深度学习模型的高效部署往往依赖于对核心算子的极致打磨,而TensorIR正是算子开发与性能调优的底层语言。本文通过向量加法与矩阵乘法的完整实

weixin_34246529的博客 112

深入理解TVM中的TensorIR抽象

深入理解TVM中的TensorIR抽象 【免费下载链接】tvm Open deep learning compiler stack for cpu, gpu and specialized accelerators 项目地址: h...

gitblog_00289的博客 406

逆变器专题(3)-锁相环-PLL

锁相环作为并网逆变器的第一道门户,其锁相的精度将直接影响逆变器是否并网成功,若锁相精度较差,则会直接导致系统的功率因数下降,产生无功等等。在有关文献中指出,提高PLL带宽可以准确且快速进行锁相,而当电网电压含有谐波时,可适当降低带宽抵制谐波的干扰。成为变化量,而如果两者旋转速度达到一致时,所在的交轴分量。ki很大,即带宽很大时,稳定裕度不够,锁相环锁不住。为交流量,当频率锁定而相位没有锁定时,即。,即控制环前馈,可实现将锁相速度的加快。控为0,则可实现系统完美锁相。mod,取余,可减少存储空间。

cyc19980105的博客 6183

Apache TVM TensorIR 抽象入门:理解 Primitive Tensor Function、Block 与迭代注解

TensorIR 是 Apache TVM 编译器栈中的核心张量程序抽象,用于表示与优化"原始张量函数"(primitive tensor function)。本文以官方文档 [abstraction.rst](https://link.gitcode.com/i/25c5a8d2f3eeab0b177a17aa82681b08) 为主体,结合仓库内 [learning.rst](https://

gitblog_00922的博客 999

maxwell 平面变压器仿真(一)

在学习开关电源设计的时候,我们难免要设计变压器,采用有限元仿真软件MAXWELL 可以帮助我们确定变压器的励磁电感,漏感等参数。对于我们的理论分析大有裨益。但是苦于这破软件的教程真的是相当的零散,我相信大家用起来也总是苦于没有系统的教程指导,撰写本文的目的有两个,一个是记录自己使用的一些问题,一个是给大家提供一个可以参考的文档。

qq_45405656的博客 8246

Spacedesk保姆级教程:用旧平板给Windows电脑当副屏,从安装到避坑一步到位

本文提供Spacedesk保姆级教程,教你如何将旧平板变成Windows电脑的副屏,从软件安装到网络配置、显示优化及声音交互,一步步避开常见陷阱。通过WiFi实现扩展屏功能,支持4K分辨率和60Hz刷新率,让闲置设备焕发新生。

weixin_42524945的博客 1万+

深入理解 TVM TensorIR 抽象:从 NumPy 到 TVMScript 的张量程序建模

TensorIR 是 Apache TVM 中用于描述与优化张量程序(tensor program)的核心抽象,其目标是以可调度、可变换的形式刻画循环结构以及与之相关的硬件加速手段——包括线程绑定、专用硬件指令(如 Tensor Core)与内存访问方式。本文以神经网络中最常见的「矩阵乘法 + ReLU 激活」算子(`mm_relu`)为贯穿案例,从等价的 NumPy 实现出发,逐步拆解 Tens

gitblog_00883的博客 433

从工具选型到落地实践:吃透 SAP Fiori Launchpad 配置工具体系

摘要: SAP Fiori Launchpad配置远非简单添加应用和分配角色,涉及技术目录、业务目录、Spaces/Pages等多层管理。官方推荐新工具分工:技术目录用FLPAM维护应用定义,业务目录用FLPCM编排应用组合,Spaces/Pages优化用户体验布局,而传统Groups模式已被标记弃用。这种分层治理模式(定义层-编排层-展示层)能有效解决传输混乱、升级兼容性问题,尤其适合大规模项目实施。关键在于区分技术配置与业务呈现,避免将所有功能堆砌在单一旧工具中。(149字)

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 103

【TVM教程】TensorIR 创建

TVM 现已更新到 0.21.0 版本,TVM 中文文档已经和新版本对齐。 Apache TVM 是一个深度的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。

HyperAI超神经 384

C/C++ LMS算法详解及源码

LMS(Least Mean Squares)算法是一种自适应滤波器算法,用于估计一个系统的参数,以使输出信号与期望信号之间的均方误差最小化。LMS算法通过使用梯度下降的方法,逐步调整自适应滤波器的权值来优化滤波效果。

希望我的博客,能帮上你解决学习中工作中所遇到的问题 3276

YOLOv8改进,YOLOv8主干网络替换为ShuffleNetV2

ShuffleNet V2的设计原则:1.减少内存访问成本:通过优化数据传输路径,减少内存访问延迟,提高整体运算速度。2.考虑平台特性:针对不同硬件平台的特性进行优化设计,确保在目标平台上的高效运行。3.结构简洁高效:采用简洁而高效的模块设计,降低计算复杂度,同时保持或提升模型的预测准确性。下图,以四种不同计算复杂度水平下的准确性(在ImageNet验证集上的分类),速度和FLOPs的测量结果。(a, c) 为GPU结果,批量大小为8。(b, d) 为ARM结果,批量大小为1。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 1565

深度学习编译器TVM核心:TensorIR创建与算子优化实践

在深度学习模型部署中,算子实现与计算图优化是连接高级框架与底层硬件的关键。其核心原理在于通过中间表示(IR)对计算过程进行抽象与变换,以弥合不同硬件平台间的性能鸿沟。这一技术价值在于实现了计算与调度的分离,使得开发者可以专注于定义计算逻辑,再通过多种调度策略为特定硬件寻找最优执行方案,从而显著提升模型推理效率。在应用场景上,无论是为新型AI加速芯片编写自定义算子,还是对现有模型进行深度性能调优,掌握领域专用中间表示的创建都是基础且必要的技能。本文以TVM的TensorIR为例,详细解析了如何从零开始手动创建

weixin_30410119的博客 373

(6):单相三绕组变压器的拉氏变换数学模型和仿真模型

本节详细推导了基于耦合电路的单相三绕组变压器考虑铁心损耗情况下的拉普拉斯变换数学模型,并据此用Matlab/Simulink的传递函数模块搭建了相应的仿真模型,仿真结果表明所建立的数学模型和仿真模型都是正确的。本文的贡献是建立了考虑铁心损耗的单相三绕组变压器基于拉氏变换象函数的数学模型,为使用Simulink传递函数模块实现单相三绕组变压器的仿真模型提供了一条途径,所采用的建模方法和技巧具有启发作用,值得借鉴。

weixin_45670943的博客 373

【TVM教程】TensorIR

TVM 现已更新到 0.21.0 版本,TVM 中文文档已经和新版本对齐。 Apache TVM 是一个深度的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。

HyperAI超神经 251

拉曼光谱入门:7.拉曼光谱仪光学系统结构详解

本文系统拆解了拉曼光谱仪从激光器输出经聚焦照明、二向色镜/陷波滤光片组滤除瑞丽散射、衍射光栅色散至CCD探测的完整光路,阐述了各光学模块在微弱非弹性散射信号提取、杂散光抑制及高分辨光谱成像中的工程原理与技术参数要求。

qq_53529450的博客 223

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

TVM TensorIR创建实战:用TVMScript直写可调度算子

编译器中间表示(IR)是连接高层计算逻辑与底层硬件执行的桥梁,理解它对于算子开发至关重要。TVM作为深度学习编译器,其层次化IR设计使得循环优化、内存访问变换等关键操作得以显式表达。其中TensorIR作为一种可编程、可调度的中间表示形态,为开发者提供了直接操控循环、缓冲区(Buffer)与计算块(Block)的能力。通过TVMScript脚本化前端,开发者能够像写普通Python代码一样定义IR结构,极大降低了手写算子的门槛。从逐元素算子到复杂规约计算,TensorIR在矩阵分块、向量化、并行化等经典编译

weixin_32830601的博客 187

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

【MLC】 TensorIR 练习

这两天重新看了一下天奇的mlc课程文档,把里边儿的TensorIR 练习写了一下,顺便推广一下相关资料MLC-机器学习编译-B站MLC-文档bbuf老哥-B站Archer哥的二三事。

椰子奶糖的博客 924

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Apache TVM Relax 图抽象完全指南:从端到端模型执行到 dataflow 块

Relax 是 Apache TVM 中用于端到端优化机器学习模型的图级抽象(graph abstraction),它以计算图的方式刻画模型的结构、数据流以及各部分之间的依赖关系,从而让编译器能够在"高层神经网络层"与"低层张量算子"之间自由跨越。本文以官方文档 [learning.rst](https://link.gitcode.com/i/c9b1566a21dce95d16745e4772

gitblog_00926的博客 379

Apache TVM Relax 图抽象详解:计算图表示、跨层级 IR 与端到端优化

本文围绕 Apache TVM 中 Relax 的图抽象(Graph Abstraction)展开,讲解 Relax 如何将 ML 模型表示为有向计算图、如何在单一 IRModule 中同时承载高层神经网络算子与底层张量算子(TensorIR),以及图抽象如何为算子融合、动态形状追踪等编译优化提供支撑。读完本文,你将掌握 Relax 中 `R.dataflow` 数据流块、`R.call_tir`

gitblog_00716的博客 714

深度学习模型部署-番外-TVM机器学习编译

AI编译器,再不学就晚啦!

qq_45983373的博客 1694

TVM 学习指南(个人版)

最近粗略的看完了天奇大佬的MLC课程(顺便修了一些语法和拼写错误,也算是做了微弱的贡献hh),对TVM的近期发展有了一些新的认识。之前天奇大佬在《新一代深度学习编译技术变革和展望》一文中(链接:https://zhuanlan.zhihu.com/p/446935289)讲解了TVM Unify也即统一多层抽象的概念。这里的统一多层抽象具体包括AutoTensorization用来解决硬件指令声明和张量程序对接,TVM FFI(PackedFunc)机制使得我们可以灵活地引入任意的算子库和运行库函数并且在各

I good vegetable a! 8518

Apache TVM 文档导航与快速上手实践指南

Apache TVM 是一个面向"任意设备、任意环境"的机器学习编译框架(Open Machine Learning Compiler Framework),其官方文档入口 [docs/index.rst](https://link.gitcode.com/i/4a7fe03a2e54cd6786b66dfc7327a8cc) 以 7 组 `toctree` 导航目录,完整组织了从安装、入门、实战

gitblog_00973的博客 387

Apache TVM:Python-first 的开放机器学习编译器框架全解析

Apache TVM(本仓库即其开源镜像)是一个开放(Open)的机器学习编译框架(Machine Learning Compiler Framework),其核心使命是把预训练好的机器学习模型编译为可部署模块,从而在多样化的硬件与运行环境中高效执行。本文以仓库根目录 [README.md](https://link.gitcode.com/i/f1e10b09994f810e1e43d0ccad

gitblog_00537的博客 406

TVM Relax:重塑深度学习编译器的抽象层设计

深度学习编译器的发展,始终绕不开中间表示(IR)的设计——它决定了优化能走多远,表达能力能有多强。传统图IR擅长表达静态数据流,但在动态形状、复杂控制流和训练场景面前常显乏力。为此,TVM社区推出了Relax,一个重新审视机器学习编译抽象层次的新方案。Relax通过StructInfo统一类型、形状与存储信息,以dataflow块隔离纯计算与副作用,借助符号形状和运行时绑定机制应对动态形状难题。它将结构、算子和执行分层管理,既能描述计算图,也能表达闭包回调等高阶结构,配合Relax VM实现灵活高效的执行。

weixin_33957648的博客 470

TVM编译入门概念 一

清楚一个概念,onnx模型文件可以直接转换到Relay IR这一层onnx模型文件可以通过这个网站可视化展开哦代码角度看,Relay的基类Expr 就是 tvm.ir基础设施中的RelayIR在tvm/relay/expr.h中可以看到 relay命名空间中Expr指的就是 RelayExprVarNode 是Relay里面的变量VarNode 也会继承自 ExprNode这个类VarNode当中 有vid,type_annotatiton两个成员变量。

qq_43450892的博客 310

Apache TVM Relax 深度解析:图抽象、跨层优化与 Dataflow Pattern Language 实战

Relax 是 Apache TVM 技术栈中面向**图优化与图变换**的高层抽象,它与底层张量计算抽象 TensorIR 协同工作,共同完成对整个 `IRModule` 的跨层表示与优化。本文以 [docs/deep_dive/relax/index.rst](https://link.gitcode.com/i/fb302973d404d626231bec6d4457757f) 所组织的 De

gitblog_00626的博客 365
上一篇: 当多模态开始卷落地:MiniCPM-o-4.5仅9B覆盖实时图像理解与文本生成;vLLM Omni 同时支持文本与多模态模型的高吞吐部署与服务化
下一篇: 【Triton 教程】triton_language.clamp
HyperAI超神经
博客等级 码龄7年 8873粉丝 1753原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值