任何新的运行时环境都必须实现三个主要方面:

  • DeviceAPI类为特定设备提供了一个句柄,以及用于与之交互的API。它定义了一个通用接口,用于查询设备参数(例如可用内存、线程数量等)和执行简单操作(例如从主机复制内存,或在设备的缓冲区之间复制内存)
  • Target类包含函数将在其上运行的设备的描述。它同时暴露给目标代码生成器和优化pass。
  • 目标代码生成器从IRModule构造一个由一个或多个PackedFunc组成的Module。

DeviceAPI

DeviceAPI表示特定硬件设备API的句柄(例如CUDADeviceAPI通过CUDA框架处理所有的交互)。大多数DeviceAPI方法接受device_id参数来指定应该访问哪个设备。在Python中,通常使用tvm.runtime.device()函数通过特定的API访问特定设备,返回设备的句柄(例如tvm.runtime.device('cuda',0)通过cuda API提供对物理设备0的访问) 。

  • 属性查询(Attribute queries)——GetAttr允许查询设备的各种参数,如设备名称、线程数等。可查询的参数定义在device_api.h中的DeviceAttrKind enum中。并非所有设备都支持该enum中定义的所有可查询参数。如果一个参数不能被查询(例如Vulkan上的kMaxClockRate),或者一个参数不适用(例如CPU上的kWarpSize),那么这些查询应该返回nullptr。

  • 设置活动设备(Setting active device)SetDevice应该将特定设备设置为活动设备。如果由特定目标的代码生成的PackedFunc需要在一个设备上执行,它应该在活动设备上运行。

  • 内存管理(Memory management)——用于在设备上分配和释放内存的实用程序。

  • 分配数据空间(Allocate data space) AllocDataSpaceFreeDataSpace用于分配和释放设备上的空间。这些分配的空间可以提供给算子的输入和输出,并构成算子图的主要数据流。必须能够在主机和设备数据空间之间传输数据。返回一个不透明的void。虽然有些实现返回内存地址,但这不是必需的,而且void可能是一个不透明的句柄,只有生成它的设备后端才能解释它。void*被用作其他后端特定函数的参数,例如CopyDataFromTo。
  • 分配工作空间(Allocate work space)AllocWorkspaceFreeWorkspace分别分配和释放设备上的空间。与数据空间不同的是,它们用于存储算子定义中的中间值,并且不要求可在主机和设备间转移。如果DeviceAPI子类没有实现这些方法,它们将默认调用父类相应的DataSpace函数。
  • 复制数据(Copy data)CopyDataFromTo应该将数据从一个位置复制到另一个位置。复制的类型由dev_from和dev_to参数确定实现应该支持在单个设备上将内存从CPU复制到设备、从设备复制到CPU、从一个缓冲区复制到另一个缓冲区。如果源或目标位置在CPU上,对应的void指向一个CPU地址,该地址可以传递给memcpy。如果源或目标位置在设备上,则相应的void是此前由AllocDataSpaceAllocWorkspace生成的。

    这些拷贝在特定的TVMStreamHandle上排队执行。但是,实现不应该假设CPU缓冲区在CopyDataFromTo调用完成后仍然有效或可访问。
  • 执行流管理(Execution stream management)——用于处理TVMStreamHandle的实用程序,它表示用于执行命令的并行执行流。
  • 创建流(Create stream)——CreateStreamFreeStream应该为执行流分配/释放一个句柄。如果一个设备只实现一个命令队列,那么CreateStream应该返回nullptr。
  • 设置活动流(Set active stream)SetStream应该将一个流设置为活动流。在活动时,如果特定目标的代码生成器生成的PackedFunc需要在设备上执行,那么工作应该提交给活动流。
  • 同步到CPU(Synchronize to CPU)——StreamSync应该同步一个执行流到CPU。对StreamSync的调用应该在StreamSync完成之前,返回提交的所有内存传输和计算。
  • 流之间的同步(Synchronize between streams)——SyncStreamFromTo应该在源流和目标流之间引入同步栅栏。也就是说,在源流完成当前队列中的所有命令之前,目标流不能超越队列中的当前命令。

为了能够被TVM框架使用,新的DeviceAPI应该按照以下步骤注册:

1.创建一个实例化新DeviceAPI的函数,并返回一个指向它的指针:

