向Relay添加算子
为了在Relay IR中使用TVM算子,需要在Relay中注册算子,以确保将其集成到Relay的类型系统中。
注册算子需要三个步骤:
• 使用RELAY_REGISTER_OPC ++中的宏注册算子的Arity和类型信息
• 定义一个C ++函数为算子生成一个调用节点,并为该函数注册一个Python API挂钩
• 将上述Python API挂钩包装在更整洁的界面中
该文件src/relay/op/tensor/binary.cc提供了前两个步骤的python/tvm/relay/op/tensor.py示例,同时提供了后两个步骤的示例。
注册算子
TVM已经具有算子注册表,如果没有其它类型信息,Relay无法正确合并TVM算子。
为了在注册算子时具有更大的灵活性,并在Relay中表达类型时,提高了表达性和粒度,使用输入和输出类型之间的关系来对算子进行类型化。这些关系表示为接受输入类型和输出类型的列表(这些类型中的任何一个都不完整),返回满足该关系的输入和输出类型的列表的函数。本质上,算子的关系除了计算输出类型外,还可以强制执行所有必要的键入规则(即,通过检查输入类型)。
例如,参阅src/relay/op/type_relations.h及其实现。例如,BroadcastRel接受两个输入类型和一个输出类型,都是具有相同基础数据类型的张量类型,最后确保输出类型的形状是输入类型的形状的广播。
type_relations.h 如果现有类型未捕获所需算子的行为,则可能有必要添加另一种类型关系。
使用RELAY_REGISTER_OPC ++中的宏,开发人员可以在Relay中指定有关算子的以下信息:
• Arity(参数个数)
• 位置参数的名称和说明
• 支持级别(1表示内部固有;较高的数字表示积分较少或不受外部支持的算子)
• 算子的类型关系
下面的示例来自binary.cc张量,并将其用于张量广播:
RELAY_REGISTER_OP(“add”)
.set_num_inputs(2)
.add_argument(“lhs”, “Tensor”, “The left hand side tensor.”)
.add_argument(“rhs”, “Tensor”, “The right hand side tensor.”)
.set_support_level(1)
.add_type_rel(“Broadcast”, BroadcastRel);
创建调用节点
此步骤仅需要简单地编写一个将参数带给算子的函数(如Relay表达式),然后将调用节点返回给算子(即,应将其放置在Relay AST中的节点,该AST是要向算子进行调用的位置)。
目前不支持调用属性和类型参数(最后两个字段),足以用于Op::Get从算子注册表中获取算子信息,并将参数传递给调用节点,如下所示。
TVM_REGISTER_GLOBAL(“relay.op._make.add”)
.set_body_typed<Expr(Expr, Expr)>([](Expr lhs, Expr rhs) {
static const Op& op = Op::Get(“add”);
return Call(op, {lhs, rhs}, Attrs(), {});
});
包括Python API挂钩
在Relay中通常是约定,通过导出的函数TVM_REGISTER_GLOBAL应该包装在单独的Python函数中,而不是在Python中直接调用。对于产生对算子的调用的函数,捆绑起来可能很方便,其中python/tvm/relay/op/tensor.py,都提供了张量上的元素算子。例如,以下是上一节中的add函数在Python中的显示方式:
def add(lhs, rhs):
“”"Elementwise addition.

Parameters
----------
lhs : relay.ExprThe left hand side input data
rhs : relay.ExprThe right hand side input dataReturns
-------
result : relay.ExprThe computed result.
"""
return _make.add(lhs, rhs)

这些Python库也可能是向算子提供更简单接口的好机会。例如,该 concat算子被注册为仅接受一个算子,即一个具有要连接的张量的元组,Python库将这些张量作为参数,组合成一个元组,然后生成调用节点:
def concat(*args):
“”"Concatenate the input tensors along the zero axis.

Parameters
----------
args: list of TensorReturns
-------
tensor: The concatenated tensor.
"""
tup = Tuple(list(args))
return _make.concat(tup)

