TVM运行时系统

2023-05-16

本文翻译自TVM Runtime System — tvm 0.9.dev0 documentation

TVM的编译器栈开发和部署支持多种编程语言。在本文中,我们将解释TVM运行时的关键元素。

我们需要满足一些有趣的需求:

  • 部署:从python/javascript/c++语言调用编译后的函数。
  • 调试:在python中定义一个函数,并从编译后的函数中调用它。
  • 链接:编写驱动程序代码调用设备特定代码(CUDA),并从编译后的host侧函数调用它。
  • Prototype:用python定义一个IR pass,并从c++后端调用它。
  • 公开:用c++开发的编译器栈到前端(python)
  • 实验:将编译好的函数发布到嵌入式设备上,并直接在设备上运行。

我们希望能够用任何语言定义函数,并在另一种语言中调用该函数。我们还希望最小化运行时核心,以便部署到嵌入式设备上。

PackedFunc

PackedFunc是我们找到的解决上述挑战的一个简单而优雅的解决方案。一个单独的PackedFunc对象表示一个调用者和被调用者可能使用不同语言的函数调用。

下面的代码块提供了一个C++示例:

#include <tvm/runtime/packed_func.h>

void MyAdd(TVMArgs args, TVMRetValue* rv) {
  // automatically convert arguments to desired type.
  int a = args[0];
  int b = args[1];
  // automatically assign value return to rv
  *rv = a + b;
}

void CallPacked() {
  PackedFunc myadd = PackedFunc(MyAdd);
  // get back 3
  int c = myadd(1, 2);
}

在上面的代码块中,我们定义了一个PackedFunc MyAdd。它接受两个参数:args表示输入参数,rv表示返回值。该函数是类型擦除的,这意味着函数签名不限制传递的输入类型或返回的类型。在底层,当我们调用PackedFunc时,它将输入参数打包到栈上的TVMArgs,并通过TVMRetValue返回结果。

多亏了C++中的模板技巧,我们可以像调用普通函数一样调用PackedFunc。由于它的类型擦除特性,我们可以从python等动态语言中调用PackedFunc,而不需要为创建的每个新类型函数添加额外的胶水代码。下面的例子在C++中注册了PackedFunc,并从python中调用。 

// register a global packed function in c++
TVM_REGISTER_GLOBAL("myadd")
.set_body(MyAdd);

import tvm

myadd = tvm.get_global_func("myadd")
# prints 3
print(myadd(1, 2))

 PackedFunc最神奇的地方在于TVMArgs和TVMRetValue结构。我们限定了可传递的数据类型。以下是常见类型:

  • Int, float和string
  • PackedFunc本身
  • 编译得到的模块
  • 表示张量对象交换的DLTensor*
  • 用于表示IR中的任何对象的TVM Object 

这个限定使实现变得简单,不需要对数据做序列化。尽管只支持少数几种类型,但PackedFunc对于深度学习部署的用例来说已经足够了,因为大多数函数只使用DLTensor或数字。

因为一个PackedFunc可以接受另一个PackedFunc作为实参,所以我们可以将函数从Python传递给C++ (PackedFunc)。

TVM_REGISTER_GLOBAL("callhello")
.set_body([](TVMArgs args, TVMRetValue* rv) {
  PackedFunc f = args[0];
  f("hello world");
});

import tvm

def callback(msg):
  print(msg)

# convert to PackedFunc
f = tvm.convert(callback)
callhello = tvm.get_global_func("callhello")
# prints hello world
callhello(f)

 TVM提供了一个最小的C API,它允许我们将PackedFunc 嵌入到任何语言中。除了python,到目前为止我们还支持java和javascript。这种嵌入式API的原理与Lua非常相似,只是我们没有新的语言,而是使用了C++。

关于PackedFunc的一个有趣的事实是,我们将它用于编译器和部署栈。

  • 所有TVM的编译器pass函数都作为PackedFunc公开给前端
  • 编译后的模块还将编译后的函数以PackedFunc返回

为了使运行时最小化,我们将IR对象支持与部署运行时隔离开来。最终的运行时模块大小大约需要200K - 600K,这取决于包含了多少运行时驱动模块(例如CUDA)。

与普通函数相比,调用PackedFunc的开销很小,因为它只在堆栈上保存一些值。所以只要我们不包装小函数就没问题。总之,PackedFunc是TVM中的通用粘合剂,我们广泛地使用它来支持我们的编译器和部署。

 Module

