
AI系统 编译原理与编译器
文章平均质量分 65
主要整理编译原理和AI编译器的相关知识点
生活需要深度
这个作者很懒,什么都没留下…
展开
-
AI编译器管理教程
IRModule:包含和:包含大部分编译部分是关键数据结构之间的转换。和是确定性的基于规则的转换和autotvm包含基于搜索的转换最后,编译流程示例只是 TVM 栈的典型用例。我们将这些关键数据结构和转换公开给 python 和 C++ API。因此,您可以像使用 numpy 一样使用 TVM,只是感兴趣的数据结构从 numpy.ndarray 更改为 tvm.IRModule。使用 python API 直接构建 IRModule。编写一组自定义转换(例如自定义量化)。原创 2025-02-14 20:24:10 · 1008 阅读 · 0 评论 -
【TVM系列七】TVMC介绍
TVMC默认使用xgboost调优器进行调优,需要指定调优记录的输出路径文件,整个调优过程本质上是一个参数选择的过程,对不同的算子使用不同的参数配置,然后选择模型运行最快的那一组参数,属于一种参数空间搜索的策略,一般情况下都会比较耗时。本文介绍了TVMC工具的使用以及基本的实现流程,TVMC提供了很丰富的命令选项,可以说TVMC是一个很好的TVM Python API使用范例,建议感兴趣的同学可以通过深入了解。TVMC是TVM python包的一个应用工具,安装完TVM之后可以通过tvmc命令来执行。原创 2025-02-11 10:53:48 · 405 阅读 · 0 评论 -
【TVM系列六】PackedFunc原理
在base.py执行完_load_lib函数后,全局变量_LIB和_LIB_NAME都完成了初始化,其中_LIB是一个ctypes.CDLL类型的变量,它是Python与C++部分进行交互的入口,可以理解为操作TVM动态链接库函数符号的全局句柄,而_LIB_NAME是“libtvm.so”字符串。对赋值运算符的重载;在TVM中,PackedFunc贯穿了整个Stack,是Python与C++进行互相调用的桥梁,深入理解PackedFunc的数据结构及相应的调用流程对理解整个TVM的代码很有帮助。原创 2025-02-11 10:53:04 · 924 阅读 · 0 评论 -
【TVM系列五】添加Relay自定义算子
这就需要实现一个函数,传递相应的参数给对应的relay算子,并且返回对应算子的Call Node(这个算子最终在Relay表达式的AST里面)。A:在函数中会创建输入与输出的TypeVarNode,然后创建TypeRelationNode将类型关系函数管理起来,并定义一个FuncTypeNode将这些定义好的对象作为输入,最终赋值给op_type。本文以实现一个axis_abs的自定义算子为例介绍如何在tvm中添加新的relay算子,该算子实现的功能是以输入的3维tensor取某一维度的指定切片取绝对值。原创 2025-02-11 10:52:16 · 737 阅读 · 0 评论 -
【TVM系列四】模型编译与运行过程
类class Executor(object)是一个接口类,它的成员函数_make_executor()是一个接口函数,继承它的子类需要实现,它的另一个成员函数evaluate()会调用_make_executor(),也即调用子类class GraphExecutor实现的_make_executor()成员函数。该函数首先会遍历输入的数据,并调用set_input(...)为module设置输入参数,然后调用run()进行模型推理,最后获取输出的结果。这两个步骤在TVM中的运行过程是怎么样的呢?原创 2025-02-11 10:51:29 · 490 阅读 · 0 评论 -
【TVM系列三】算子转换调用流程
那么此函数是如何找到对应的conv2d算子的创建函数呢?那么算子是在哪里注册的呢?TVM_REGISTER_GLOBAL("relay.op.nn._make.conv2d).set_body_typed():将"relay.op.nn._make.conv2d注册到注册表中,并调用MakeConv。遍历这个表,查找节点对应的函数名,通过_get_global_func(name,...)获取到PackedFunc的控制句柄,调用的也是C++部分的接口_LIB.TVMFuncGetGlobal()。原创 2025-02-11 10:50:46 · 558 阅读 · 0 评论 -
【TVM系列二】TVM介绍
前面描述的转换都是基于规则和确定的,而TVM的设计目标之一是支持对于不同的硬件平台都可以进行高性能的代码优化。因此,需要对尽可能多的优化进行选择,每个优化又需要选择最优的参数,从这个角度来看,这个的工作量无疑是巨大的。TVM采用了基于空间搜索和机器学习的方法来解决这个优化选择与调参的问题。在relay优化的pipeline的最后,会运行一个 FuseOps的pass,将一个完整的Function(对应一个端到端的模型如 MobileNet)分解为多个子Funcions(例如 conv2d-relu)段。原创 2025-02-11 10:50:05 · 796 阅读 · 0 评论 -
【TVM系列一】开发环境搭建
其中一个特点是,使用机器学习(结合专家知识)的方法,通过在目标硬件上跑大量trial,来获得该硬件上相关运算(例如卷积)的最优实现。众所周知,深度学习的计算量庞大,在追求效率与实用性的工业界,深度学习所面临的一个最大的问题就是如何在不影响模型精度的前提下将算法模型部署到目标硬件平台上进行高效的前向计算。针对这些问题,TVM应运而生,为了解决第一个问题,TVM内部实现了自己的IR,可以将上面这些主流深度学习框架的模型转换为统一的内部表示,主要是通过NNVM进行转换。下载32位anconda。原创 2025-02-11 10:49:19 · 275 阅读 · 0 评论 -
【AI系统】为什么需要 AI 编译器
本文将通过探讨 AI 编译器的黄金年代以及传统编译器与 AI 编译器的区别等角度,来介绍为什么需要 AI 编译器。原创 2025-02-05 20:58:12 · 579 阅读 · 0 评论 -
【AI系统】LLVM 后端代码生成
上一篇文章主要讲了 LLVM 的前端和优化层,前端主要对高级语言做一些词法的分析,把高级语言的特性转变为 token,再交给语法分析对代码的物理布局进行判别,之后交给语义分析对代码的的逻辑进行检查。优化层则是对代码进行优化,比如常量折叠、死代码消除、循环展开、内存分配优化等。本文将介绍 LLVM 后端的生成代码过程,LLVM 后端的作用主要是将优化后的代码生成目标代码,目标代码可以是汇编语言、机器码。原创 2025-02-05 18:21:40 · 833 阅读 · 0 评论 -
【AI系统】AI 编译器后端优化
AI 编译器分为多层架构,最顶层由各种 AI 训练框架编写的神经网络模型架构,一般由 Python 编写,常见的 AI 训练框架有 PyTorch、MindSpore、PaddlePaddle 等。在导入 AI 编译器时需要用对应框架的converter功能转换为 AI 编译器统一的 Graph IR,并在计算图级别由进行计算图级优化,也叫前端优化。前端优化主要的计算图优化包括图算融合、数据排布转换、内存优化、死代码消除,这些优化是硬件无关的通用优化。在得到优化后的计算图后,将其转换为TensorIR。原创 2025-02-05 18:20:43 · 817 阅读 · 0 评论 -
【AI系统】LLVM 前端和优化层
在上一篇文章讲到了 LLVM 的 IR 贯穿了 LLVM 编译器的全生命周期,里面的每一个箭头都是一个 IR 的过程,这个就是整体 LLVM 最重要的核心概念。有了 LVM IR 之后这并不意味着 LLVM 或者编译器的整个 Pipeline 都是使用一个单一的 IR,而是在编译的不同阶段会采用不同的数据结构,但总体来说还是会维护一个比较标准的 IR。接下来本文就具体的介绍一下 LLVM 的前端和优化层。原创 2025-02-05 18:20:01 · 751 阅读 · 0 评论 -
【AI系统】LLVM 架构设计和原理
在上一篇文章中,我们详细探讨了 GCC 的编译过程和原理。然而,由于 GCC 存在代码耦合度高、难以进行独立操作以及庞大的代码量等缺点。正是由于对这些问题的意识,人们开始期待新一代编译器的出现。在本文,我们将深入研究 LLVM 的架构设计和原理,以探索其与 GCC 不同之处。原创 2025-02-05 17:21:20 · 1017 阅读 · 0 评论 -
LLVM学习笔记
我主要是看IR和PASS我们知道,传统的编译过程大概可分为两个步骤:把源代码翻译成中间表示(IR),把IR翻译成机器码(或者由解释器来解释执行)。这三个层次也就是前端、中端、后端。GCC编译器在设计时没有做好层次划分,你不能知道它的IR是什么样子的,它也不会提供接口让你操作IR,这导致了其前端后端的大量数据耦合在了一起。这样一来,GCC就很难支持新的编程语言或者架构。如果有一个大家都使用的开放的IR,那么每种新语言只需要一个新前端,每个新平台只需要一个新后端,这就比GCC方便的多。原创 2025-02-05 16:57:24 · 1041 阅读 · 0 评论 -
【AI系统】LLVM 后端代码生成
上一篇文章主要讲了 LLVM 的前端和优化层,前端主要对高级语言做一些词法的分析,把高级语言的特性转变为 token,再交给语法分析对代码的物理布局进行判别,之后交给语义分析对代码的的逻辑进行检查。优化层则是对代码进行优化,比如常量折叠、死代码消除、循环展开、内存分配优化等。本文将介绍 LLVM 后端的生成代码过程,LLVM 后端的作用主要是将优化后的代码生成目标代码,目标代码可以是汇编语言、机器码。原创 2025-02-05 15:42:41 · 953 阅读 · 0 评论 -
【AI系统】LLVM 前端和优化层
在上一篇文章讲到了 LLVM 的 IR 贯穿了 LLVM 编译器的全生命周期,里面的每一个箭头都是一个 IR 的过程,这个就是整体 LLVM 最重要的核心概念。有了 LVM IR 之后这并不意味着 LLVM 或者编译器的整个 Pipeline 都是使用一个单一的 IR,而是在编译的不同阶段会采用不同的数据结构,但总体来说还是会维护一个比较标准的 IR。接下来本文就具体的介绍一下 LLVM 的前端和优化层。原创 2025-02-05 15:40:33 · 671 阅读 · 0 评论 -
LLVM学习笔记——目录(含7.0更新)
不过,不管怎么说,饭要一口口吃,路要一步步走,退一万步来说,LLVM的架构极其先进,如果能从其软件架构中学到些什么,也是有益的。不过据说4.0进行的重构,应该会好些),充斥着动辄数千行的函数,包含着庞大的switch块以及if块,加之函数间的相互调用,看得人昏头转向。它使用一种称为tlbgen的语言来描述目标机器的方方面面(该语言的许多语法成分被LLVM的发明人ChrisLatter借鉴到新发明的Swift语言里),然后在编译LLVM的过程里,通过工具解析生成C++的源代码。另,原创不易,转载请注明出处。原创 2025-02-05 10:49:04 · 358 阅读 · 0 评论 -
LLVM学习笔记(30)
如果是变量的某个定义,它就需要维护一个使用链,记录对它的使用,这就是355行的UseList的用处——构成Def-Use链。需要这个次序,是因为指令选择后得到的节点将替换被选中的节点,即被选中节点的使用者需要使用选择得到节点来代替被选中的节点。实际上这个SelectionDAG是从最顶上的EntryToken开始构建的(即以函数的语句顺序),节点保存在ilist<SDNode>类型的容器里(SelectionDAG的AllNodes,这个容器是一个链式容器,图中没有显示将各个节点连接起来的边)。原创 2025-02-05 10:46:37 · 546 阅读 · 0 评论 -
深入浅出 LLVM之 Value 、User 、Use 源码解析
先叠个甲。这是我的第二篇技术文章,并且我对于LLVM源代码的理解还停留在比较粗浅的层面。可能文章中措辞有些不严谨,亦或是技术点有误的地方,欢迎评论区友好讨论。温馨提示:文中代码块和图比较多,建议使用电脑观看哦。LLVM之设计是LLVM中最核心的设计之一,为了详细地讲解他们之间的关系,我先以中一个常见的优化来引入。原创 2025-02-05 10:39:39 · 976 阅读 · 0 评论 -
LLVM基本框架结构
LLVM编译器采用了如下图所示的三段式设计:前端,优化组件和后端。前端组件解析程序源代码,检查语法错误,生成一个基于语言特性的AST来表示输入代码,并将其转换为LLVM IR;优化器作用是中间代码(IR)优化,比如去除无用的变量或者无用的计算,来提高代码运行效率;后端生成目标机器码。LLVM backend的主要功能是code gen,也就是代码生成,其中包括若干个code gen分析转换pass将LLVM IR转换成特定目标架构的机器代码。原创 2025-02-05 10:37:58 · 1048 阅读 · 0 评论 -
llvm学习笔记(2)查看这个博客学习源码
第二个值则是一个dag值,其操作符是“v2i64”,“v2i64”的操作数又是一个dag值,其操作符是“scalar_to_vector”,操作数是一个dag值,以“i64”作为操作符,以此类推。在上面的Instruction声明中,dag,bit,string,int与list都可视为TD语言的保留字,它们只允许出现在class,multiclass,def,defm及foreach这样的声明里。它们是TD的内置类型。dag是一个很特殊的类型,它表示了程序中间表达树中的dag【有向无环(子)图】结构。原创 2025-02-05 10:31:40 · 260 阅读 · 0 评论 -
深入理解TVM:TVM_REGISTER_NODE_TYPE
本文来重点讲一下TVM中第三个重要的注册宏TVM_REGISTER_NODE_TYPE,它主要用于配合之前讲的两个注册宏,目前能查到这个宏使用了三百多次,下面是TVM_REGISTER_NODE_TYPE在})它首先通过定义一个全局唯一静态变量的方式,通过调用前文《深入理解TVM:Object家族》中定义的_GetOrAllocRuntimeTypeIndex为注册对象分配一个全局唯一的type index,也可以调用RuntimeTypeIndex这个静态接口,它是对前者的封装,把上面定义中的宏展开})原创 2025-02-04 15:58:47 · 747 阅读 · 0 评论 -
深入理解TVM:详解Relay Op Attrs
Relay Op Attrs指的是Op中属性的定义,以前这是属于NNVM的部分,后来TVM引入了Relay替换掉了NNVM,Op Attrs的定义被放到了Relay中,先看一下Attrs相关的类定义继承关系:图1其中蓝色的类就是Op Attrs实际定义的地方,所有的Attrs都应该定义在这个文件夹的文件中。因为Conv2D的属性个数和类型相对比较多,所以感觉更具有代表性,下面就以int groups;原创 2025-02-04 15:35:57 · 675 阅读 · 0 评论 -
TVM中resize算子原理及细节分析
原始图像是 f(x) 为定义在区间 [a,b] 上的函数。x1,x2,x3...xn 为 [a,b] 上 n 个互不相同的点,插值函数为 G , g(x) 经过变换后是蓝色部分曲线:红色是曲线中实际已知数据点;蓝色为插值即连接的曲线可以看到原始图像是红色的一些离散点,经过插值函数 f(x) 映射得到蓝色的曲线。尽管插值函数是通过原始像素变换得到的,这些像素不一定全部正确,有些可能是粗略的估计。通常插值算法有基于经典的图像插值算法、基于边缘的插值算法。经典的插值算法主要分片段插值、线性插值。原创 2025-02-04 15:32:42 · 831 阅读 · 0 评论 -
写给入门者的LLVM介绍
LLVM 非常庞大。LLVM 提供的大量经典编译器分析。通过拓展后端来生成任何特殊的机器指令,就像架构师经常想做的那样。利用debug info,可以连接回与 IR 对应的源码位置。为 Clang编写前端插件。希望上文提及的知识足够我们用来创建一些很棒的东西。探索、构建并让作者知道这是否有帮助!原创 2025-02-04 15:14:16 · 687 阅读 · 0 评论 -
深入理解TVM:常用的Container
TVM没有直接使用STL中的container,而是自成体系,单独写了一套,这部分代码作为整个TVM code base的基石,非常重要,虽然能透过字面意思猜到其用途,但是了解其具体实现更有助于深刻理解这套系统。这些container也都继承自TVM的Object体系(细节可参考前文《》),这样在TVM中,就连container也可使用Object来表示,使整个系统的抽象更加统一。原创 2025-02-03 20:42:34 · 746 阅读 · 0 评论 -
深入理解TVM:内存分配器
中make_object构造的对象在完成相关初始化之后,最终交由data_管理,如下面代码所示,data_定义在Tensor的顶层基类ObjectRef中,可以看作是一个指向Object对象的指针,Object、ObjectPtr、ObjectRef三者的关系已经在前文。看到这里,所有的一切就真相大白了,make_object调用的New通过标准库的new来分配空间,然后再通过placement new来在分配的空间上构造对象,这里可能大家会有个疑问,就是为什么要用。原创 2025-02-03 20:33:48 · 651 阅读 · 0 评论 -
深入理解TVM:RELAY_REGISTER_OP
RELAY_REGISTER_OP是TVM中非常重要的一个注册宏,用来注册relay中的op,目前code base中大概有200多个(基于commit fe25b9e7c,因为官方的代码一直在更新,所以这个数字也会继续变化,但现在op基本趋于稳定,应该不会再有大的变化),先贴几个relay中注册的op,给大家一个直观的印象:下面来详细介绍这个注册机制的实现和原理,为了便于理解,所有代码都做了不同程度的精简,有些语法不通的地方是混用了一些伪代码。这个宏定义在。原创 2025-02-03 20:17:31 · 684 阅读 · 0 评论 -
深入理解TVM:Object家族
Object类在TVM里非常重要,基本上所有其他的类都直接或者间接继承自这个类,我做了一个简单的统计,基于这个基本类派生出来的类目前有三百多个(基于commit:fe25b9e7c,使用TypeContext类提供的Dump功能,可以把所有的类名和继承关系用文本的方式打印出来),比较靠顶层的部分类信息如下图:ICHECK(fp!= nullptr);(*fp)(0);主要有几个静态变量_type_key:类的全局唯一的字符串标识符。原创 2025-02-03 17:47:11 · 671 阅读 · 0 评论 -
深入理解TVM:Python/C++互调
本文只详细说了开头列出的第一部分,即PackedFunc的实现原理,还有第二第三部分没说,后面的文章会陆续再分析细说这两部分。最后的最后,TVM的官方文档对PackedFunc机制有一段简短精辟的介绍(),大家可以作为参考来理解上面代码:深入理解TVM:Python/C++互调(上)原创 2025-02-03 17:45:18 · 793 阅读 · 0 评论 -
图解TVM中的调度原语(Schedule Primitives)
上面简要介绍了TVM中基本的调度原语(Schedule Primitives),我们可以通过组合这些基本元素,达到一个满意的优化结果。原创 2025-02-03 15:55:12 · 882 阅读 · 0 评论 -
Windows 安装TVM 及各种报错解决!无GPU版本
我这里选择的是第(2)种 ,虽然我不确定这样对,不过还是那句话,后面出了问题,可以解决!把OFF 替换为 D:/anaconda3/envs/tvm-build/Library/bin/llvm-config(根据自己实际情况替换地址,有时候这个地址需要加引号,有时候不需要,可以根据自己实际情况试试)conda activate tvm-build 其中tvm-build 是 build-environment.yaml 中的name,上文已经提到了,如果你改了,这一块也要改。原创 2025-02-03 11:38:43 · 298 阅读 · 0 评论 -
AI算法工程师老潘的思考(部署、AI、就业)
至于开发新的算法,说实话确实很牛逼,只是大部分场景下不需要,很多业务场景算法做到极致还是比较难的,从0-90提升好说,从98-99就难的很了。不过可以肯定的是,不管是阿里的达摩院、华为的2012实验室啥的,我问了一些在里头的朋友,搞的和咱们正常算法工程师相差不大。手机这种移动端AI部署落地也是目前需求较高的一个方向,毕竟手机芯片也是年年要更新的,关于这方面要学习的有很多,算法SDK、算法移植、算法op优化、甚至具体到芯片层面,arm的指令、gpu、npu、dsp的优化等等要做的东西很多很多,原创 2025-02-03 10:23:59 · 1093 阅读 · 0 评论 -
利用TVM神经网络编译器完成模型C++端的部署
在上一篇文章中<一步一步解读神经网络编译器TVM(一)——一个简单的例子>,我们简单介绍了什么是TVM以及如何利用Relay IR去编译网络权重然后并运行起来。上述文章中的例子很简单,但是实际中我们更需要的是利用TVM去部署我们的应用么,最简单直接的就是在嵌入式系统中运行起我们的神经网络模型。例如树莓派。这才是最重要的是不是?所以嘛,在深入TVM之前还是要走一遍基本的实践流程的,也唯有实践流程才能让我们更好地理解TVM到底可以做什么。原创 2025-02-02 17:53:11 · 1018 阅读 · 0 评论 -
可以让深度学习编译器来指导算子优化吗
之前在阅读Ansor论文的时候(https://zhuanlan.zhihu.com/p/390783734)我就在想这样一个问题,既然Ansor是在人为指定的推导规则下启发式的生成高性能的Scheduler模板。那么这个算子生成的Scheduler模板是否可以反过来指导我们写程序呢?嗯,然后我就开启了这个实验,但最近因为工作的事情delay得厉害,终于在这个周末抽出时间来更新这个实验结果并且记录了这篇文章。由于笔者只对GEMM的优化熟悉,这里就以优化X86的GEMM为例子来探索。原创 2025-02-02 17:39:01 · 1033 阅读 · 0 评论 -
TVM源语-Compute篇
总结一下,TVM的DSL其实包含很多内容,和我们平时写序列形式的code的style不太一样,这种写法更偏向functional programming的模式,当然这样写的好处也很明显,通过lambda表达式和reduce_axis的组合,将for-loop的形式hidden起来,增加大家对于算法的理解,从而让compiler的后端能更好的优化前端通过DSL定义的for-loop。原创 2025-02-02 17:38:24 · 726 阅读 · 0 评论 -
【从零开始学深度学习编译器】番外二,在Jetson Nano上玩TVM
【GiantPandaCV导语】这篇文章主要是讲解了如何给Jetson Nano装机,以及在Jetson Nano上如何配置TVM并将MxNet的ResNet18跑起来获取分类结果,最后我们还体验了一下使用AutoTVM来提升ResNet50在Jetson Nano上的推理效率,AutoTune了一个Task(一共需要AutoTune 20个Task)之后可以将ResNet50的推理速度做到150ms跑完一张图片(224x224x3),从上面的BenchMark可以看到TensorRT在FP32的时候大概能原创 2025-02-02 17:35:56 · 787 阅读 · 0 评论 -
【从零开始学深度学习编译器】番外一,Data Flow和Control Flow
本来是想在讲TVM Relay的时候提一下DataFlow和ControlFlow的,但是担心读者看到解析代码的文章打开就关了,所以这里用一篇简短的文章来介绍一下深度学习框架中的DataFlow和ControlFlow。这篇文章介绍了一下深度学习中的Data Flow和Control Flow,然后介绍了一下将Pytorch模型转为TorchScript的两种模式,并探索了要将Pytorch的Python层的Control Flow转换为ONNX应该怎么做。原创 2025-02-02 17:37:07 · 861 阅读 · 0 评论 -
【从零开始学深度学习编译器】十,TVM的整体把握
大概4个月前开始接触TVM,虽然是0经验开始看,但目前对TVM的IR以及Pass,Codegen,Scheduler等也有了一些基础的认识。所以这篇文章的目的是梳理一下TVM的整体架构,复盘一下自己学到了什么,以及为想学习TVM的小伙伴们提供一个整体思路。这个专题的文章和实验代码都被我汇总放到了https://github.com/BBuf/tvm_learn这个仓库中,当然是希望,感激不尽。仓库目录如下:TVM 学习笔记目录页。原创 2025-02-02 17:39:36 · 731 阅读 · 0 评论 -
【从零开始学深度学习编译器】九,TVM的CodeGen流程
这篇文章主要是来介绍一下TVM的CodeGen流程。TVM自动代码生成的接口是tvm.build和tvm.build是用来做算子的代码生成,而是用来做relay计算图的自动代码生成(这里代码生成已经包含了编译流程)。接下来我们就从这两个函数讲起,一直到TVM的Codegen的具体实现。阅读这篇文章之前建议先了解一下TVM的编译流程,即看一下【从零开始学深度学习编译器】六,TVM的编译流程详解这篇文章。原创 2025-02-02 17:22:29 · 1006 阅读 · 0 评论