FooDeviceAPI* FooDeviceAPI::Global() {
static FooDeviceAPI inst;
return &inst;
}
  1. 将该函数注册到tvm注册表:
TVM_REGISTER_GLOBAL("device_api.foo").set_body_typed(FooDeviceAPI::Global);

(1) 在c_runtime_api.hTVMDeviceExtType enum中添加新DeviceAPI的条目。该值应该是一个大于DLDeviceType::kDLExtDev但小于DeviceAPIManager::kMaxDeviceAPI的未使用的值。

(2) 在device_api.h中的DeviceName中添加条件分支,将enum值转换为对应字符串。这个字符串表示应该匹配对应的TVM_REGISTER_GLOBAL注册名称

(3) 在tmv .runtime. device的MASK2STR和STR2MASK字典中,为新的enum值添加条目。

Target Definition

Target对象是一个关于物理设备、其硬件/驱动程序限制及其功能的属性的查找表。在优化和代码生成阶段都可以访问Target。虽然对所有运行时目标使用相同的Target类,但每个运行时目标可能需要添加特定于目标的选项。

target_kind.cc中,添加TVM_REGISTER_TARGET_KIND的新声明,传递新目标的字符串名称,以及运行该目标的设备的TVMDeviceExtTypeDLDeviceType enum值。通常,目标名称和设备名称是匹配的(例如,“cuda”目标运行在kDLCUDA设备上)。 但也有例外,比如多个不同的代码生成目标可以在同一个物理设备上运行(例如"llvm"和"c"目标都运行在kDLCPU设备类型上)。

特定目标类型的所有选项都是用add_attr_option函数添加的,带有可选的默认值。可以使用set_attrs_preprocessor添加预处理器,以定义任何参数,这些参数是动态地基于其他参数或从设备属性查询的

这个参数定义定义了一个解析器,该解析器可以解析目标的字符串描述。这是在c++的Target::Target(const string &)构造函数中完成的,该构造函数接受json格式的字符串,通常使用python对象tvm.target.Target调用。例如,tvm.target。目标('{"kind": "cuda", "max_num_threads": 1024}')将创建一个cuda目标,同时覆盖默认的最大线程数。

在代码生成器中,可以使用C++中的target->GetAttr<T>(param_name), 或者使用Python中的target.attrs字典访问目标属性。

Target Code Generators

代码生成器接受一个优化的IRModule,并将其转换为可执行的表示形式。 每个代码生成器都必须注册才能被TVM框架使用。这是通过注册一个名为target.build.foo的函数来完成的, foo与上面TVM_REGISTER_TARGET_KIND定义中使用的名称相同。

tvm::runtime::Module GeneratorFooCode(IRModule mod, Target target);
TVM_REGISTER_GLOBAL("target.build.foo").set_body_typed(GeneratorFooCode);

代码生成器接受两个参数。

第一个是要编译的IRModule

第二个是描述代码应该在其上运行的设备的Target。因为执行编译的环境不一定与将要执行代码的环境相同,所以代码生成器不应该对设备本身执行任何属性查找,而是应该访问存储在Target中的参数。

输入IRModule中的每个函数,都应该在输出runtime::Module中可以通过名称访问

