![tvm从模型到机器码的流图](https://img-blog.csdnimg.cn/45cad450669a416f987141b257c797dc.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAc2hhb2ppZV93YW5n,size_20,color_FFFFFF,t_70,g_se,x_16)
导入模型
可以支持从tf,pytorch,或者onnx框架中导入模型。
模型转换到relay
上述框架中产生的模型可以转换到tvm的relay上,relay是一个高级模型描述语言和IR,能做的东西还挺多:
- 传统的数据流表述
- 泛函表达,可以绑定出可微分变成语言
- 两者的混合使用
同时,relay也会针对模型做些图级别的优化。
转换到 tensor expression (TE)
通过relay做过高级优化后,relay会用FuseOps pass去把模型分解成一个个子图,并且把子图转化到低阶表达TE中去。TE已经是一个描述张量计算的dsl。TE阶段也会提供一些调度原语去做更底层的循环优化,比如loop tile,vectorization,并行,loop unroll和loop fusion。tvm中还封装了一些常见的张量计算像conv2d,transpose这样。(tvm中叫这些为TOPI)
自动优化调度
在tvm中,可以使用 AutoTVM 和 AutoScheduler 去搜索出一个张量计算的最佳优化调度方式。每个调度(schedule)会针对算子或者张量运算指定一种低级循环优化。自动优化模块会找出一个最佳调度方案并且把它和cost model中的方案或者片上的实际测量作对比。自动优化共有两种方式:
- AutoTVM:一个模板化的自动优化模块,通过运行搜索算法找到在用户定义模板内的最佳的优化组合方案。对于常见算子,TOPI会提供一套优化调度的搜索空间出来。
- AutoScheduler(a.k.a Ansor):一个非模板化的自动优化模块。他并不需要一些预定义的调度模板,它会通过分析计算定义自动生成搜索空间,并且在空间内搜索最佳优化调度方案。
模型编译
选择最优的模型编译配置。通过上一步的优化调度搜索,各个子图最佳的优化方案会保存在一份JSON文件中。
转换到TIR(tensor IR)
TIR就是TVM能玩的最底层的IR。获取到最佳的优化调度空间后,TE的子图会被转化(lower)到TIR上面并且会执行更底层的循环优化。随后,优化后的TIR会被转换到目标平台的编译器(codegen)上。最后由编译器产生机器码,codegen包含以下编译器后端:
- LLVM:支持X86,arm,AMDPGU,nvptx
- NVCC:nv的编译器
- 自定义编译器(BYOC)框架定义的嵌入式平台
编译器编译到机器码
最后会由编译器把code编译成机器码到目标平台运行。
综上,tvm可以把一个model编译成为一个机器码(linkable object),通过轻量级的runtime接口动态加在动态链接库。基本上可以理解为把一个深度学习模型转换成平台的运行库。