由于TVM支持多种类型的设备,我们需要支持不同类型的驱动程序。我们必须使用驱动程序API来加载内核,以压缩格式设置参数并执行内核启动。我们还需要修补驱动程序API,以便公开的函数是线程安全的。因此,我们经常需要在C++中实现这些驱动程序胶水代码,并将它们公开给用户。我们当然不能对每种类型的函数都这样做,所以PackedFunc再次成为我们的方案。

TVM将编译后的对象定义为Module。用户可以从Module中获取编译后的函数PackedFunc。生成的编译代码可以在运行时动态地从Module中获取函数。它在第一次调用中缓存函数句柄,并在后续调用中重用。我们使用它来链接设备代码并回调到任何PackedFunc(例如Python)。

ModuleNode是一个抽象类,可以由每种类型的设备实现。到目前为止,我们支持CUDA、Metal、OpenCL模块和加载动态共享库。这种抽象使得引入新设备变得容易,而且我们不需要为每种类型的设备重新生成host侧代码。

远程部署 

PackedFunc和Module系统还可以很容易地将函数直接发送到远程设备。在幕后,我们有一个RPCModule,它序列化参数来进行数据移动,并远程启动计算。

RPC服务器本身很小,可以绑定到运行时中。我们可以在iPhone/android/树莓派甚至浏览器上启动一个最小的TVM RPC服务器。服务器上的交叉编译和测试模块的交付可以在同一个脚本中完成。更多细节可以参阅。

这种即时反馈给了我们很多优势。例如,为了测试在iPhone上生成的代码的正确性,我们不再需要在swift/objective-c中从头开始编写测试用例——我们可以使用RPC在iPhone上执行,将结果复制回来,并通过numpy在主机上进行验证。我们还可以使用相同的脚本进行分析。

如前所述,我们在PackedFunc运行时系统之上构建编译器栈API。为了研究的需要,我们面临着编译器API的不断变化。当我们想测试新的原语时,我们需要一个新的语言对象或IR节点。但是,我们不想时不时地改变我们的API。除此之外,我们也想

  • 能够序列化任何语言对象和ir
  • 能够探索,打印和操作IR对象在前端语言做快速原型。

 我们引入了一个名为Object的基类来解决这个问题。编译器栈中的所有语言对象都是Object的子类。每个对象都包含一个唯一标识对象类型的字符串type_key。我们选择string而不是int作为类型键,这样就可以以分散的方式添加新的Object类,而无需将代码添加回中央回购器。为了简化分派的速度,我们在运行时为每个type_key分配一个整数type_index。

因为通常一个Object可以在语言中的多个地方被引用,所以我们使用shared_ptr来跟踪引用。我们使用ObjectRef类来表示对Object的引用。我们可以粗略地将ObjectRef类视为Object容器的shared_ptr。还可以定义子类ObjectRef来保存Object的每个子类型。Object的每个子类都需要定义VisitAttr函数。

class AttrVisitor {
public:
  virtual void Visit(const char* key, double* value) = 0;
  virtual void Visit(const char* key, int64_t* value) = 0;
  virtual void Visit(const char* key, uint64_t* value) = 0;
  virtual void Visit(const char* key, int* value) = 0;
  virtual void Visit(const char* key, bool* value) = 0;
  virtual void Visit(const char* key, std::string* value) = 0;
  virtual void Visit(const char* key, void** value) = 0;
  virtual void Visit(const char* key, Type* value) = 0;
  virtual void Visit(const char* key, ObjectRef* value) = 0;
  // ...
};

class BaseAttrsNode : public Object {
public:
  virtual void VisitAttrs(AttrVisitor* v) {}
  // ...
};

 每个Object子类都将重载它来访问它的成员。下面是TensorNode的一个示例实现。

class TensorNode : public Object {
public:
  /*! \brief The shape of the tensor */
  Array<Expr> shape;
  /*! \brief data type in the content of the tensor */
  Type dtype;
  /*! \brief the source operation, can be None */
  Operation op;
  /*! \brief the output index from source operation */
  int value_index{0};
  /*! \brief constructor */
  TensorNode() {}

  void VisitAttrs(AttrVisitor* v) final {
    v->Visit("shape", &shape);
    v->Visit("dtype", &dtype);
    v->Visit("op", &op);
    v->Visit("value_index", &value_index);
  }
};

