TVMNN编译Compiler栈
内容纲要

  1. 前言
  2. 调研目标
  3. TVM介绍
  4. TVM源码架构
    i. FrontEnd
    ii. Relay
    iii. BackEnd
  5. VTA实现原理及设计思想提炼
    i. 整体结构
    ii. VTA Hardware
    a.
    a. 指令集
    b. 数据流
    c. 控制流
    b. VTA Config
    c. Pyng HLS
    d. 硬件设计思想提炼
    e. Chisel Scalar
    f. SIM C++
    g. Xilinx Scripts
    iii. VTA JIT
    a. Driver
    b. Runtime
    c. TVM Runtime Library
    iv. VTA Complier
  6. 参考文献
    前言
    深度学习/神经网络应用日益广泛,多终端部署形成常态。从CPU、ARM、GPU到专用的神经网络加速器/深度学习处理器,不同的终端/不同的体系结构引起神经网络的碎片化;每一款设备特别是专用的加速芯片部署深度学习是一件费力不讨好的事情;同时近年来,虽然CNN加速器在学术上和产业上火热,但不同的研究人员/企业在CNN加速器上使用不同的指令集,不同的体系结构,没有统一的标准使开发人员在终端上部署。所以一款支持前端,各种后端,统一结构/指令集,扩展方便的NN编译栈在NN生态上的构建有着举足轻重的影响力,这就是TVM的魅力。
      现在主流的深度学习训练框架是Caffe/PyTorch/TensorFlow/MxNet等,对CPU/CUDA支持得很好。如果想把训练好的神经网络部署到其它的终端设备,这就带了几个挑战:
  7. 主流框架不支持ARM/FPGA/ASIC
  8. 嵌入式终端不需要训练功能,对前向推理的速度有极大的要求
  9. 嵌入式终端性能/内存/存储有限,主流框架的臃肿不适合部署
  10. 终端指令集,架构没有统一标准,开发部署难度很大
      这时需要一款软件编译栈,上接前端主流深度学习框架,后接各种终端;同时满足轻量级,高性能,高度扩展与灵活性,开发容易等要求。TVM 是深度学习系统的编译器堆栈。旨在缩小以算力为重点的深度学习框架与以性能和效率为重点的硬件后端之间的差距。TVM与深度学习框架协同工作,为不同的后端提供端到端编译。TVM支持主流的深度学习前端框架,包括TensorFlow, MXNet, PyTorch, Keras, CNTK;同时能够部署到宽泛的硬件后端,包括CPUs, server GPUs, mobile GPUs, and FPGA-based accelerators。
      本文深度分析TVM的源代码(主要是FPGA-based accelerator/VTA方面),总结TVM的几个实现特点:
  11. 对接前端的神经网络模型配置文件,将前端网络转为自主设计的AST Graph/Relay IR;后端编译都基于这个Graph/Relay IR。这类似于实现一个通用的编译器,将C++/JAVA/Python等语言转换为自主的编译型语言IR;然后基于IR实现一个高性能的后端程序部署。
  12. 实现NN的Tensor Operator Libray:不同的后端采用不同的实现方式。
  13. 根据后端硬件将前端网络编译为Complied PackedFunc生成动态链接库,用于后端执行。
  14. RunTime和Driver加载Complied PackedFunc调用硬件执行推理计算。
  15. 在HalideIR/LLVM框架/思想上实现编译系统。
      前端的分离方式便于TVM兼容主流的深度学习框架,后端的编译运行分离使后端只需要部署一个轻量级的TVM(只包括RunTime和Driver)。这种思想能够兼顾通用性与性能。同时TVM在VTA(NN加速器)上的设计了一套通用的类RISC指令集,体系结构。TVM的整体思想与最终目标就是通用,形成一个深度学习全栈生态;但目前TVM实现的效果如何,让走近源代码分析一番。
    调研目标
    本文着重分析TVM的Relay IR 层,编译,VTA(NN加速器)源代码;ARM/CUDA部分目前不在源代码分析范围内。
    • 明确TVM层次结构,掌握TVM的用法,工作原理,支持的软硬件框架
    • 分析TVM源码设计与实现,对TVM的工作框架有清晰地、层次化的认识
    • 研究TVM论文、文档与源码,提炼出TVM的设计思想;包括整体设计思想,Relay、VTA,并细化到JIT、Complier、Hardware Design等设计理念。
    • 评估TVM从前端到后端的性能,着重于VTA硬件的实现指标
    • 整体评估基于TVM设计加速器的可行性
    • 具体分析TVM的细节实现,包括VTA Hardware,JIT Diver,Complier等。
    • 评估设计或修改加速器所需的软件改动,包括修改难度、工作量
    • 综合以上,得出基于TVM编译栈生态设计自己的处理器,部署神经网络的可行性及成熟度分析。
    TVM介绍
      TVM是一个端到端的深度学习工具链,能够高效地把前端深度学习模型部署到CPUs、GPUs和专用的加速器上。TVM具有强大的兼容能力和扩展性,支持主流的深度学习前端框架,包括TensorFlow, MXNet, PyTorch, Keras, CNTK;同时能够部署到宽泛的硬件后端,包括CPUs, server GPUs, mobile GPUs, and FPGA-based accelerators。