TVM: Device/Target Interactions的更多相关文章

  1. 桥接PyTorch和TVM

    桥接PyTorch和TVM 人工智能最引人入胜的一些应用是自然语言处理.像BERT或GPT-2之类的模型及其变体,可以获住足够多的文本信息. 这些模型属于称为Transformers的神经网络类体系结 ...

  2. TVM交叉编译和远程RPC

    TVM交叉编译和远程RPC 本文介绍了TVM中使用RPC的交叉编译和远程设备执行. 使用交叉编译和RPC,可以在本地计算机上编译程序,然后在远程设备上运行它.当远程设备资源受到限制时(如Raspber ...

  3. TVM性能评估分析(二)

    TVM性能评估分析(二) Figure 1.  A bird's eye view of the µTVM + AutoTVM infrastructure Figure 2.  A standard ...

  4. TVM部署预定义模型

    TVM部署预定义模型 本文通过深度学习框架量化的模型加载到TVM中.预量化的模型导入是在TVM中提供的量化支持之一. 本文演示如何加载和运行由PyTorch,MXNet和TFLite量化的模型.加载后 ...

  5. TinyML-TVM是如何驯服Tiny的(上)

    TinyML-TVM是如何驯服Tiny的(上) 低成本.人工智能驱动的消费类设备的激增,导致了ML研究人员和从业者对"裸智能"(低功耗,通常没有操作系统)设备的广泛兴趣.虽然专家已 ...

  6. ARM-CPU卷积网络的自动调谐

    ARM-CPU卷积网络的自动调谐 为特定的ARM设备自动调谐对于获得最佳性能至关重要.这是一个关于如何调整整个卷积网络的资料. 以模板的形式编写了TVM中ARM CPU的操作实现.模板有许多可调旋钮( ...

  7. logstash日志分析的配置和使用

    logstash是一个数据分析软件,主要目的是分析log日志.整一套软件可以当作一个MVC模型,logstash是controller层,Elasticsearch是一个model层,kibana是v ...

  8. KVM 介绍(5):libvirt 介绍 [ Libvrit for KVM/QEMU ]

    学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...

  9. WPF ListView和ListBox等双击事件问题

    上两篇文章中说双击行获取不到当前数据对象问题, http://www.cnblogs.com/ligl/p/5636899.html http://www.cnblogs.com/ligl/p/562 ...

  10. 第一个Java Rest服务

    package com.example; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import ...

随机推荐

  1. DOCKER20231217: 容器引擎Docker

    1.1 Docker简介 1.1.1 什么是Docker? 一种轻量级的操作系统虚拟化技术,基于Go语言实现的开源容器项目,诞生于2013年,最初发起者是dotCloud公司(现 Docker Inc ...

  2. Typora - typora主题样式

    主题名称:github_harley.css(随便命名) 效果:Mac风格的代码块.更舒适的引用块风格. css harley01 /* 代码块主题 */ /* 顶部 */ .md-fences { ...

  3. 大数据之路Week10_day04 (Hbase的二级索引,二级索引的本质就是建立各列值与行键之间的映射关系)

    二级索引的本质就是建立各列值与行键之间的映射关系 HBASE是在hadoop之上构建非关系型,面向列存储的开源分布式结构化数据存储系统. Hbase的局限性: HBase本身只提供基于行键和全表扫描的 ...

  4. DeepSeek 不太稳定?那就搭建自己的 DeepSeek 服务

    概述 DeepSeek-R1 发布 DeepSeek 在 2025 年给我们送来一份惊喜,1 月 20 号正式发布第一代推理大模型 DeepSeek-R1.这个模型在数学推理.代码生成和复杂问题解决等 ...

  5. postgresql使用for循环

    开发过程中经常需要制造一些测试数据,sqlserver等数据库都有循环执行语句的方式,postgresql也可以使用for循环插入数据 do $$ begin for tt in 1..99 loop ...

  6. 基于正则化的图自编码器在推荐算法中的应用 Application of graph auto-encoders based on regularization in recommendation algorithms

    引言 看过的每一篇文章,都是对自己的提高.不积跬步无以至千里,不积小流无以成江海,积少成多,做更好的自己. 本文基于2023年4月6日发表于SCIPEERJ COMPUTER SCIENCE(PEER ...

  7. 【Matlab】求解复合材料层合板刚度矩阵及柔度矩阵

    1. matlab文件结构 2. main.m代码 clc clear; warning off; %% %铺层角度数组 angles=[0 90 0]; % ° %单层厚度 ply_thicknes ...

  8. 虚拟机使用ESXi主机物理硬盘的办法

    虚拟机使用ESXi主机物理硬盘的办法 weixin_33928137 于 2018-06-19 15:22:06 发布 868 收藏 1文章标签: 运维版权 VMware Workstation的虚拟 ...

  9. Linux系统挂载未分配硬盘空间

    先查看未挂载之前的磁盘使用情况 发现磁盘使用率已经达到了96%,迫切需要扩容 查看分区情况fdisk –l 首先确保有可分配的磁盘空间 发现/dev/vda下有400多个G 的空间 所以将/dev/v ...

  10. (踩坑)windows本地部署Dify ,玩转智能体、知识库

      windows 安装docker windows 本地部署deepseek windows 通过docker本地部署dify     一:安装Docker 前提: 开启Hyper-V 打开 控制面 ...