13. MLIR定义
本章介绍MLIR各个元素的定义,包括Dialect、Interface等等
13.1. Top Dialect
13.1.1. Operations
13.1.1.1. AddOp
- 简述
加法操作,\(Y = coeff_0 * X_0 + coeff_1 * X_1\)
- 输入
inputs: tensor数组,对应2个或多个输入tensor
- 输出
output: tensor
- 属性
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
coeff: 对应每个tensor的系数,默认为1.0
- 输出
output: 输出tensor
- 接口
无
- 范例
%2 = "top.Add"(%0, %1) {do_relu = false} : (tensor<1x3x27x27xf32>, tensor<1x3x27x27xf32>) -> tensor<1x3x27x27xf32> loc("add")
13.1.1.2. AvgPoolOp
- 简述
将输入的tensor进行均值池化,\(S=\frac{1}{width\ *\ height}\sum_{i,j}a_{ij}\) 。大小给定的滑动窗口会依次将输入tensor进行池化
其中 \(width\) 和 \(height\) 表示kernel_shape的宽度和高度。 \(\sum_{i,j}a_{ij}\) 则表示对kernel_shape进行求和
- 输入
input: tensor
- 输出
output: tensor
- 属性
kernel_shape: 控制均值池化滑动窗口的大小
strides: 步长,控制滑动窗口每次滑动的距离
pads: 控制填充形状,方便池化
pad_value: 填充内容,常数,默认为0
count_include_pad: 结果是否需要对填充的pad进行计数
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
- 接口
无
- 范例
%90 = "top.AvgPool"(%89) {do_relu = false, kernel_shape = [5, 5], pads = [2, 2, 2, 2], strides = [1, 1]} : (tensor<1x256x20x20xf32>) -> tensor<1x256x20x20xf32> loc("resnetv22_pool1_fwd_GlobalAveragePool")
13.1.1.3. Depth2SpaceOp
- 简述
深度转空间操作,\(Y = Depth2Space(X)\)
- 输入
inputs: tensor
- 输出
output: tensor
- 属性
block_h:tensor 高度改变的参数,i64类型
block_w:tensor 宽度改变的参数,i64类型
is_CRD:column-row-depth,如果true,则数据沿深度方向的排布按照HWC,否则为CHW,bool类型
- is_inversed:如果true,那么结果的形状为: \([n, c * block_h * block_w, h / block_h, w / block_w]\),
否则结果的形状为:\([n, c / (block_h * block_w), h * block_h, w * block_w]\)
- 输出
output: 输出tensor
- 接口
无
- 范例
%2 = "top.Depth2Space"(%0) {block_h = 2, block_w = 2, is_CRD = true, is_inversed = false} : (tensor<1x8x2x3xf32>) -> tensor<1x2x4x6xf32> loc("add")
13.1.1.4. BatchNormOp
- 简述
在一个四维输入tensor上执行批标准化(Batch Normalization)。关于批标准化的更多细节可以参考论文《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift 》。
具体计算公式如下:
\[y = \frac{x - \mathrm{E}[x]}{ \sqrt{\mathrm{Var}[x] + \epsilon}} * \gamma + \beta\]- 输入
input: 四维输入tensor
mean: input的均值tensor
variance: input的方差tensor
gamma: 公式中的 \(\gamma\) tensor, 可以为None
beta: 公式中的 \(\beta\) tensor, 可以为None
- 输出
output: 结果tensor
- 属性
epsilon: 公式中的 \(\epsilon\) 常量,默认为1e-05
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
- 接口
无
- 范例
%5 = "top.BatchNorm"(%0, %1, %2, %3, %4) {epsilon = 1e-05, do_relu = false} : (tensor<1x3x27x27xf32>, tensor<3xf32>, tensor<3xf32>, tensor<3xf32>, tensor<3xf32>) -> tensor<1x3x27x27xf32> loc("BatchNorm")
13.1.1.5. CastOp
(待补充)
13.1.1.6. ClipOp
- 简述
将给定输入限制在一定范围内
- 输入
input: tensor
- 输出
output: tensor
- 属性
min: 给定的下限
max: 给定的上限
- 输出
output: 输出tensor
- 接口
无
- 范例
%3 = "top.Clip"(%0) {max = 1%: f64,min = 2%: f64} : (tensor<1x3x32x32xf32>) -> tensor<1x3x32x32xf32> loc("Clip")
13.1.1.7. ConcatOp
- 简述
将给定的tensor序列在给定的维度上连接起来。所有的输入tensor或者都具有相同的shape(待连接的维度除外),或者都为空。
- 输入
inputs: tensor数组,对应2个或多个输入tensor
- 输出
output: 结果tensor
- 属性
axis: 待连接的维度的下标
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
- 接口
无
- 范例
%2 = "top.Concat"(%0, %1) {axis = 1, do_relu = false} : (tensor<1x3x27x27xf32>, tensor<1x3x27x27xf32>) -> tensor<1x6x27x27xf32> loc("Concat")
13.1.1.8. ConvOp
- 简述
对输入tensor执行二维卷积操作。
简单来说,给定输入大小为 \((N, C_{\text{in}}, H, W)\),输出 \((N, C_{\text{out}}, H_{\text{out}}, W_{\text{out}})\) 的计算方法为:
\[\text{out}(N_i, C_{\text{out}_j}) = \text{bias}(C_{\text{out}_j}) + \sum_{k = 0}^{C_{\text{in}} - 1} \text{weight}(C_{\text{out}_j}, k) \star \text{input}(N_i, k)\]其中 \(\star\) 是有效的cross-correlation操作, \(N\) 是batch的大小, \(C\) 是channel的数量, \(H, W\) 是输入图片的高和宽。
- 输入
input: 输入tensor
filter: 参数tensor,其形状为 \((\text{out\_channels}, \frac{\text{in\_channels}}{\text{groups}}, \text{kernel\_size[0]}, \text{kernel\_size[1]})\):
bias: 可学习的偏差tensor,形状为 \((out\_channels)\).
- 输出
output: 结果tensor
- 属性
kernel_shape: 卷积核的尺寸
strides: 卷积的步长
pads: 输入的每一条边补充0的层数
group: 从输入通道到输出通道的阻塞连接数,默认为1
dilations: 卷积核元素之间的间距,可选
inserts: 可选
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
- 接口
无
- 范例
%2 = "top.Conv"(%0, %1) {kernel_shape = [3, 5], strides = [2, 1], pads = [4, 2]} : (tensor<20x16x50x100xf32>, tensor<33x3x5xf32>) -> tensor<20x33x28x49xf32> loc("Conv")
13.1.1.9. DeconvOp
- 简述
对输入tensor执行反卷积操作。
- 输入
input: 输入tensor
filter: 参数tensor,其形状为 \((\text{out\_channels}, \frac{\text{in\_channels}}{\text{groups}}, \text{kernel\_size[0]}, \text{kernel\_size[1]})\):
bias: 可学习的偏差tensor,形状为 \((out\_channels)\).
- 输出
output: 结果tensor
- 属性
kernel_shape: 卷积核的尺寸
strides: 卷积的步长
pads: 输入的每一条边补充0的层数
group: 从输入通道到输出通道的阻塞连接数,默认为1
dilations: 卷积核元素之间的间距,可选
inserts: 可选
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
- 接口
无
- 范例
%2 = "top.Deconv"(%0, %1) {kernel_shape = (3, 5), strides = (2, 1), pads = (4, 2)} : (tensor<20x16x50x100xf32>, tensor<33x3x5xf32>) -> tensor<20x33x28x49xf32> loc("Deconv")
13.1.1.10. DivOp
- 简述
除法操作,\(Y = X_0 / X_1\)
- 输入
inputs: tensor数组,对应2个或多个输入tensor
- 输出
output: tensor
- 属性
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
multiplier: 量化用的乘数,默认为1
rshift: 量化用的右移,默认为0
- 输出
output: 输出tensor
- 接口
无
- 范例
%2 = "top.Div"(%0, %1) {do_relu = false, relu_limit = -1.0, multiplier = 1, rshift = 0} : (tensor<1x3x27x27xf32>, tensor<1x3x27x27xf32>) -> tensor<1x3x27x27xf32> loc("div")
13.1.1.11. InputOp
(待补充)
13.1.1.12. LeakyReluOp
- 简述
tensor中每个元素执行LeakyRelu函数,函数可表示为:f(x) = alpha * x for x < 0, f(x) = x for x >= 0
- 输入
input: tensor
- 输出
output: tensor
- 属性
alpha:对应每个tensor的系数
- 输出
output: 输出tensor
- 接口
无
- 范例
%4 = "top.LeakyRelu"(%3) {alpha = 0.67000001668930054 : f64} : (tensor<1x32x100x100xf32>) -> tensor<1x32x100x100xf32> loc("LeakyRelu")
13.1.1.13. LSTMOp
- 简述
执行RNN 的LSTM操作
- 输入
input: tensor
- 输出
output: tensor
- 属性
filter:卷积核
recurrence:循环单元
bias:LSTM的参数:偏置
initial_h:LSTM中的每句话经过当前cell后会得到一个state,state 是个tuple(c, h),其中h=[batch_size, hidden_size]
initial_c:c=[batch_size, hidden_size]
have_bias:是否设置偏置bias,默认为false
bidirectional:设置双向循环的LSTM,默认为false
batch_first:是否将batch放在第一维,默认为false
num_layers:LSTM堆叠层数,默认为1
- 输出
output: 输出tensor
- 接口
无
- 范例
%6 = "top.LSTM"(%0, %1, %2, %3, %4, %5) {batch_first = false, bidirectional = true, have_bias = true} : (tensor<75x2x128xf32>,tensor<2x256x128xf32>, tensor<2x256x64xf32>, tensor<2x512xf32>, tensor<2x2x64xf32>, tensor<2x2x64xf32>) -> tensor<75x2x2x64xf32> loc("LSTM")
13.1.1.14. LogOp
- 简述
按元素计算给定输入张量的自然对数
- 输入
input: tensor
- 输出
output: tensor
- 属性
无
- 输出
output: 输出tensor
- 接口
无
- 范例
%1 = "top.Log"(%0) : (tensor<1x3x32x32xf32>) -> tensor<1x3x32x32xf32> loc("Log")
13.1.1.15. MaxPoolOp
- 简述
将输入的tensor进行最大池化
- 输入
input: tensor
- 输出
output: tensor
- 属性
kernel_shape: 控制均值池化滑动窗口的大小
strides: 步长,控制滑动窗口每次滑动的距离
pads: 控制填充形状,方便池化
pad_value: 填充内容,常数,默认为0
count_include_pad: 结果是否需要对填充的pad进行计数
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
- 接口
无
- 范例
%8 = "top.MaxPool"(%7) {do_relu = false, kernel_shape = [5, 5], pads = [2, 2, 2, 2], strides = [1, 1]} : (tensor<1x256x20x20xf32>) -> tensor<1x256x20x20xf32> loc("resnetv22_pool0_fwd_MaxPool")
13.1.1.16. MatMulOp
- 简述
二维矩阵乘法操作,\(C = A * B\)
- 输入
input: tensor: m*k 大小的矩阵
right: tensor: k*n 大小的矩阵
- 输出
output: tensor m*n 大小的矩阵
- 属性
bias: 偏差,量化的时候会根据bias计算 bias_scale,可以为空
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
- 输出
output: 输出tensor
- 接口
无
- 范例
%2 = "top.MatMul"(%0, %1) {do_relu = false, relu_limit = -1.0} : (tensor<3x4xf32>, tensor<4x5xf32>) -> tensor<3x5xf32> loc("matmul")
13.1.1.17. MulOp
- 简述
乘法操作,\(Y = X_0 * X_1\)
- 输入
inputs: tensor数组,对应2个或多个输入tensor
- 输出
output: tensor
- 属性
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
multiplier: 量化用的乘数,默认为1
rshift: 量化用的右移,默认为0
- 输出
output: 输出tensor
- 接口
无
- 范例
%2 = "top.Mul"(%0, %1) {do_relu = false, relu_limit = -1.0, multiplier = 1, rshift = 0} : (tensor<1x3x27x27xf32>, tensor<1x3x27x27xf32>) -> tensor<1x3x27x27xf32> loc("mul")
13.1.1.18. MulConstOp
- 简述
和常数做乘法操作,\(Y = X * Const_Val\)
- 输入
inputs: tensor
- 输出
output: tensor
- 属性
const_val: f64类型的常量
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
- 输出
output: 输出tensor
- 接口
无
- 范例
%1 = arith.constant 4.7 : f64 %2 = "top.MulConst"(%0) {do_relu = false, relu_limit = -1.0} : (tensor<1x3x27x27xf64>, %1) -> tensor<1x3x27x27xf64> loc("mulconst")
13.1.1.19. PermuteOp
- 简述
改变tensor布局,变化tensor数据维度的顺序,将输入的tensor按照order给定的顺序重新布局
- 输入
inputs: tensor数组,任意类型的tensor
- 属性
order: 指定重新布局tensor的顺序
- 输出
output: 输出tensor,按order的顺序重新布局后的tensor
- 接口
无
- 范例
%2 = "top.Permute"(%1) {order = [0, 1, 3, 4, 2]} : (tensor<4x3x85x20x20xf32>) -> tensor<4x3x20x20x85xf32> loc("output_Transpose")
13.1.1.20. ReluOp
- 简述
tensor中每个元素执行ReLU函数,如果极限为零,则不使用上限
- 输入
input: tensor
- 输出
output: tensor
- 属性
relu_limit:如果做Relu,指定上限值,如果是负数,则认为没有上限。
- 输出
output: 输出tensor
- 接口
无
- 范例
%1 = "top.Relu"(%0) {relu_limit = 6.000000e+00 : f64} : (tensor<1x3x32x32xf32>) -> tensor<1x3x32x32xf32> loc("Clip")
13.1.1.21. ReshapeOp
- 简述
Reshape算子,返回一个给定形状的tensor,该tensor的类型和内部的值与输入tensor相同。reshape可能会对tensor的任何一行进行操作。在reshape过程中不会有任何数据的值被修改
- 输入
input: tensor
- 输出
output: tensor
- 属性
无
- 接口
无
- 范例
%133 = "top.Reshape"(%132) : (tensor<1x255x20x20xf32>) -> tensor<1x3x85x20x20xf32> loc("resnetv22_flatten0_reshape0_Reshape")
13.1.1.22. ScaleOp
- 简述
Scale操作 \(Y = X * S + B\),其中X/Y的shape为[N, C, H, W],S/B的shape为[1, C, 1, ,1]。
- 输入
input: 输入tensor
scale: 保存input的放大倍数
bias: 放大后加上的bias
- 输出
output: 结果tensor
- 属性
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
- 接口
无
- 范例
%3 = "top.Scale"(%0, %1, %2) {do_relu = false} : (tensor<1x3x27x27xf32>, tensor<1x3x1x1xf32>, tensor<1x3x1x1xf32>) -> tensor<1x3x27x27xf32> loc("Scale")
13.1.1.23. SigmoidOp
- 简述
激活函数,将tensor中元素映射到特定区间,默认映射到[0,1],计算方法为:
\[Y = \frac{scale}{1 + e^{-X}} + bias\]- 输入
inputs: tensor数组,任意类型的tensor
- 属性
scale: 倍数,默认是1
bias: 偏置,默认是0
- 输出
output: 输出tensor
- 接口
无
- 范例
%2 = "top.Sigmoid"(%1) {bias = 0.000000e+00 : f64, scale = 1.000000e+00 : f64} : (tensor<1x16x64x64xf32>) -> tensor<1x16x64x64xf32> loc("output_Sigmoid")
13.1.1.24. SiLUOp
- 简述
激活函数,\(Y = \frac{X}{1 + e^{-X}}\) 或 \(Y = X * Sigmoid(X)\)
- 输入
input: tensor数组,任意类型的tensor
- 属性
无
- 输出
output: 输出tensor
- 接口
无
- 范例
%1 = "top.SiLU"(%0) : (tensor<1x16x64x64xf32>) -> tensor<1x16x64x64xf32> loc("output_Mul")
13.1.1.25. SliceOp
- 简述
tensor切片,将输入的tensor的各个维度,根据offset和steps数组中的偏移和步长进行切片,生成新的tensor
- 输入
input: tensor数组,任意类型的tensor
- 属性
offset: 存储切片偏移的数组,offset数组的索引和输入tensor的维度索引对应
steps: 存储切片步长的数组,steps数组的索引和输入tensor维度索引对应
- 输出
output: 输出tensor
- 接口
无
- 范例
%1 = "top.Slice"(%0) {offset = [2, 10, 10, 12], steps = [1, 2, 2, 3]} : (tensor<5x116x64x64xf32>) -> tensor<3x16x16x8xf32> loc("output_Slice")
13.1.1.26. SoftmaxOp
- 简述
对输入tensor,在指定axis的维度上计算归一化指数值,计算的方法如下:
\[\sigma(Z)_i = \frac{e^{\beta{Z_i}}}{\sum_{j=0}^{K-1}{e^{\beta{Z_j}}}}\]其中, \(\sum_{j=0}^{K-1}{e^{\beta{Z_j}}}\) ,在axis维度上做指数值求和,j从0到K-1,K是输入tensor在axis维度上的尺寸。
例如:输入tensor的尺寸为 \((N, C, W, H)\),在axis=1的通道上计算Softmax,计算方法为:
\[Y_{n,i,w,h} = \frac{e^{\beta{X_{n,i,w,h}}}}{\sum_{j=0}^{C-1}{e^{\beta{X_{n,j,w,h}}}}}\]- 输入
input: tensor数组,任意类型的tensor
- 属性
axis: 维度索引,用于指定对输入tensor执行Softmax对应的维度,axis可以取值[-r, r-1], r 为输入tensor维度的数量, 当axis为负数时,表示倒序维度
beta: tflite模型中对输入的缩放系数,非tflite模型无效,默认值为1.0
- 输出
output: 输出tensor,在指定维度做归一化指数值后的tensor
- 接口
无
- 范例
%1 = "top.Softmax"(%0) {axis = 1 : i64} : (tensor<1x1000x1x1xf32>) -> tensor<1x1000x1x1xf32> loc("output_Softmax")
13.1.1.27. SqueezeOp
- 简述
对输入tensor进行指定维度的裁剪并返回裁剪后的tensor
- 输入
input: tensor
- 输出
output: tensor
- 属性
axes: 指定需要裁剪的维度,0代表第一个维度,-1代表最后一个维度
- 接口
无
- 范例
%133 = "top.Squeeze"(%132) {axes = [-1]} : (tensor<1x255x20x20xf32) -> tensor<1x255x20xf32> loc(#loc278)
13.1.1.28. UpsampleOp
- 简述
上采样op,将输入tensor进行nearest上采样并返回tensor
- 输入
tensor
- 属性
scale_h: 目标图像与原图像的高度之比
scale_w: 目标图像与原图像的宽度之比
do_relu: 结果是否做Relu,默认为False
relu_limit: 如果做Relu,指定上限值,如果是负数,则认为没有上限
- 输出
output: tensor
- 接口
无
- 范例
%179 = "top.Upsample"(%178) {scale_h = 2 : i64, scale_w = 2 : i64} : (tensor<1x128x40x40xf32>) -> tensor<1x128x80x80xf32> loc("268_Resize")
13.1.1.29. WeightOp
- 简述
权重op,包括权重的读取和创建,权重会存到npz文件中。权重的location与npz中的tensor名称是对应关系。
- 输入
无
- 属性
无
- 输出
output: 权重Tensor
- 接口
read: 读取权重数据,类型由模型指定
read_as_float: 将权重数据转换成float类型读取
read_as_byte: 将权重数据按字节类型读取
create: 创建权重op
clone_bf16: 将当前权重转换成bf16,并创建权重Op
clone_f16: 将当前权重转换成f16,并创建权重Op
- 范例
%1 = "top.Weight"() : () -> tensor<32x16x3x3xf32> loc("filter")