TVM设计架构
TVM架构如下:

  1. 导入前端深度学习模型 CNN model configuration and parameters,生成计算图
  2. 重构原始计算图,基于operator-level优化图的计算
  3. 基于Tensor张量化计算图,并根据后端进行硬件原语级优化
  4. 根据优化目标探索搜索空间,找到最优解
  5. 生成硬件所需指令、数据并部署到硬件上
    Tvm注意点:
    • TVM只做前向计算包括量化,不对网络进行训练
    • 硬件是预先可配置的,编译优化部署的时候硬件需保持固定。
    • 可以部署TVM Runtime System到嵌入式设备上(SOC),实现CPU与VTA之间的自动交互和实时运行环境。
    TVM源码架构

TVM软件架构
  TVM 源代码由三层构成,包括FrontEnd接口、Relay优化和BackEnd部署。目前着重研究BackEnd VTA层级和与硬件相关的Relay部分。设计上三层应该互不影响,各自独立;但源代码分析中,Relay层糅合了与硬件无关的图优化和与VTA相关的调度生成,没有分得很开。
FrontEnd
  支持主流的深度学习前端框架,包括TensorFlow, MXNet, PyTorch, Keras, CNTK。目前TVM可以继承到PyTorch框架中优化、训练,而不是单纯地调用CNN模型接口。
Relay
  根据具体硬件对原始计算图进行重构、张量优化、数据重排等图优化操作。源代码分析中,Relay层比较杂,干的事情比较多,既对接上层的图优化又对接硬件的调度器。

Relay及Tensorlization示例
BackEnd
后端支持ARM、CUDA/Metal/OpenCL及加速器VTA。

  1. 生成硬件所需指令流与数据打包
  2. 一个CPU与VTA的交互式运行环境:包括driver、JIT。
    VTA实现原理及设计思想提炼
    整体结构

VTA层次结构
VTA源代码架构有三个部分组成:

  1. 硬件实现:包括硬件源代码、硬件配置文件
  2. 编译器:以operator或func级打包计算图生成调度器,以及编译出硬件执行指令
  3. JIT:软硬件交互运行环境
    • Driver:CPU与VTA的通信与控制驱动
    • Runtime:CPU对VTA的实时运行控制
    • TVM runtime library:VTA runtime的基本库,主要是句柄的定义
    VTA Hardware
      为了实现硬件的通用化计算,VTA硬件参考RISC指令集,按照Fetch—>Load—>Compute—>Store模式,将所有操作划分到这种粒度的计算,不设计专用复杂的计算模式。在牺牲一定性能的情况下,尽可能兼容更多的深度学习网络。

VTA硬件体系结构
指令集
VTA指令分为四大类:

  1. Fetch:从DRAM取指到片上指令SRAM
    • load 指令buffer
    • GEMM指令buffer
    • Store指令buffer
  2. LOAD:从DRAM取数据到片上SRAM
    • inp buffer和wgt buffer
    • uop buffer (源码实现在compute 中)
    • Acc buffer放bias(源码实现在compute 中)
  3. Compute:加载SRAM数据到计算单元并执行GEMM或ALU计算
    • ALU:执行vector的计算Min、Max、ADD、MUL、SH
    • GEMM:执行Tensor乘法
  4. Store:从SRAM存储数据到DRAM