梯度算子
梯度算子对于在Relay中编写可区分的程序很重要。尽管Relay的autodiff算法可以区分一流的语言结构,算子是不透明的。由于Relay无法调查实现,必须提供明确的区分规则。
Python和C ++均可用于编写梯度算子,将示例重点放在Python上,因为更常用。
在Python中添加渐变
可以找到Python梯度算子的集合 python/tvm/relay/op/_tensor_grad.py。将通过两个有代表性的示例:sigmoid和multiply。
@register_gradient(“sigmoid”)
def sigmoid_grad(orig, grad):
“”“Returns [grad * sigmoid(x) * (1 - sigmoid(x))].”""
return [grad * orig * (ones_like(orig) - orig)]
这里的输入是原始算子orig和grad要累加到的渐变。返回的是一个列表,其中第i个索引处的元素是算子相对于算子第i个输入的派生。通常,渐变将返回一个列表,其中包含与基本算子输入相同数量的元素。
在进一步分析这个定义之前,应该回想一下S型函数的导数: ∂σ∂x=σ(x)(1−σ(x))∂σ∂x=σ(x)(1−σ(x))。上面的定义看起来与数学定义相似,有一个重要的补充,将在下面进行描述。
该术语直接与导数匹配,因为这是S型函数,不仅对如何计算此函数的梯度感兴趣。有兴趣将此梯度与其它梯度组成,可以在整个程序中累积该梯度。这是该术语出现的地方。指定到目前为止如何用梯度组成导数。orig * (ones_like(orig) - orig)origgradgrad * orig * (ones_like(orig) - orig)grad
来看multiply一个更有趣的示例:
@register_gradient(“multiply”)
def multiply_grad(orig, grad):
“”“Returns [grad * y, grad * x]”""
x, y = orig.args
return [collapse_sum_like(grad * y, x),
collapse_sum_like(grad * x, y)]
在此示例中,返回列表中有两个元素, multiply是一个二进制算子。如果f(x,y)=xyf(x,y)=xy,偏导数是 ∂f∂x=y∂f∂x=y 和 ∂f∂y=x∂f∂y=x。
有一个必需的步骤,因为广播具有语义,multiply不需要。可能与输入的形状不匹配,习惯于获取术语的内容,并使形状与要区分的输入的形状相匹配。sigmoidmultiplygradcollapse_sum_likegrad *
在C ++中添加渐变
在C ++中添加渐变类似于在Python中添加渐变,注册的界面略有不同。
确保src/relay/pass/pattern_utils.h包含其中。提供了用于在Relay AST中创建节点的辅助功能。然后,以类似于Python示例的方式定义渐变:
tvm::Array MultiplyGrad(const Expr& orig_call, const Expr& output_grad) {
const Call& call = orig_call.Downcast();
return { CollapseSumLike(Multiply(output_grad, call.args[1]), call.args[0]),
CollapseSumLike(Multiply(output_grad, call.args[0]), call.args[1]) };
}
在C ++中,不能使用与Python中相同的算子重载,并且需要向下转换,实现更为冗长。即使这样,仍可以轻松地验证此定义,是否与Python中的先前示例相同。
代替使用Python渲染,需要set_attr在基本算子注册的末尾添加对“ FPrimalGradient”的调用,以注册渐变。
RELAY_REGISTER_OP(“multiply”)
// …
// Set other attributes
// …
.set_attr(“FPrimalGradient”, MultiplyGrad);
总结
• TVM算子可以使用表示适当类型信息的关系在中继中注册。
• 在中继中使用算子需要一个函数来为算子生成调用节点。
• 最好有一个简单的Python库来生成调用节点。

