前言
最近读了mackler的2篇文章,专用架构与AI软件栈,深有同感。借此机会也小结一下目前自己对MLIR的体会。
一、MLIR的江湖地位
MLIR从诞生开始就争议不断,但争议归争议,使用者和关注度逐渐上升。为什么呢?能解决问题的工具就是好工具。虽说有可能在某些人眼中,使用MLIR耗费了更多的时间和人力。
但MLIR能走多远,和mackler文中所提到的问题有关:MLIR本身更接近一个库的定位而非生态? 两者最大的差别就在于使用者是仅仅从MLIR本身受益,还是也会从其他MLIR使用者身上受益?如是后者,如能形成链式反应,那将是轰轰烈烈的场面,但目前的现状可以说是不温不火。我觉得本司对待MLIR的态度正好可以说明一些问题。
本司有一xPU,经过几年的辛苦开发,终于编译器接近成熟,在对DNN的覆盖面以及精度方面,已经接近商用。但此时,新开了MLIR编译器项目,也是以xPU为目标后端。但开发进度一直不紧不慢,不知道是作为预研项目还是没有任务时间节点。我想这可能是大多数开发者对待MLIR的态度吧,不能不碰,但是又不愿太近。一方面期待能形成MLIR群体效应,减少自己的开发工作量,但另一方面的,对此又信心不足。
目前本司的MLIR编译器项目只是直接使用了MLIR框架以及core dialect,并没有涉及到第三方的共享。
二、IR的完备性
引用文中的一段话:
希望在剧烈变化的前端和后端之间找到一个稳定不变的层来解耦合,在变化中求稳的办法只有依靠完备性,像CPU基础指令集一样稳定,但CPU基础指令集的完备性是来源于图灵祖师爷带给我们的,但这完备性仅限于细粒度IR。但细粒度IR是没法向下对接DSA硬件的,因为DSA硬件的指令是粗粒度的,否则拿不到DSA的收益。
深度学习框架早期从caffe那种粗粒度的layer模式转向相对细粒度的operator转变就是一种尝试
抛开理论上的高度,直观的面对为xPU定制编译器的需求,这种大一统的思路就不好走。直觉会告诉我走算子编译器的路子。体现在MLIR上,就是提供了多种lowering的可能性。
三、MLIR结构的一些理解
MLIR是以dialect为节点,以lowering连接各个dialect。下图就是一个典型的MLIR编译过程。
引自codegen-dialect-overview
不同的backend, 走不同的lowering路径, 最终得到可运行的blob。如果没有自己想要的dialect,只能自己想办法了。但这些dialect究竟需要做些什么呢?
我们先来看看一个完备的IR需要包含哪些模块或功能。model可以看做是Tensor,Control,Operation三位一体的组合体。从3个不同的角度看,会是model的3种不同 呈现。
Tensor model
Operation model
Control model
一层层的dialect所做就是在优化之外,按照backend的执行特性,将3者粘合在一起。有些dialect做运行调度的并行化;有些dlalect做memory的布局和映射;有些dialect做operator的transformation。比如靠数据依赖来达到并行的目的;或者使用硬件锁显式的做并行调度等等。各个中间IR包含了各个dialect的语句,有些语句可能仅仅只是placeholder,供后续的转换或优化之用。
但最终的IR表达式里是什么样子呢?不同的backend有不同的诉求。比如针对CPU的,最红就是LLVM IR并被编译为代码,没有显式的Tensor/Control/Operation的表示,只有执行流。而对xPU而言,不同额xPU架构设计(参见一文吃透AI芯片技术路线,清华尹首一教授演讲全文:GTIC2020)也会有不同的runtime需求。
以典型的数据流AI处理器为例,最终生成的IR是要递交给xPU的runtime去解释执行的,所以IR的lowering其实分为了2个阶段。第一阶段就是offline处理,生成IR blob;第二阶段则是由runtime实时处理,主要是将执行流lowering到根据xPU的硬件资源,比如memory的重定位,硬件锁的复用, 计算单元的调度等等。
|