VTA 指令结构
数据流
  VTA relies on dependence FIFO queues between hardware modules to synchronize the execution of concurrent tasks. The figure below shows how a given hardware module can execute concurrently from its producer and consumer modules in a dataflow fashion through the use of dependence FIFO queues, and single-reader/single-writer SRAM buffers. Each module is connected to its consumer and producer via read-after-write (RAW) and write-after-read (WAR) dependence queues。
VTA依赖于硬件模块之间的依赖FIFO队列来同步并发任务的执行。下图显示了给定硬件模块如何通过使用依赖FIFO队列和单读写器SRAM缓冲区,以数据流方式从其生产者和消费者模块并发执行。每个模块通过读后写(RAW)和读后写(WAR)依赖队列连接到其使用者和生产者。

Dataflow and Dependency
  The pseudo-code above describes how a module executes a given instruction predicated on dependences with other instructions. First, the dependence flags within each instruction are decoded in hardware. If the instruction has an incoming RAW dependences, execution is predicated upon receiving a RAW dependence token from the producer module. Similarly, if the task has an incoming WAR dependence, execution is predicated upon receiving a WAR dependence token from the consumer module. Finally when the task is done, we check for outgoing RAW and WAR dependences, and notify the consumer and producer modules respectively.
上面的伪代码描述了一个模块如何根据与其它指令的依赖关系,执行给定的指令。首先,在硬件中对每条指令中的依赖标志进行解码。如果指令具有传入的原始依赖项,则在从生产者模块接收到原始依赖项令牌时,将断言执行。类似地,如果任务具有传入的WAR依赖性,则在从使用者模块接收到WAR依赖性令牌时,就断言执行。最后,当任务完成时,检查输出的RAW和WAR依赖,并分别通知使用者和生产者模块。
控制流
按照Fetch—>Load—>Compute—>Store模式去计算:

  1. CPU把数据和指令放到DRAM
  2. Fetch和Load分别将指令和数据从DRAM搬运到SRAM
  3. CPU会提前计算好一部分AGU地址uop放到DRAM,然后被搬运到uop Sram
  4. Compute译码指令根据指令参数,执行对应的GEMM或ALU计算;计算结果放回到acc/out sram。
  5. Store将计算结果从SRAM放回到DRAM
  6. CPU取出计算结果并准备下次计算数据,返回第一步
    Inp buffer和Out buffer之间没有数据交换,固定buffer in/out。控制逻辑会处理数据/指令依赖以及memory latency hiding。
    VTA Config
      VTA主要对硬件的数据位宽,SRAM 大小,计算阵列大小进行配置,而不能更改大的计算架构,数据流,控制流等;同时TVM根据已配置好的VTA执行编译工作,而不会在编译阶段在线生成硬件代码。

VTA配置
Pyng HLS
  VTA采用高层次综合C++实现Xilinix Pynq FPGA的部署,包含配置文件,Vivado HLS 脚本,HLS C++硬件实现三部分组成。

Pynq FPGA部署
Hw_spec和VTA Implementation构成HLS 实现的主体:

  1. hw_spec.h: 数据及指令定义
    • 根据VTA Config 定义数据宽度,GEMM规模,SRAM大小
    • 定义指令layout(指令关键字段的排列顺序,如下面GEMM layout所示)

    // GEMM Layout
    // ________________|type|
    // arg 0: opcode | opcode_T |
    // arg 1: pop_prev_dependence | bool |
    // arg 2: pop_next_dependence | bool |
    // arg 3: push_prev_dependence | bool |
    // arg 4: push_next_dependence | bool |
    // arg 5: reset_reg | bool |
    // arg 6: uop_bgn | uop_idx_T |
    // arg 7: uop_end | uop_idx_T |
    // arg 8: iteration count ax0 | loop_T |
    // arg 9: iteration count ax1 | loop_T |
    // arg a: accum idx factor ax0 | acc_idx_T |
    // arg b: accum idx factor ax1 | acc_idx_T |
    // arg c: input idx factor ax0 | inp_idx_T |
    // arg d: input idx factor ax1 | inp_idx_T |
    // arg e: weight idx factor ax0 | wgt_idx_T |
    // arg f: weight idx factor ax1 | wgt_idx_T
  2. VTA Implementation:硬件实现包括Stream、fetch、load、compute、store五大模块及VTA顶层控制。

