TVM apps extension示例扩展库
此文件夹包含TVM的示例扩展库。演示了其它库如何在C++和Python API中扩展TVM。
该库扩展了TVM的功能。
python模块加载新的共享库,可以使用TVM的python API进行插值。
https://github.com/apache/tvm/tree/main/apps/extension

test_ext.py修改了一些代码




运行结果

TVM Runtime System
TVM支持多种编程语言用于编译器堆栈的开发和部署。将解释TVMRuntime的关键元素。

需要满足许多有趣的要求:

部署:从python/javascript/c++语言调用编译后的函数。

调试:在python中定义一个函数,从编译后的函数调用该函数。

链接:编写驱动程序代码,调用设备特定代码(CUDA),从编译后的主机函数中调用。

原型:从Python定义IR传递,从C++后端调用。

暴露:C++开发的编译器栈到前端(即,Python)

实验:将编译后的函数发送到嵌入式设备,直接运行。

希望能够从任何语言定义函数,从另一种语言调用函数。希望Runtime核心最小,部署到嵌入式设备。

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 and string
• PackedFunc itself
• Module for compiled modules
• DLTensor* for tensor object exchange
• TVM Object to represent any object in IR
该限制使得实现简单,无需序列化。尽管PackedFunc是最小的,对于深度学习部署的用例已经足够了,因为大多数函数只接受DLTensor或数字。
由于一个PACKEDFUNC可以采取另一个PACKEDFUNC作为参数,所以可以将函数从Python(如PackedFunc)传递到C++。
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返回
为了保持Runtime最小值,将IR对象支持与部署Runtime隔离。根据包含多少Runtime驱动程序模块(如CUDA),生成的Runtime大约需要200K-600K。

与普通函数相比,调用PackedFunc的开销很小,因为只在堆栈上保存了一些值。因此,只要不包装小函数就可以了。总之,PackedFunc是TVM中的通用粘合剂,在TVM中广泛使用,支持编译器和部署。
Module
由于TVM支持多种类型的设备,需要支持不同类型的驱动程序。必须使用驱动程序API加载内核,以压缩格式设置参数,执行内核启动。需要修补驱动程序API,以便公开的函数是线程安全的。因此,经常需要在C++中实现这些驱动程序GLUE,公开给用户。当然不能对每种类型的函数都这样做,所以PackedFunc也是答案。
TVM将编译对象定义为模块。用户可以从模块中以PackedFunc的形式获取编译后的函数。生成的编译代码可以在Runtime从模块中动态获取函数。在第一次调用中缓存函数句柄,在后续调用中重用。将设备代码和回调从生成的代码链接到任何PackedFunc(如python)中。
ModuleNode是一个抽象类,可以由每种类型的设备实现。到目前为止,支持CUDA、Metal、OpenCL和加载动态共享库的模块。这种抽象使得引入新设备变得容易,不需要为每种类型的设备重新生成主机代码。
远程部署
PackedFunc和模块系统可以轻松地将功能直接发送到远程设备。在后端,有一个RPCModule,序列化参数以进行数据移动,在远程启动计算。

RPC服务器本身是最小的,可以捆绑到Runtime中。可以在iPhone/android/raspberry pi甚至浏览器上,启动最小的TVM RPC服务器。服务器上的交叉编译和用于测试的模块的发布,可以在同一个脚本中完成。有关更多详细信息,请参考交叉编译和RPC。
这种即时反馈给了很多好处。例如,为了在iPhone上测试生成代码的正确性,不再需要从头开始用swift/objective-c编写测试用例——可以使用RPC在iPhone上执行,将结果复制,通过numpy在主机上进行验证。可以使用相同的脚本进行分析。
TVM对象和编译器堆栈
如前所述,在PackedFuncRuntime系统之上,构建编译器堆栈API。为了研究的需要,面临着编译器API的不断变化。每当想要测试新的原语时,都需要一个新的语言对象或IR节点。但是,不希望不时更改API。除此之外,
能够序列化任何语言对象和IRs
能够使用前端语言探索、打印和操作IR对象,进行快速原型制作。
引入了一个名为Object的基类,解决这个问题。编译器堆栈中的所有语言对象都是object的子类。每个对象都包含一个字符串类型type_key,该键唯一标识对象的类型。选择string而不是int作为类型键,可以以分散的方式添加新的对象类,无需将代码添加回中心repo。为了简化调度速度,在Runtime为每个type_key分配一个整数type_index。