向Relay添加算子相关推荐

  1. 这可能是关于Pytorch底层算子扩展最详细的总结了!

    1.前言​ ​一般情况下,pytorch推荐使用python层的前端语言来构建新的算子.因为pytorch在python层的api已经足够丰富,可以构造出很多自定义的算子.但是有时候出于一些其他方面的 ...

  2. 带你了解AKG正反向算子注册+关联流程

    摘要:简要介绍一下akg正反向算子的注册和关联流程. 本文分享自华为云社区<AKG正反向算子注册+关联>,作者:木子_007 . 一.环境 硬件:eulerosv2r8.aarch64 m ...

  3. 基于OneFlow实现Unfold、Fold算子

    撰文 | zzk 1 从卷积层说起 熟悉CNN的小伙伴应该知道卷积是一个很常用也很重要的操作,CNN里的卷积和信号处理的卷积并不是一回事,CNN的卷积是做一种二维的互相关运算,以<动手学深度学习 ...

  4. MindSpore GPU异构算子全流程开发指导

    Tips ① 此文档详细介绍了MindSpore GPU异构算子开发流程,与官方文档相比本文档更加侧重于开发文件的解读以及常用开发方法的讲解.同时本文档用词相对简单,主要帮助大家了解GPU算子开发需要 ...

  5. TensorFlow+TVM优化NMT神经机器翻译

    TensorFlow+TVM优化NMT神经机器翻译 背景 神经机器翻译(NMT)是一种自动化的端到端方法,具有克服传统基于短语的翻译系统中的弱点的潜力.本文为全球电子商务部署NMT服务. 目前,将Tr ...

  6. 技术揭秘!百度搜索中台低代码的探索与实践

    导读:据Gartner调研,应用开发需求的市场增长至少超过IT交付能力的5倍,预计到2025年,70%的新应用开发将使用低代码技术.我们需要在需求迭代越来越高频.创新能力要求越来越高的背景下,探索如何 ...

  7. Tensorflow源码解析1 -- 内核架构和源码结构

    1 主流深度学习框架对比 当今的软件开发基本都是分层化和模块化的,应用层开发会基于框架层.比如开发Linux Driver会基于Linux kernel,开发Android app会基于Android ...

  8. Flink从入门到放弃之源码解析系列-第1章 Flink组件和逻辑计划

    >请戳GitHub原文: github.com/wangzhiwubi- 本文参考了网上很多博客,大多数博客都是基于1.1.0版本的,已经严重滞后,本系列文章做了很多订正,欢迎大家指正. 概要和 ...

  9. 动手学PaddlePaddle(1):线性回归

    你将学会: 机器学习的基本概念:假设函数.损失函数.优化算法 数据怎么进行归一化处理 paddlepaddle深度学习框架的一些基本知识 如何用paddlepaddle深度学习框架搭建全连接神经网络 ...

最新文章

  1. win7上安装theano keras深度学习框架
  2. Jeff Dean:一年开源12款新工具,谷歌负责任AI原则落地生根
  3. inline-block各浏览器兼容以及水平间隙问题解决方案
  4. Spring测试框架springContextTest
  5. 关于windows内存泄露思考
  6. Mybatis使用statementType=STATEMENT实现动态传入表名或字段名
  7. Redis入门(二)之数据类型
  8. android 头像球_Android一行代码实现圆形头像
  9. Luogu P3731 [HAOI2017]新型城市化
  10. ECCV 2020 论文大盘点-视频目标检测篇
  11. WCF中因序列化问题引起的异常和错误。
  12. 阶段3 2.Spring_02.程序间耦合_2 编译期依赖
  13. 【软件工程习题答案】第八章 维护
  14. Advanced Installer生成安装包
  15. C#番外篇-SpinWait
  16. wps改照片底色有红边_Excel怎么给证件照换底色?Excel中快速将证件照蓝底换红底的方法介绍...
  17. 超级简单的三次方程求解!
  18. mysql获取汉字首字母拼音,包括复杂字
  19. 考研名校压分黑名单——斯基
  20. matlab导出图片背景_matlab美化图片之添加背景颜色

热门文章

  1. 2022-2028年中国互联网+不良资产处置行业深度调研及投资前景预测报告
  2. 2022-2028年中国硫化橡胶粉行业市场发展调研及竞争战略分析报告
  3. 二叉树中和为某一值的路径
  4. javascript的知识总结
  5. 笔记本通过网线连接并控制工控机
  6. 阿里云服务器部署项目
  7. 【运维学习笔记】生命不息,搞事开始。。。
  8. python list 删除元素
  9. TVM将深度学习模型编译为WebGL
  10. 激光雷达Lidar Architecture and Lidar Design(下)