在上面的例子中,Operation和 Array<Expr>是ObjectRef。VisitAttrs为我们提供了一个反射API来访问对象的每个成员。我们可以使用这个函数访问节点并递归地序列化任何语言对象。它还允许我们在前端语言中轻松获取对象的成员。例如,在下面的代码中,我们访问了TensorNode的op字段。

import tvm
from tvm import te

x = te.placeholder((3,4), name="x")
# access the op field of TensorNode
print(x.op.name)

可以在不改变前端运行时的情况下向C++中添加新的Object,这使得对编译器栈进行扩展变得很容易。注意,这不是向前端语言公开成员的最快方法,但可能是最简单的方法之一。我们还发现它符合我们的目的,因为我们主要使用python进行测试和原型设计,而仍然使用C++来完成繁重的工作。

实现细节

PackedFunc中的每个参数都包含一个联合值TVMValue和一个类型编码。这种设计允许动态类型语言直接转换为相应的类型,而静态类型语言可以在转换期间进行运行时类型检查。 

相关文件如下:

  • packed_func.h : C++ API

  • c_runtime_api.cc : C API和如何提供回调。

为了支持扩展类型,我们使用了一个注册系统来注册与类型相关的信息,类似C++中对任何类型的支持,参见扩展类型了解更多细节。 

具体运行时信息 

  • Vulkan Runtime
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TVM运行时系统 的相关文章

  • TVM在Windows10下编译安装

    本教程记录了Windows端安装tvm的过程 xff0c 欢迎交流 教程参考 TVM Windows下全功能编译方法 xff1a 从入门到劝退 https blog csdn net znsoft article details 11503
  • 【KAWAKO】TVM-在ubuntu服务器上的安装

    目录 下载源码 安装依赖库 修改config cmake文件 编译 安装python库 添加tophub 简单验证 官方的安装教程在这里 下载源码 从Download Page中下载下来的源码是0 8版本的 xff0c 亲测该版本不可用 x
  • 冯思远:Apache TVM 与机器学习编译发展

    下午好 欢迎大家今天来参加 2023 Meet TVM 作为 Apache TVM PMC 由我来给大家做关于 TVM 的发展以及 TVM 未来 Unity 框架的分享 Apache TVM Evolution 首先为什么会有 MLC Ma
  • TVM张量表达式

    Get Started with Tensor Expression TVM使用一个定义域特定张量表达式来高效地构造核 In 1 import tvm import tvm testing from tvm import te import
  • 编译 Keras 模型

    本篇文章译自英文文档 Compile Keras Models 作者是 Yuwei Hu 更多 TVM 中文文档可访问 TVM 中文站 本文介绍如何用 Relay 部署 Keras 模型 首先安装 Keras 和 TensorFlow 可通
  • TVM中python访问c++函数机制

    data TVM tvm python tvm ffi registry py data TVM tvm python tvm ffi registry py data TVM tvm python tvm ffi ctypes packe
  • TVM User Tutorial -- Blitz Course to TensorIR

    Author Siyuan Feng TensorIR 是一种特定领域语言 用于深度学习项目 有两个广泛的用途 在各种硬件后端上实现转换和优化程序 自动张力化程序优化的抽象 import tvm from tvm ir module imp
  • AutoSchedule和AutoTVM

    简介 AutoTVM 用户自己手写一个模版 在模版里面自己定义一下tune的参数 例如tile size等 给定一个模版 在这个模版里面去搜索参数 使得可以达到一组最好的参数使得张量计算的结果最好 但是 它是一种基于模板的方法 因此仍然需要
  • 【开发环境】Windows下搭建TVM编译器

    关于搭建TVM编译器的官方文档 Install from Source tvm 0 14 dev0 documentation apache org 1 安装Anaconda 首先我们需要安装Anaconda 因为其中包含着我们所需要的各类
  • TVM的安装过程

    最近在看深度学习编译器相关的工作 其中FlexTensor给我留下了比较深刻的印象 加上这项工作是开源的 所以想看看这份工作的源码 首先是怎么把工程跑起来 FlexTensor倚仗TVM做代码生成 所以首先得安装TVM 首先给出官方网站的安
  • 【TVM 学习资料】使用 Python 接口(AutoTVM)编译和优化模型

    本篇文章译自英文文档 Compiling and Optimizing a Model with the Python Interface AutoTVM 作者是 Chris Hoge 更多 TVM 中文文档可访问 TVM 中文站 TVMC
  • TVM概述

    TVM TVM是陈天奇领导的一个DL加速框架项目 它处于DL框架 如tensorflow pytorch 和硬件后端 如CUDA OpenCL 之间 兼顾了前者的易用性和后者的执行效率 官网 https tvm apache org 代码
  • TVM 结构学习总结

    最近对深度学习编译器TVM学习了一下 了解各部分的功能 根据自己的理解进行总结 如有不正确请指正 话不多说上脑图 TVM为解决各种深度学习训练框架的模型部署到各种硬件而诞生 下图是TVM经典技术栈图 编译器层次抽象 编译器前端 接收C C
  • TVM(一):简介与安装

    简介 TVM是一个用于深度学习系统的编译器堆栈 它旨在缩小以生产力为中心的深度学习框架与以性能和效率为中心的硬件后端之间的差距 TVM与深度学习框架合作 为不同的后端提供端到端编译 换句话说 TVM就是一种将深度学习工作负载部署到硬件的端到
  • TVM编译安装

    本文是在已大致了解tvm功能和架构的基础上 根据官方文档 在x86 64 Ubuntu 18 04 GPU Pytorch1 8 0上安装TVM的流程 参考文档 TVM安装官方文档 llvm下载链接 1 下载源代码 从tvm官网下载源代码
  • TVM编译pytorch模型

    编译PyTorch模型 加载预训练的PyTorch模型 加载测试图像 将图形导入到Relay 构建Relay 在TVM上执行可移植图形 查找同义词集名称 本文是介绍如何使用Relay部署PyTorch模型的入门教程 首先 应该安装PyTor
  • windows11安装wsl2(linux)+VScode+ miniconda+TVM+python环境部署

    在wsl上运行 TVM demo 环境配置 预备加速工具 vpn 清华镜像 第一次安装 失败 1 Windows11 D盘安装wls linux 2 安装vscode并连接到WSL2 3 wsl 安装miniconda 4 wls安装TVM
  • iOS编程基础-OC(八)-运行时系统的结构(续)

    该系列文章系个人读书笔记及总结性内容 任何组织和个人不得转载进行商业活动 第八章 运行时系统的结构 8 1 2 运行时系统库 苹果公司提供的OC运行时系统库实现了OC的面向对象特性和动态属性 多数情况下 运行时系统库是在后台起作用 但也拥有
  • TVM系列---1.开始使用Tensor Expression

    Author Tianqi Chen https docs tvm ai tutorials tensor expr get started html Tensor Expression入门 这是TVM中Tensor表达语言的入门教程 TV
  • 【tvm官网教程01】设计和架构-1

    tvm官网教程01 设计和架构 1 目的 1 编译流 1 1 关键数据结构 1 2 Transformations 1 2 1 变换的分类 1 2 2 relay transform 1 2 2 1 子函数 1 2 2 2 overall问