因为通常一个对象可以在语言中的多个位置引用,所以使用一个共享的ptr跟踪引用。使用ObjectRef类表示对对象的引用。可以粗略地将ObjectRef类视为对象容器的shared_ptr。可以定义子类ObjectRef,保存对象的每个子类型。对象的每个子类都需要定义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) {}
// …
};
每个对象子类都将覆盖此项访问成员。下面是TensorNode的一个示例实现。
class TensorNode : public Object {
public:
/*! \brief The shape of the tensor /
Array 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);
}
};
在上面的示例中,操作和数组都是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++,便于对编译器堆栈进行扩展。这不是向成员公开前端语言的最快方法,但可能是最简单的方法之一。主要使用Python进行测试和原型开发,仍然使用C++完成繁重的工作。
实施详情
PackedFunc中的每个参数,都包含一个联合值TVMValue和一个类型代码。这种设计允许动态类型的语言,直接转换为相应的类型,静态类型的语言在转换过程中,进行运行时类型检查。
有关档案如下:
C++ API的PACKEDFUNC.H
c_runtime_api.cc用于c API,如何提供回调。
为了支持扩展类型,使用注册表系统登记类型相关信息,如C++中的任何支持,参阅扩展类型获取更多细节:https://github.com/apache/tvm/tree/main/apps/extension。

参考链接:
https://github.com/apache/tvm/tree/main/apps/extension
https://tvm.apache.org/docs/arch/runtime.html

TVM apps extension示例扩展库相关推荐

  1. linux php添加mysql扩展模块_linux下为php添加扩展库的方法

    本节内容: linux下添加php扩展库 这里以php curl 扩展库编译为例. 本次编译只是单独编译php的扩展库,然后将编译好的php扩展库加到现在运行的php中,不对现在运行的php重新编译, ...

  2. php 扩展库curl下载,PHP添加CURL扩展库的二种方法

    说明: 本次编译只是单独编译php的扩展库,然后将编译好的php扩展库加到现在运行的php中,不对现在运行的php重新编译,对现在运行的php没有任何影响. 有两种方法可以实现这一操作,下面分别介绍. ...

  3. PHP mysqli 扩展库(面向对象/数据库操作封装/事务控制/预编译)

    1.和mysql扩展库的区别: (1   安全性.稳定性更高 (2  提供了面向对象和面向过程两种风格 2.php.ini  中的  extension=php_mysqli.dll 解除封印 3.面 ...

  4. PHP如何添加自带的扩展库

    当服务器上PHP已经安装好,需要额外添加PHP扩展时怎么办?不需要重新安装PHP,有了phpize我们可以在原有的PHP基础之上直接安装扩展库. 这次编译仅仅只是单独编译PHP的扩展库,接下来将编译好 ...

  5. zlib 离线安装_黑板派Python扩展库安装与常见问题解决完整指南

    点击蓝字 ! 关注我们 "Python小屋"编程比赛正式开始 推荐图书: <Python程序设计(第3版)>,(ISBN:978-7-302-55083-9),董付国, ...

  6. 微软一站式示例代码库 7月新代码示例发布

    微软一站式示例代码库 7月新代码示例发布. 下载地址: http://1code.codeplex.com/releases/view/69942 你也可以通过 示例代码浏览器 或 示例代码浏览器Vi ...

  7. 小结两种在Python中导入C语言扩展库的方法

    小结两种在Python中导入C语言扩展库的方法 分类: Pythoner2009-08-18 20:44 2563人阅读 评论(1) 收藏 举报 python扩展c语言importstring 一种是 ...

  8. 微软一站式示例代码库 2012 年2月示例代码更新。8个全新示例为您的开发保驾护航...

    微软一站式示例代码库2012年2月新代码示例发布.我们发布了8个全新的示例代码,内容包含Windows Azure, Directory Services, Hyper-V, TFS, WDK和Win ...

  9. 1cocos2dx扩展库UI控件,CCControlSlider,CCScale9Sprite(九妹图),CCControlSwitch,CCControlButton

     UI控件来自cocos2dx的扩展库,完善了UI方面的元素,使cocos2dx更加丰富多彩.使用扩展库需包含: #include "cocos-ext.h" USING_NS ...

最新文章

  1. Linux网站架构系列之Apache----进阶篇
  2. Python持续点火,跟进还是观望?
  3. 龙芯服务器cpu支持最大数量,龙芯启动全国六个适配中心:加速生态建设
  4. framebuffer小程序显示3个矩形 测试
  5. python安装numba_python – 在OS X上安装Numba时出错
  6. pyqt5教程13:客户定制组件
  7. 练字究竟练的是什么?
  8. linux常见命令_Linux系统常见命令
  9. 音视频低延迟应用的四个技术实践
  10. 技术分享|手机推送原理剖析指南
  11. me shy是什么歌 抖音make_内含活动福利 | 小红书、抖音爆赞的高颜值的北欧家居神店开到卜蜂中心啦!...
  12. 格密码教程(六):高斯二维格规约,解决SVP问题
  13. Python批量Excel文件数据导入SQLite数据库的优化方案
  14. 2014-06-13 jq chart
  15. 国科微电子:芯片将是国内企业下一个发力点
  16. 袖珍计算器c语言设计源码,VB程序题:编一模拟袖珍计算器的完整程序,界面如下图所示。要求:输入两个操作数和一个操作符,根据操作符决定所做的运算。 VB源码 龚沛曾...
  17. Unity与 DLL文件 ☀️| 怎样使用 C# 类库 生成一个DLL文件 并 调用!
  18. ruoyi-vue集成积木报表
  19. 【leetcode】电话号码的字母组合
  20. Java中开根号,你还记得吗

热门文章

  1. 2022-2028年中国养老保险行业深度调研及投资前景预测报告
  2. 2022-2028年中国磷肥工业投资分析及前景预测报告
  3. lightgbm 决策树 可视化 graphviz
  4. python压缩和解压缩
  5. LeetCode简单题之二叉树的最大深度
  6. ONNX MLIR应用示例(含源码链接)
  7. Battery electric vehicles (BEVs) 快充技术
  8. YOLO v1到YOLO v4(下)
  9. 面部表情视频中进行远程心率测量:ICCV2019论文解析
  10. 2021年大数据Flink(二十三):​​​​​​​Watermaker案例演示