MLIR定义

本章介绍MLIR各个元素的定义, 包括Dialect、Interface等等

Top Dialect

Operations

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")

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")

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")

BatchNormOp

简述:

在一个四维输入tensor上执行批标准化(Batch Normalization)。关于批标准化的更多细节可以参考论文《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift 》。

具体计算公式如下:

\[\begin{split}y = \frac{x - \mathrm{E}[x]}{ \sqrt{\mathrm{Var}[x] + \epsilon}} * \gamma + \beta\end{split}\]
输入:
  • 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")

CastOp

(待补充)

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")

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")

ConvOp

简述:

对输入tensor执行二维卷积操作。

简单来说, 给定输入大小为 \((N, C_{\text{in}}, H, W)\), 输出 \((N, C_{\text{out}}, H_{\text{out}}, W_{\text{out}})\) 的计算方法为:

\[\begin{split}\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)\end{split}\]

其中 \(\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")

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")

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")

InputOp

(待补充)

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")

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

输出:
  • 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")

LogOp

简述:

按元素计算给定输入张量的自然对数

输入:
  • input: tensor

输出:
  • output: tensor

属性:

输出:
  • output: 输出tensor

接口:

范例:
%1 = "top.Log"(%0) : (tensor<1x3x32x32xf32>) -> tensor<1x3x32x32xf32> loc("Log")

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")

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")

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")

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")

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")

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")

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")

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")

SigmoidOp

简述:

激活函数, 将tensor中元素映射到特定区间, 默认映射到[0, 1], 计算方法为:

\[\begin{split}Y = \frac{scale}{1 + e^{-X}} + bias \end{split}\]
输入:
  • 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")

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")

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")

SoftmaxOp

简述:

对输入tensor, 在指定axis的维度上计算归一化指数值, 计算的方法如下:

\[\begin{split}\sigma(Z)_i = \frac{e^{\beta{Z_i}}}{\sum_{j=0}^{K-1}{e^{\beta{Z_j}}}} \end{split}\]

其中, \(\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, 计算方法为:

\[\begin{split}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}}}}} \end{split}\]
输入:
  • 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")

SqueezeOp

简述:

对输入tensor进行指定维度的裁剪并返回裁剪后的tensor

输入:
  • input: tensor

输出:
  • output: tensor

属性:
  • axes: 指定需要裁剪的维度, 0代表第一个维度, -1代表最后一个维度

接口:

范例:
%133 = "top.Squeeze"(%132) {axes = [-1]} : (tensor<1x255x20x20xf32) -> tensor<1x255x20xf32> loc(#loc278)

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")

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")