VTA HLS C++ 实现
• Stream:定义CPU与VTA之间的数据接口/数据流。
• fetch:将指令从DRAM根据译码分类分别搬运到SRAM三个buffer中:load_queue,gemm_queue,store_queue。
• load:从load_queue中读取load指令,译码并计算对应地址;从DRAM上搬运inp和weight到SRAM上inp_mem和wgt_mem中。同时数据的padding工作通过在数据传输时对inp_mem写零完成。
• compute:从gemm_queue中读取计算指令,译码计算对应地址;从DRAM上搬运uop(计算所需的部分数据,权重地址)和bias到SRAM;从SRAM中加载数据和权重,根据译码计算GEMM或者ALU。其中计算的核心数据流为:
• Input SRAM—>Input Register
• Input Register—> Computing Unit
• Result—>Out Register/Out SRAM
• Out Register—> Out SRAM
• Store:将计算结果从SRAM—>DRAM
• VTA:以上模块的控制逻辑实现。
• 封装stream:包括instuction queue和dependency queue。
• 实例化SRAM
• 取值
• 根据依赖调度存储和计算(依赖参考上文数据流中的dependence)
硬件设计思想提炼
VTA的核心思想,将计算划分到一个通用的细腻度的计算结构Operation Wrapper:
• Load Inst:加载Operation对应指令
• Decode:译码
• AGU:计算Operation所需要的DRAM或SRAM地址
• Operation:利用Operation对应的硬件计算资源执行操作
  无论是Fetch、load、compute、store等较大粒度的操作都可以利用OperationWrapper分解到更细粒度的四个步骤,这和传统的设计方法不同。举例,传统设计是将芯片分为DMA—>Load—>Compute—>Store四个模式,每个模式单独去设计一套尽量通用的操作单元,去匹配软件算法;同时每个模式不会再分解到一个更通用的细腻度结构;OperationWrapper将Fetch—>Load—>Compute—>Store中每个模式都分解为Load—>Decode—>AGU—>Operation,即使是传统认为Load/Store已经是最小粒度,TVM依然再次分解到OperationWrapper。这有点像RISC中再RISC的思想。

VTA 硬件设计思想
  另外,传统方法设计一个统一的AGU负责所有的地址计算;而TVM通过OperationWrapper将统一的AGU分解到每个模块,让每个模块负责一个更细粒度的AGU。这种方式能够加强AGU的通用性。
  VTA这种OperationWrapper的思想,将硬件进一步分解到更加通用的细粒度模式,比起传统方法通用型更强。
  VTA的第二个核心思想,利用Stream传输并通过同步控制解决指令与数据的依赖性(有点类似操作系统中的设计理念),让CPU与VTA的通讯、传输、控制变得更向操作系统级靠拢,可能也是为了TVM的通用性考虑。
参考文献
TVM: An Automated End-to-End Optimizing Compiler for Deep Learning
VTA: A Hardware-Software Blueprint for Flexible Deep Learning Specialization
TVM Tutorials
TVM GitHub