随机推荐

  • uboot编译报错 dtc: command not found解决办法

    编译uboot 报错 解决办法 span class token function sudo span span class token function apt get span span class token function ins
  • 解决imx6ull开发板加载驱动disagrees about version of symbol module_layout失败问题

    一 环境 1 硬件 100ask imx6ull单板 2 软件环境 xff0c 提供的开发环境 二 报错信息 hello drv disagrees about version of symbol module layout insmod
  • 应用软件安装

    在进行开发中 xff0c 会使用到很多各种类型的软件 xff0c 现在将其进行整理 xff0c 列表如下 xff0c 如有需要 xff0c 请给我留言 xff0c 我可以给分享给大家 001 application software 序号
  • 安装树莓派的系统到SD卡

    安装树莓派的系统到 SD卡 准备工作 1 一张 16G 以上的 SD 卡 xff0c 最好是高速卡 xff0c 推荐 Class4 以上的卡 xff0c 因为卡得速度直接影响树莓派的运行速度 2 格式化SD卡工具 xff0c 建议使用工具
  • 串口测试例程

    串口分为RS232和TTL xff0c 所以在测试前请先确认自己的串口类型进行测试 下面以海思的一个RS232串口为例说明一下具体的测试过程 xff0c 串口测试代码参考的为讯为提供的 xff0c 在其基础上做的调整 1 确定接口 xff0
  • C语言中的字符串初始化

    1 C语言没有字符串类型 xff0c 通过字符数组模拟 xff0c C语言字符串 xff0c 以字符 0 数字0 2 数组指定长度后 xff0c 后面没有赋值的元素 xff0c 自动补0 char buf 100 61 39 a 39 39
  • 自动收取蚂蚁森林能量雨

    首先 xff0c 说明一下 这是一个非常迂回且效果不佳的方法 xff0c 小弟不才 xff0c 安卓以及苹果手机上的脚本没啥研究 xff0c PC的按键精灵略懂 xff0c 因此才有一下脚本 觉得有用拿去参考 xff0c 大佬勿喷 我一直都
  • AD中画圆弧形板框的方法

    在实际的板框设计中 xff0c 有时为了生产需要 xff0c 不得不需要将PCB板设计成四角需要倒角的形式 xff0c 经过实际的摸索 xff0c 现在得出一种画圆形板框的小技巧 现在需要将板框设计成3 5mm半径样式 xff08 1 xf
  • AD中板内挖空的方法

    一 先使用禁止布线层将板框确定 使用的快捷键 xff1a D gt S gt D 二 再绘制一个挖空区域 使用的快捷键 xff1a T gt V gt B 三 挖空后的效果
  • STL初识

    STL的诞生 长久以来 xff0c 软件界一直希望建立一种可重复利用的东西 C 43 43 的面向对象和泛型编程思想 xff0c 目的就是复用性的提升 大多情况下 xff0c 数据结构和算法都未能有一套标准 导致被迫从事大量重复工作 为了建
  • 删除U盘中的System Volume Information 文件夹的方法

    在使用U盘测试ARM板的时候 xff0c 会发现System Volume Information这个文件夹阴魂不散 xff0c 总是存在 xff0c 在Windows下是看不见的 xff0c 即便将文件的查看属性设置为显示隐藏文件 在使用
  • Linux命令发送Http的get或post请求

    get请求 curl命令模拟get请求 xff1a 1 使用curl命令 xff1a curl span class hljs string 34 http www baidu com 34 span 如果这里的URL指向的是一个文件或者一
  • 深度学习之----多任务学习

    介绍 在机器学习 xff08 ML xff09 中 xff0c 通常的关注点是对特定度量进行优化 xff0c 度量有很多种 xff0c 例如特定基准或商业 KPI 的分数 为了做到这一点 xff0c 我们通常训练一个模型或模型组合来执行目标
  • PID控制原理(全干货)

    主要内容 xff1a 1 常用的控制算法与PID控制算法的异同点 xff1b 2 PID控制算法的理论分析 3 基于单片机的PID算法实现 4 PID算法的工程应用的一些注意事项 5 演示板电路分析 6 PID算法C语言实现 基于ARM C
  • ESP32 手册+文档整理

    ESP32 一些手册和批注 Arduino IDE 这个板子是带了LoRa的版本 xff0c 国外还有一个TTGo 有类似的ESP32 43 LoRa这种组合 如果不需要LoRa xff0c 可以考虑ESP32 DevKit 或者PicoK
  • 【TVM帮助文档学习】TVM语言参考

    本文翻译自Language Reference tvm 0 9 dev0 documentation 本文档提供TVM的嵌入式语言和IRs的参考 Relay介绍 Relay 是一种函数式的 可微的编程语言 它是一种面对机器学习领域的具有良好
  • 【TVM帮助文档学习】通过示例分析TVM代码流程

    本文翻译自TVM Codebase Walkthrough by Example tvm 0 9 dev0 documentation 了解TVM代码颇具挑战性 xff0c 它的各组件之间的交互非常隐晦 在本指南中 xff0c 我们将通过一
  • Linux设置nacos自启动(centos7)

    1 编写服务脚本 vim lib systemd system nacos service 将下列内容添加进入 span class token punctuation span Unit span class token punctuat
  • 图像处理——Haar特征

    Haar特征最初是用来进行人脸特征的表示的 xff0c 最近重新看了SURF算法 xff0c 发现在生成特征点描述子的时候也有用到Haar特征 查看了一些博文 xff0c 自己整理一些 xff0c 方便以后复习 Haar特征分为三类 xff
  • TVM运行时系统

    本文翻译自TVM Runtime System tvm 0 9 dev0 documentation TVM的编译器栈开发和部署支持多种编程语言 在本文中 xff0c 我们将解释TVM运行时的关键元素 我们需要满足一些有趣的需求 部署 从p