【TVM模型编译】2. relay算子构造
从TVM的官方Tutorial里面,介绍了如何新增自定义算子。(这是我翻译的)
之前的文章讲到了onnx 算子转换到Relay IR的过程
下面以Conv2d算子介绍,编译过程中 Relay IR是如何被调用的。
relay 算子调用
上面的get_relay_op
实际上是查找所有 relay ir算子,其代码在python/tvm/relay/frontend/common.py
中的get_relay_op
。继续以conv卷积算子为例介绍。上文所述的转换算子中,有下面的语句
1 | for candidate in (_op, _op.nn, _op.image, _op.vision, _op.contrib): |
对于conv2d
算子,在_op.nn
中,找到conv2d实现。
1 | def conv2d( |
这里的_make.conv2d
是通过下面的PackFunc注册得到的
1 | tvm._ffi._init_api("relay.op.nn._make", __name__) |
在src/relay/op/nn/convolution.cc
找到conv2d的注册函数
1 | TVM_REGISTER_GLOBAL("relay.op.nn._make.conv2d") |
MakeConv 是对所有卷积的模板,根据参数实例化相应的函数
1 | template <typename T> |
这里通过Op::Get(op_name);
获取对应relay算子,在Op::Get
函数中发现是通过查表得到。
1 | // find operator by name |
注册是通过C++的RELAY_REGISTER_OP("nn.conv2d")
宏注册到OpRegistry::Global()
中。宏展开为
1 | static __attribute__((unused))::tvm::OpRegEntry& __make_Op230 = |
注册过程:
1 | RELAY_REGISTER_OP("nn.conv2d") |
返回的是OpRegEntry
,后续的set_name
等,则是通过OpRegEntry
的get接口(返回的是OpNode),构造对应的Relay op
本文标题:【TVM模型编译】2. relay算子构造
文章作者:王二
发布时间:2023-08-09
最后更新:2024-11-06
原始链接:https://wanger-sjtu.github.io/tvm-relay-op-construct/
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!