TVMNN编译Compiler栈相关推荐

  1. TVM适配NN编译Compiler缺陷

    TVM适配NN编译Compiler缺陷 内容纲要 前言 TVM针对VTA的编译流程 i. 自定义VTA架构:TVM的缺陷与性能瓶颈 TVM缺陷与瓶颈 i. 缺陷一:SRAM配置灵活性差 ii. 缺陷二 ...

  2. 探索编译软件栈新范式;高端GPU禁售的影响;陈天奇DL系统免费课程|AI系统前沿动态

    1. 高端GPU禁售传闻声起,BAT们遭遇紧张时刻 互联网企业成为此次制裁波及的主要对象.行业人士指出,互联网厂商出于对性能等因素考虑,对国产CPU.GPU普遍接纳度不高,此次事件应为互联网厂商预警, ...

  3. g++ linux 编译开栈_Linux下编写C++服务器(配置C++编译调试环境)

    Linux下编写C++服务器(配置C++编译调试环境) 安装好linux虚拟机,确定能上网后,我们可以开始编写C++程序了,但在这之前我们需要下载编译器和调试器 下载gcc 1.在终端输入yum se ...

  4. vue中模板编译compiler源码详解

    vue编译模板过程; <div><h1>这是compiler</h1> <p v-if="message">{{ message } ...

  5. g++ linux 编译开栈_方舟编译器编译hello world踩坑全记录

    闲来无事,看到方舟编译器完整开源,于是打算拿来试着编译一个东西来,接下来把踩过的一些坑记录一下. 参考文档 方舟编译器的官网是 OpenArkCompiler​www.openarkcompiler. ...

  6. g++ linux 编译开栈_使用g++编译器扩大程序可用栈空间

    如题,在写一些程序的时候我们有时会开一个比较大的数组或进行层数较多的dfs.这时候,程序常常会报错,于是就很无奈. 其实,虽然Windows给程序的默认栈空间比较小,我们还是有办法去扩大这个程序运行栈 ...

  7. g++ linux 编译开栈_使用 linux kernel +busybox 定制linux系统

    写在开头: 本来是想使用linux kernel +busybox 制作一个教程的,后来快要结束的时候,死活找不到硬盘,我了解很多文章都有类似的,但是没有谈到硬盘找不到问题,最后历经艰辛,终于把问题解 ...

  8. g++ linux 编译开栈_linux gcc和g++版本的修改

    ##编译的时候容易遇到:unsupported GNU version! gcc versions later than 6 are not supported这样的错误.所以我们要更改系统的gcc和 ...

  9. g++ linux 编译开栈_linux下使用g++编译cpp工程

    C++编程中相关文件后缀 1.单个源文件生成可执行程序 下面是一个保存在文件 helloworld.cpp 中一个简单的C++程序的代码: 1 /*helloworld.cpp*/ 2 #includ ...

最新文章

  1. 吊打 ThreadLocal!
  2. 智能车竞赛开启了新的一个周期,让我聚焦十六届赛题吧
  3. 机器学习笔记:Transformer
  4. martingale、markov chain、Monte Carlo、MCMC
  5. php函数网,php函数
  6. Spring3.1+Quertz1.8实现多个计划任务
  7. Java网络编程从入门到精通(5):使用InetAddress类的getHostName方法获得域名
  8. (31)Verilog HDL逻辑运算
  9. 网络机房利用()将多台计算机,2020现代教育技术章测试答案.doc
  10. 【C语言】在线OJ题 BC7-BC52-牛客网编程初学者入门训练
  11. 中国工业信息安全大会召开,开发新技术与新模式,推动工业互联网安全发展
  12. shell脚本如何获取当前时间
  13. 教你如何选择网络机顶盒
  14. 天池大数据竞赛口碑商家客流量预测——时序预测(python-numpy-arima)
  15. HAUT OJ 1475: cxk下棋
  16. 基因测序的云计算平台可能带来的变革与进步
  17. vsftpd 虚拟用户
  18. 阿里云专网服务器连接互联网的设置
  19. 抖音直播伴侣和快手直播伴侣如何实现无人直播还能防封号
  20. 常见的分类算法及分类算法的评估方法

热门文章

  1. 创建数据库,指定数据库的字符集和编码顺序
  2. c++中的vector的常见使用
  3. 阿里云服务器部署项目
  4. Sping中利用HandlerExceptionResolver实现全局异常捕获
  5. pyspark性能调优参数
  6. python if elif else 区别
  7. LeetCode简单题之分糖果 II
  8. 硬件平台上深度学习自动内核优化
  9. 用TensorRT针对AArch64用户的交叉编译示例
  10. OpenCV读写视频文件解析(二)