TVM学习

【TVM系列四】模型编译与运行过程

2022-07-04  本文已影响0人  AIPlayer

一、前言

针对神经网络模型的编译,TVM封装了非常简洁的python接口,如下:

# keras前端导入,使用llvm作为target编译
mod, params = relay.frontend.from_keras(keras_resnet50, shape_dict)
# compile the model
target = "llvm"
dev = tvm.cpu(0)
with tvm.transform.PassContext(opt_level=0):
    model = relay.build_module.create_executor("graph", mod, dev, target, params).evaluate()
print(model)
tvm_out = model(tvm.nd.array(data.astype(dtype)))

在上一篇文章中介绍了模型的算子转换与Relay IR Module的流程,当TVM将Relay IR Module模型编译为runtime module时,可以通过下面的函数完成:

model = relay.build_module.create_executor("graph", mod, dev, target, params).evaluate()

它返回的是一个函数入口,从打印的输出可以看到它所指向的函数:

<function graphexecutor._make_executor.._graph_wrapper at 0x7fb634b3ed30>

下面这一句相当于将输入传入这个函数去运行:

tvm_out = model(tvm.nd.array(data.astype(dtype)))

这两个步骤在TVM中的运行过程是怎么样的呢?这篇文章将围绕这个问题进行相关的介绍。

二、模型编译

image.png

首先来看一下TVM是如何调用到编译函数的:

下面介绍一下build(...)函数的过程:

其中BuildRelay的调用过程如下图所示,它主要有两个步骤,一个是对relay_module做了OptimizeImpl(...)的优化,对模型进行算子的融合、fold constants以及其它的一些优化;第二个是创建codegen对象并生成lowered_funcs并调用tvm::build(...)进行编译。

image.png

整个模型编译的过程可以总结为:将Relay IR Module编译为runtime module并为其构造好执行器的对象。

三、模型运行

模型运行时会调用_make_executor(...)里定义的_graph_wrapper(...)函数:

def _graph_wrapper(*args, **kwargs):
    args = self._convert_args(self.mod["main"], args, kwargs)
# Create map of inputs.
for i, arg in enumerate(args):
        gmodule.set_input(i, arg)
# Run the module, and fetch the output.
    gmodule.run()
    flattened = []
for i in range(gmodule.get_num_outputs()):
        flattened.append(gmodule.get_output(i).copyto(_nd.cpu(0)))
    unflattened = _unflatten(iter(flattened), ret_type)
return unflattened

四、总结

本文主要介绍了TVM模型编译与运行过程中的代码流程。

上一篇 下一篇

猜你喜欢

热点阅读