TVM Learning (2)-Tensor Program Abstraction Case Study-TensorIR
Primitive Tensor Function
机器学习编译的过程可以被看作张量函数之间的变换。一个典型的机器学习模型的执行包含许多步将输入张量之间转化为最终预测的计算步骤,其中的每一步都被称为元张量函数 (Primitive Tensor Function)
通常来说,一个典型的元张量函数实现的抽象包含了以下成分:存储数据的多维数组,驱动张量计算的循环嵌套以及计算部分本身的语句。下图以上一篇中的向量加法为例子进行了分解。
我们称这类抽象为张量程序抽象(Tensor Program Abstraction). 张量程序抽象的一个重要性质是,他们能够被一系列有效的程序变换所改变。例如,我们能够通过一组变换操作(如循环拆分、并行和向量化)将下图左侧的一个初始循环程序变换为右侧的程序。
Learning one Tensor Program Abstraction – TensorIR
我们对于神经网络的一个基本的 Linear+ReLU 层可以用以下的数学公式表示
其Numpy实现如下,下面的代码直接调用了Numpy的高级API,看起来非常简洁。
1 |
|
我们可以将上述程序改写成Low-level Numpy,意味着对于复杂的计算我们使用循环进行表示,并且写出开辟数组空间的过程。
1 |
|
该函数执行以下操作:
- 矩阵乘法: 将两个矩阵
A
和B
相乘,并将结果存储在Y
中。 - ReLU 激活: 将 ReLU 激活函数应用于
Y
的元素,并将结果存储在C
中。
可以用以下代码来检查上述实现的正确性:
1 |
|
示例 numpy 代码包含了实际过程中实现这些计算时可能会用到的所有元素,用Numpy函数内部工作机制 (Under the Hood) 实现了MM-ReLU。
- 开辟多维数组空间。
- 循环遍历数组的维度。
- 计算在循环内执行。
我们也可以用上一节的TensorIR来实现,TVMScript 是嵌入在 Python AST 中的领域特定语言的 Dialect, 它本质上是 Python 的一个子集,但添加了一些特定于 TVM 的扩展,例如用于描述计算图的特殊语法和语义。
Dialect 通常指一种语言的变体或子集,它与原始语言共享大部分语法和语义,但也有一些独特的特征。
抽象语法树 (AST) 是源代码的树状表示形式。它将代码的结构以一种层次化的方式呈现,每个节点代表代码中的一个语法元素,例如变量、运算符、函数调用等。
1 |
|
上述 TensorIR 程序的一个示例实例涵盖了大部分内容,包括
- 参数和中间临时内存中的缓冲区声明。
- For 循环迭代。
- Block 和 Block Axis属性。
Transformation
TVM
的 tvm.tir.Schedule
提供了一系列用于调度和优化计算图的变换函数。这些函数允许用户灵活地调整计算顺序、内存访问模式和并行化策略,以提高模型的性能。
我们可以用以下函数获得计算块和其对应的循环
1 |
|
我们可以使用 split
函数将一个循环拆成多个循环,用 reorder
函数交换循环的顺序,用 reverse_compute_at
函数移动计算块所在的循环,用 decompose_reduction
函数将初始化和归约操作分开。
1 |
|
对应的 Low-level Numpy 函数如下
1 |
|
Why Do Loop Influence the Exec Time
CPU 带有多级缓存,需要先将数据提取到缓存中,然后 CPU 才能访问它。而且访问已经在缓存中的数据要快得多。CPU 采用的一种策略是获取彼此更接近的数据。 当我们读取内存中的一个元素时,它会尝试将附近的元素(Cache Line)获取到缓存中,当读取下一个元素时它已经在缓存中。 因此,具有连续内存访问的代码通常比随机访问内存不同部分的代码更快。
j1
这一迭代产生了对 B
元素的连续访问。具体来说,它意味着在 j1=0
和 j1=1
时我们读取的值彼此相邻。这可以让我们拥有更好的缓存访问行为。此外,我们使 C 的计算更接近 Y,从而实现更好的缓存行为。
Ways to Create and Interact with TensorIR
Create TensorIR via TVMScript
创建 TensorIR 函数的第一种方法是直接在 TVMScript 中编写函数,它也是一种在变换过程中检查张量函数的有用方法。我们可以打印出 TVMScript,进行一些手动编辑,然后将其反馈给 MLC 流程以调试和尝试可能的(手动)变换,然后将变换后的程序重新应用到 MLC 流程中。
Generate TensorIR code using Tensor Expression
张量表达式 (TE) 是一种特定领域的语言,它通过 API 之类的表达式描述一系列计算。MM-ReLU 可以通过以下程序完成
1 |
|