Operator

为了BMLang编程时可以考虑到获取好的性能,下面会将Operator分成本地操作(Local Operator)、受限本地操作(Limited Local Operator) 和全局操作(Global Operator)。

  • 本地操作:在启动编译时,可以与其它的本地操作进行合并优化,使得操作之间的数据只存在于TPU的本地存储中。

  • 受限本地操作:在一定条件下才能作为本地操作与其它本地操作进行合并优化。

  • 全局操作:不能与其它操作进行合并优化,操作的输入输出数据都需要放到TPU的全局存储中。

以下操作中,很多属于按元素计算(Element-wise)的操作,要求输入输出Tensor的shape具备相同数量的维度。

当操作的输入Tensor是2个时,分为支持shape广播和不支持shape广播两种。 支持shape广播表示tensor_i0(输入0)和tensor_i1(输入1)的同一维度的shape值可以不同,此时其中一个tensor的shape值必须是1,数据将被广播扩展到另一个tensor对应的shape值。 不支持shape广播则要求tensor_i0(输入0)和tensor_i1(输入1)的shape值一致。

NN/Matrix Operator

conv

二维卷积运算。

void conv(
  vector<Tensor*> tensor_i, // [in]
  Tensor& tensor_o,         // [out]
  ConvParam param)          // [in]
//example:
//vector<Tensor*> vec = {&tensor_input, &tensor_filter, &tensor_bias};
//ConvParam param(dw, dh, pad_h_t, pad_h_b, pad_w_l, pad_w_r, stride_h, stride_w, scale);
//conv(vec, tensor_output, param);

参数说明: tensor_i:依次压入tensor_input, tensor_weight, tensor_bias(如果存在)的地址 tensor_o:Tensor类型。

tensor_input要求是NCHW的shape和数据排布。tensor_weight的数据排布和shape要求是[oc, ic, kh, kw], 其中oc表示输出Channel数,ic表示输入channel数,kh是kernel_h,kw是kernel_w。 tensor_bias的shape要求是[1, oc, 1, 1]。

param: ConvParam类型,包含conv各参数,定义如下

typedef struct ConvParam {
  int    dh;            // 纵向dilation
  int    dw;            // 横向diliation
  int    pad_h_t;       // 纵向top的padding值
  int    pad_h_b;       // 纵向bottom的padding值
  int    pad_w_l;       // 横向left的padding值
  int    pad_w_r;       // 横向right的padding值
  int    stride_h;      // 纵向stride的值
  int    stride_w;      // 横向stride的值
  int    groups;        // conv的groups值,若ic=oc=groups时,则为depthwise conv
  /* Parameters for quantized computation */
  double  scale;        // conv的scale值
  QCalMode mode;        // INT8量化计算模式
  int left_zero_point;  // input的zero point, zp_l
  int right_zero_point; // weight的zero point, zp_r
  int output_zero_point;// output的zero point, zp_o
} ConvParam;
// QCalMode definition
typedef enum {
  LowPrecisionSymmetric = 0,
  HighPrecisionSymmetric = 1,
  HighPrecisionAsymmetric = 2,
} QCalMode;

以上scale、mode、left_zero_point、right_zero_point、output_zero_point是量化计算参数, 仅在量化计算时才会被用到。

二维卷积即深度学习中普遍的二维卷积计算。这里主要介绍定点下的二维卷积计算, 该操作对应的定点二维卷积计算式为:

output = Round{ [ (input - zp_l) Conv (weight - zp_r) + bias ] * scale } + zp_o;

其中Conv表示卷积计算,Round表示四舍五入。

  1. LowPrecisionSymmetric

该模式下,要求zp_l、zp_r和zp_o都为0。

要求input/weight的数据类型只能是INT8/UINT8。bias的数据类型要求是INT16/UINT16。 output可以是INT8/UINT8,不限制输出符号。

其计算如下伪代码所示:

// scale精度只有float32
scale = (float)(ConvParam.scale)
// 以右移方式来做 * scale,若scale是1/(2^m),则rshift正好是m
rshift = (scale <= 1 && scale > 0) ? ceil(log2(1/scale)) : 0;
// 卷积后做一次四舍五入的右移,四舍五入右移的说明请见操作mul_shift里的说明
// 获取imm_res的计算过程中间结果一直是INT32
imm_res = ((Convolution(input, weight) + bias) + (1 << (rshift - 1))) >> rshift;
// imm_res是INT32数据,饱和到INT8或UINT8结果
res = saturate_to_8bit(imm_res, tensor_o.get_dtype());

// 以下代码是当scale不是1/(2^m)时,对剩余浮点scale的补偿
scale_left_fp32 = (float)scale * exp2(rshift);
if (scale_left_fp32 != 1.0f) {
  imm_res2 = ((res * (int)(scale_left_fp32 * exp2(7))) + (1<<6)) >> 7;
  res = saturate_to_8bit(imm_res2, tensor_o.get_dtype());
}

从上述伪代码看出,若scale不等于1/(2^m),则LowPrecisionSymmetric下的计算结果与预期结果有误差,无法保证精度。

而若模型量化时将这里的scale限制为1/(2^m),m为正整数,则LowPrecisionSymmetric可以完全对齐预期的量化推理结果。

相比后两个量化计算模式,LowPrecisionSymmetric在BM1684下能获取最好的芯片性能。

  1. HighPrecisionSymmetric

该模式下,要求zp_l、zp_r和zp_o都为0。

要求input/weight的数据类型只能是INT8/UINT8。 bias的数据类型可以是INT16/UINT16/INT32/FLOAT32。 output可以是INT8/UINT8/INT16/UINT16,不限制输出符号。

其计算如下伪代码所示:

// scale精度只有float32
scale = (float)(ConvParam.scale)
// 以右移方式来做 * scale,若scale是1/(2^m),则rshift正好是m
rshift = (scale <= 1 && scale > 0) ? ceil(log2(1/scale)) : 0;
// 卷积后做一次四舍五入的右移,四舍五入右移的说明请见操作mul_shift里的说明
// 获取imm_res的计算过程中间结果一直是INT32
if (bias.get_dtype == FLOAT32 or INT32) {
  imm_res = ((Convolution(input, weight)) + (1 << (rshift - 1))) >> rshift;
} else {
  imm_res = ((Convolution(input, weight) + bias) + (1 << (rshift - 1))) >> rshift;
}
// imm_res是INT32数据,饱和到16bit
res = saturate_to_16bit(imm_res, INT16);

// 以下代码是当scale不是1/(2^m)时,对剩余浮点scale的补偿
if (bias.get_dtype == FLOAT32 or INT32) {
  imm_res2 = round(res * (float)scale * exp2(rshift) + bias * (float)scale);
} else
  imm_res2 = round(res * (float)scale * exp2(rshift));
}
if (tensor_o.get_dtype() == UINT16 or INT16) {
  res = saturate_to_16bit(imm_res2, tensor_o.get_dtype());
} else {
  res = saturate_to_8bit(imm_res2, tensor_o.get_dtype());
}

从上述伪代码看出,若imm_res转到16bit时没有发生饱和,则HighPrecisionSymmetric下的计算结果可以与预期的结果相同,没有精度损失。

由于BM1684的depthwise convolution不能获取16bit数据,所以若卷积是depthwise convolution,该模式下将被转为FLOAT32数据进行计算。

HighPrecisionSymmetric在BM1684下的性能要比LowPrecisionSymmetric弱,但强于HighPrecisionAsymmetric。

  1. HighPrecisionAsymmetric

该模式下,zp_l、zp_r和zp_o可以不为0,其取值范围要求与对应操作数一致。即zp_l对应input,zp_r对应weight,zp_o对应output。若对应操作数是INT8,则zp的取值范围是[-128,127];若对应操作数是UINT8,则zp取值范围是[0,255]。

要求input/weight的数据类型只能是INT8/UINT8。 bias的数据类型可以是INT16/UINT16/INT32/FLOAT32。 output可以是INT8/UINT8/INT16/UINT16,不限制输出符号。

其计算如下伪代码所示:

// scale精度只有float32
scale = (float)(ConvParam.scale)
// 以右移方式来做 * scale,若scale是1/(2^m),则rshift正好是m
rshift = (scale <= 1 && scale > 0) ? floor(log2(1/scale)) : 0;
// 重新计算bias,将zp_l合入bias中,以INT32为中间结果,bias_v2也是INT32
// 该计算在compile时离线完成,不影响性能
bias_v2 = bias + convolution(zp_l, weight - zp_r);
// 卷积后做一次四舍五入的右移,四舍五入右移的说明请见操作mul_shift里的说明
// 获取imm_res的计算过程中间结果一直是INT32
imm_res_part1 = ((Convolution(input, weight)) + (1 << (rshift - 1))) >> rshift;
imm_res_part2 = ((Convolution(input, zp_r)) + (1 << (rshift - 1))) >> rshift;
// 饱和到16bit
res_part1 = saturate_to_16bit(imm_res_part1, INT16);
res_part2 = saturate_to_16bit(imm_res_part2, INT16);
res = saturate_to_16bit(res_part1 + res_part2, INT16);

// 以下代码是当scale不是1/(2^m)时,对剩余浮点scale的补偿
imm_res2 = round(res * (float)scale * exp2(rshift) + bias_v2 * (float)scale);
if (tensor_o.get_dtype() == UINT16 or INT16) {
  res = saturate_to_16bit(imm_res2, tensor_o.get_dtype());
} else {
  res = saturate_to_8bit(imm_res2, tensor_o.get_dtype());
}

从上述伪代码看出,若imm_res_part1和imm_res_part2转到16bit时没有发生饱和,则HighPrecisionAsymmetric可以和预期的结果相同,没有精度损失。

由于BM1684的depthwise convolution不能获取16bit数据,所以若卷积是depthwise convolution,该模式下将被转为FLOAT32数据进行计算。

HighPrecisionAsymmetric由于要做两次Convolution来完成非对称量化就算,所以HighPrecisionAsymmetric在BM1684上的性能要比前两种模式性能的一半还要低。

  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型的限制请见前面说明的3种量化计算模式。

  • BM1686:在BM684的基础上另外支持FLOAT16(TODO)。

该操作属于 本地操作

deconv

二维反卷积计算。

void deconv(
vector<Tensor*> tensor_i, // [in]
Tensor& tensor_o,         // [out]
ConvParam param)          // [in]

参数说明: tensor_i:依次压入tensor_input, tensor_weight, tensor_bias(如果存在)的地址。 tensor_input要求是NCHW的shape和数据排布。tensor_weight的数据排布和shape要求是[ic, oc, kh, kw]。 tensor_o:Tensor类型 param: ConvParam类型,包含deconv各参数,定义同conv的参数,详细请见操作conv。

  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT8/UINT8,量化计算方面目前支持LowPrecisionSymmetric。

  • BM1686:在BM684的基础上另外支持FLOAT16(TODO)。

该操作属于 本地操作

conv3d

三维卷积运算。

void conv3d(
  vector<Tensor*> tensor_i, // [in]
  Tensor& tensor_o,         // [out]
  const Conv3dParam& param) // [in]

参数说明:

tensor_i:依次压入tensor_input, tensor_weight, tensor_bias(如果存在)的地址。

tensor_o:Tensor类型。

tensor_input要求是NCDHW的shape和数据排布。tensor_weight的数据排布和shape要求是[oc, ic, kd,kh, kw], 其中oc表示输出Channel数,ic表示输入channel数,kd是kernel_d,kh是kernel_h,kw是kernel_w。

tensor_bias的shape要求是[1, oc, 1, 1, 1]或[oc]。

param: Conv3dParam类型,包含conv各参数,定义如下

typedef struct Conv3dParam {
  int groups;        //  groups值
  int dilation[3];   //  dilation值,按顺序分别对应d、h、w这三个维度
  int pad[6];        //  pad值,按顺序分别对应pad_d_bottom、pad_d_top、pad_h_bottom、pad_h_top、pad_w_bottom、pad_w_top
  int stride[3];     //  stride值,按顺序分别对应d、h、w这三个维度
} Conv3dParam;

三维卷积即深度学习中普遍的三维卷积计算。

  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32。

  • BM1686:数据类型可以是FLOAT32/FLOAT16(TODO)。

该操作属于 本地操作

matrix_mul

matrix_result = matrix_left * matrix_right,对输入两个矩阵做乘法,例如:mat_l(m,k) * mat_r(k,n)输出的matrix是mat_res(m,n)。

void matrix_mul(
const vector<Tensor*> matrix_input, // [in]
Tensor& matrix_result,              // [out]
MatrixMulParam param)               // [in]

typedef struct MatrixMulParam {
  // The parameters for quantized computation
  double scale;          // scale值
  QCalMode mode;         // INT8量化计算模式
  int left_zero_point;   // input zero point, zp_l
  int right_zero_point;  // weight zero point, zp_r
  int output_zero_point; // output zero point, zp_o
} MatrixMulParam;

参数说明: matrix_input:依次压入matrix_left, matrix_right, bias(如果存在)的地址 matrix_result:Tensor类型。

matrix_left的shape和数据排列要求是[left_row, left_column],如果是CNN下的fully connect,left_row对应batch size。 matrix_right的shape和数据排列要求是[right_row, right_column],right_row = left_column。 matrix_bias的shape要求是[1, right_column]。

常规的矩阵乘运算,此时MatrixMulParam则没有用。 对于定点计算,matrix_result可以是INT8/UINT8/INT16/UINT16,如果输出为UINT8/UINT16,则要求所有的输入都为无符号。

这里主要介绍定点下的二维卷积计算,该操作对应的定点二维卷积计算式为:

output = Round{ [ (left - zp_l) MatrixMul (right - zp_r) + bias ] * scale } + zp_o;

其中Matrix表示矩阵乘计算,Round表示四舍五入。

  1. LowPrecisionSymmetric

该模式下,要求zp_l、zp_r和zp_o都为0。

要求left/right的数据类型只能是INT8/UINT8。bias的数据类型要求是INT16/UINT16。 matrix_result可以是INT8/UINT8,不限制输出符号。

其计算如下伪代码所示:

// scale精度只有float32
scale = (float)(MatrixMulParam.scale)
// 以右移方式来做 * scale,若scale是1/(2^m),则rshift正好是m
rshift = (scale <= 1 && scale > 0) ? ceil(log2(1/scale)) : 0;
// 矩阵乘后做一次四舍五入的右移,四舍五入右移的说明请见操作mul_shift里的说明
// 获取imm_res的计算过程中间结果是INT32
imm_res = ((MatrixMul(left, right) + bias) + (1 << (rshift - 1))) >> rshift;
// imm_res是INT32数据,饱和到INT8或UINT8结果
res = saturate_to_8bit(imm_res, matrix_result.get_dtype());

// 以下代码是当scale不是1/(2^m)时,对剩余浮点scale的补偿
scale_left_fp32 = (float)scale * exp2(rshift);
if (scale_left_fp32 != 1.0f) {
  imm_res2 = ((res * (int)(scale_left_fp32 * exp2(7))) + (1<<6)) >> 7;
  res = saturate_to_8bit(imm_res2, matrix_result.get_dtype());
}

从上述伪代码看出,若scale不等于1/(2^m),则LowPrecisionSymmetric下的计算结果与预期结果有误差,无法保证精度。

而若模型量化时将这里的scale限制为1/(2^m),m为正整数,则LowPrecisionSymmetric可以完全对齐预期的量化推理结果。

相比后两个量化计算模式,LowPrecisionSymmetric在BM1684下能获取最好的芯片性能。

  1. HighPrecisionSymmetric

该模式下,要求zp_l、zp_r和zp_o都为0。

要求left/right的数据类型只能是INT8/UINT8。 bias的数据类型可以是INT16/UINT16/INT32。 matrix_result可以是INT8/UINT8/INT16/UINT16,不限制输出符号。

其计算如下伪代码所示:

// scale精度只有float32
scale = (float)(MatrixMulParam.scale)
// 以右移方式来做 * scale,若scale是1/(2^m),则rshift正好是m
rshift = (scale <= 1 && scale > 0) ? ceil(log2(1/scale)) : 0;
// 矩阵乘后做一次四舍五入的右移,四舍五入右移的说明请见操作mul_shift里的说明
// 获取imm_res的计算过程中间结果是INT32
if (bias.get_dtype == FLOAT32 or INT32) {
  imm_res = ((MatrixMul(left, right)) + (1 << (rshift - 1))) >> rshift;
} else {
  imm_res = ((MatrixMul(left, right) + bias) + (1 << (rshift - 1))) >> rshift;
}
// imm_res是INT32数据,饱和到16bit
res = saturate_to_16bit(imm_res, INT16);

// 以下代码是当scale不是1/(2^m)时,对剩余浮点scale的补偿
if (bias.get_dtype == FLOAT32 or INT32) {
  imm_res2 = round(res * (float)scale * exp2(rshift) + bias * (float)scale);
} else
  imm_res2 = round(res * (float)scale * exp2(rshift));
}
if (tensor_o.get_dtype() == UINT16 or INT16) {
  res = saturate_to_16bit(imm_res2, matrix_result.get_dtype());
} else {
  res = saturate_to_8bit(imm_res2, matrix_result.get_dtype());
}

从上述伪代码看出,若imm_res转到16bit时没有发生饱和,则HighPrecisionSymmetric下的计算结果可以与预期的结果相同,没有精度损失。

HighPrecisionSymmetric在BM1684下的性能比LowPrecisionSymmetric稍弱,但强于HighPrecisionAsymmetric。

  1. HighPrecisionAsymmetric

该模式下,zp_l、zp_r和zp_o可以不为0,其取值范围要求与对应操作数一致。即zp_l对应matrix_left,zp_r对应matrix_right,zp_o对应matrix_result。若对应操作数是INT8,则zp的取值范围是[-128,127];若对应操作数是UINT8,则zp取值范围是[0,255]。

要求left/right的数据类型只能是INT8/UINT8,matrix_right必须是COEFF_TENSOR。 bias的数据类型可以是INT16/UINT16/INT32。 matrix_result可以是INT8/UINT8/INT16/UINT16,不限制输出符号。

其计算如下伪代码所示:

// scale精度只有float32
scale = (float)(MatrixMulParam.scale)
// 以右移方式来做 * scale,若scale是1/(2^m),则rshift正好是m
rshift = (scale <= 1 && scale > 0) ? ceil(log2(1/scale)) : 0;
// 重新计算bias,将zp_l合入bias中,以INT32为中间结果,bias_v2也是INT32
// 该计算在compile时离线完成,不影响性能
bias_v2 = bias + MatrixMul(zp_l, right - zp_r);
// 矩阵乘后做一次四舍五入的右移,四舍五入右移的说明请见操作mul_shift里的说明
// 获取imm_res的计算过程中间结果是INT32
imm_res_part1 = ((MatrixMul(left, right)) + (1 << (rshift - 1))) >> rshift;
imm_res_part2 = ((MatrixMul(left, zp_r)) + (1 << (rshift - 1))) >> rshift;
// 饱和到16bit
res_part1 = saturate_to_16bit(imm_res_part1, INT16);
res_part2 = saturate_to_16bit(imm_res_part2, INT16);
res = saturate_to_16bit(res_part1 + res_part2, INT16);

// 以下代码是当scale不是1/(2^m)时,对剩余浮点scale的补偿
imm_res2 = round(res * (float)scale * exp2(rshift) + bias_v2 * (float)scale);
if (tensor_o.get_dtype() == UINT16 or INT16) {
  res = saturate_to_16bit(imm_res2, matrix_result.get_dtype());
} else {
  res = saturate_to_8bit(imm_res2, matrix_result.get_dtype());
}

从上述伪代码看出,若imm_res_part1和imm_res_part2转到16bit时没有发生饱和,则HighPrecisionAsymmetric可以和预期的结果相同,没有精度损失。

HighPrecisionAsymmetric由于要做两次Matrix来完成非对称量化就算,所以HighPrecisionAsymmetric在BM1684上的性能要比前两种模式性能弱。

  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型的限制请见前面说明的3种量化计算模式。

  • BM1686:在BM684的基础上另外支持FLOAT16。

该操作属于 全局操作

batch_norm

批归一化运算。

void batch_norm(
  std::vector<Tensor*> tensor_i,  // [in]
  std::vector<Tensor*> tensor_o,  // [out]
  const NormParam& param);        // [in]

参数说明:

  • tensor_i:vector<Tensor*>类型,长度要求3或5。长度为5时依次tensor_i, mean_i, variance_i,gamma,beta的地址,其中gamma表示批正则化之后的进行的缩放系数,beta表示批正则化缩放后进行的平移;长度为3时则只有tensor_i, mean_i, variance_i,gamma相对于全1Tensor,beta相对于全0Tensor。

  • tensor_o:vector<Tensor*>类型,依次tensor_o, mean_o, variance_o的地址。

  • tensor_i要求是NCHW的shape和数据排布。mean_i/variance_i/gamma/beta的形状为[ic],ic表示输入channel数。

  • tensor_o会是NCHW的shape和数据排布。mean_o/variance_o的形状为[ic]。

  • param: NormParam类型,各参数定义如下

    typedef enum {
      BATCH_NORM = 0,           // 目前仅支持norm模式配置batch_norm
    } NormMode;
    
    typedef struct NormParam {
      float epsilon;            // 为了除法运算数值稳定加在分母上的值
      bool use_global_stats;    // 指示是否使用全局均值和方差
      float scale;              // 使用全局均值和方差时,需要一个比例系数
      NormMode method;          // norm方法
    } NormParam;
    

该batch_norm算子运算过程可参考各框架的batch_norm算子。

  • BM1684:数据类型可以是FLOAT32。

  • BM1686:数据类型可以是FLOAT32。

该操作属于 本地操作

softmax

归一化指数函数。

void softmax(
  const Tensor &tensor_i,  // [in]
  Tensor &tensor_o,        // [out]
  int axis);               // [in]

参数说明:

  • tensor_i,tensor_o:均是Tensor类型,分别对应输入输出tensor;

  • axis:int型,表示进行运算的轴。

即深度学习中普遍的归一化指数函数计算。可参考各框架的softmax算子。

  • BM1684:数据类型可以是FLOAT32。

  • BM1686:数据类型可以是FLOAT32。

该操作属于 本地操作

NN/Matrix Int Operator

conv_v2

二维卷积定点计算。

void conv_v2(
  vector<Tensor*> tensor_i, // [in]
  Tensor& tensor_o,         // [out]
  ConvV2Param param);       // [in]
// example:
// vector<Tensor*> vec = {&tensor_input, &tensor_weight, &tensor_bias};
// BMlang::ConvV2Param param;
// param.xxx = xxx
// conv_v2(vec, tensor_output, param);

参数说明: tensor_i:依次压入tensor_input, tensor_weight, tensor_bias(如果存在)的地址。 tensor_o:Tensor类型。

tensor_input要求是NCHW的shape和数据排布。tensor_weight的数据排布和shape要求是[oc, ic, kh, kw], 其中oc表示输出Channel数,ic表示输入channel数,kh是kernel_h,kw是kernel_w。 tensor_bias的shape要求是[1, oc, 1, 1]。

param: ConvV2Param类型,包含conv各参数,定义如下

typedef struct ConvV2Param {
  int               dh;            // 纵向dilation
  int               dw;            // 横向diliation
  int               pad_h_t;       // 纵向top的padding值
  int               pad_h_b;       // 纵向bottom的padding值
  int               pad_w_l;       // 横向left的padding值
  int               pad_w_r;       // 横向right的padding值
  int               stride_h;      // 纵向stride的值
  int               stride_w;      // 横向stride的值
  int               groups;        // conv的groups值,若ic=oc=groups时,则为depthwise conv
  bool              has_bias;      // 是否包含tensor_bias
  /* Parameters for quantized computation */
  bool              is_izp_const;  // input的zero point是否为const
  int               izp_val;       // input的zero point, if is_izp_const为true
  std::vector<int>  izp_vec;       // input的zero point vector, if is_izp_const为false
  bool              is_kzp_const;  // weight的zero point是否为const
  int               kzp_val;       // weight的zero point, if is_kzp_const为true
  std::vector<int>  kzp_vec;       //weight的zero point vector, if is_kzp_const为false
} ConvV2Param;

二维卷积即深度学习中普遍的二维卷积计算。这里主要介绍定点下的二维卷积定点计算, 该操作对应的定点二维卷积计算式为:

for c in channel
  izp = is_izp_const ? izp_val : izp_vec[c];
  kzp = is_kzp_const ? kzp_val : kzp_vec[c];
  output = (input - izp) Conv (weight - kzp) + bias[c];

其中Conv表示卷积计算。

要求input/weight的数据类型只能是INT8/UINT8。bias的数据类型要求是INT32/UINT32。 output可以是INT32/UINT32,不限制输出符号。

支持平台:BM1686

该操作属于 本地操作

conv3d_v2

三维卷积定点算。

void conv3d_v2(
  vector<Tensor*> tensor_i, // [in]
  Tensor& tensor_o,         // [out]
  Conv3DV2Param param);     // [in]
// example:
// vector<Tensor*> vec = {&tensor_input, &tensor_weight, &tensor_bias};
// BMlang::Conv3DV2Param param;
// param.xxx = xxx
// conv3d_v2(vec, tensor_output, param);

参数说明: tensor_i:依次压入tensor_input, tensor_weight, tensor_bias(如果存在)的地址。 tensor_o:Tensor类型。

tensor_input要求是NCTHW的shape和数据排布。tensor_weight的数据排布和shape要求是[oc, ic, kt, kh, kw], 其中oc表示输出Channel数,ic表示输入channel数,kt是kernel_t,kh是kernel_h,kw是kernel_w。 tensor_bias的shape要求是[1, oc, 1, 1, 1]或[oc]。

param: Conv3DV2Param类型,包含conv3d各参数,定义如下

typedef struct Conv3DV2Param {
  int               dt;            // t向dilation
  int               dh;            // 纵向dilation
  int               dw;            // 横向diliation
  int               pad_t_0;       // t向top的padding值
  int               pad_t_1;       // t向bottom的padding值
  int               pad_h_0;       // 纵向top的padding值
  int               pad_h_1;       // 纵向bottom的padding值
  int               pad_w_0;       // 横向left的padding值
  int               pad_w_1;       // 横向right的padding值
  int               stride_t;      // t向stride的值
  int               stride_h;      // 纵向stride的值
  int               stride_w;      // 横向stride的值
  int               groups;        // conv的groups值,若ic=oc=groups时,则为depthwise conv
  bool              has_bias;      // 是否包含tensor_bias
  /* Parameters for quantized computation */
  bool              is_izp_const;  // input的zero point是否为const
  int               izp_val;       // input的zero point, if is_izp_const为true
  std::vector<int>  izp_vec;       // input的zero point vector, if is_izp_const为false
  bool              is_kzp_const;  // weight的zero point是否为const
  int               kzp_val;       // weight的zero point, if is_kzp_const为true
  std::vector<int>  kzp_vec;       //weight的zero point vector, if is_kzp_const为false
} Conv3DV2Param;

三维卷积即深度学习中普遍的三维卷积计算。这里主要介绍定点下的三维卷积定点计算, 该操作对应的定点三维卷积计算式为:

for c in channel
  izp = is_izp_const ? izp_val : izp_vec[c];
  kzp = is_kzp_const ? kzp_val : kzp_vec[c];
  output = (input - izp) Conv3d (weight - kzp) + bias[c];

其中Conv3d表示3D卷积计算。

要求input/weight的数据类型只能是INT8/UINT8。bias的数据类型要求是INT32/UINT32。 output可以是INT32/UINT32,不限制输出符号。

支持平台:BM1686

该操作属于 本地操作

deconv_v2

二维反卷积计算。

void deconv_v2(
  vector<Tensor*> tensor_i, // [in]
  Tensor& tensor_o,         // [out]
  ConvV2Param param);       // [in]
// example:
// vector<Tensor*> vec = {&tensor_input, &tensor_weight, &tensor_bias};
// BMlang::ConvV2Param param;
// param.xxx = xxx
// deconv_v2(vec, tensor_output, param);

参数说明: tensor_i:依次压入tensor_input, tensor_weight, tensor_bias(如果存在)的地址。 tensor_o:Tensor类型。

tensor_input要求是NCHW的shape和数据排布。tensor_weight的数据排布和shape要求是[ic, oc, kt, kh, kw]。

param: Conv3DV2Param类型,包含deconv3d_v2各参数,定义同conv3d_v2的参数,详细请见操作conv3d_v2。

二维反卷积即深度学习中普遍的二维反卷积计算。这里主要介绍定点下的二维反卷积定点计算, 该操作对应的定点二维反卷积计算式为:

for c in channel:
    izp = is_izp_const ? izp_val : izp_vec[c]
    kzp = is_kzp_const ? kzp_val : kzp_vec[c]
    output = (input - izp) Deconv (weight - kzp) + bias[c]

其中Deconv表示反卷积计算。

要求input/weight的数据类型只能是INT8/UINT8。bias的数据类型要求是INT32/UINT32。 output可以是INT32/UINT32,不限制输出符号。

支持平台:BM1686

该操作属于 本地操作

deconv3d_v2

三维反卷积计算。

void deconv3d_v2(
  vector<Tensor*> tensor_i, // [in]
  Tensor& tensor_o,         // [out]
  Conv3DV2Param param);       // [in]
// example:
// vector<Tensor*> vec = {&tensor_input, &tensor_weight, &tensor_bias};
// BMlang::Conv3DV2Param param;
// param.xxx = xxx
// deconv3d_v2(vec, tensor_output, param);

参数说明: tensor_i:依次压入tensor_input, tensor_weight, tensor_bias(如果存在)的地址。 tensor_o:Tensor类型。

tensor_input要求是NCHW的shape和数据排布。tensor_weight的数据排布和shape要求是[ic, oc, kh, kw]。

param: ConvV2Param类型,包含deconv_v2各参数,定义同conv_v2的参数,详细请见操作conv_v2。

三维反卷积即深度学习中普遍的三维反卷积计算。这里主要介绍定点下的三维反卷积定点计算, 该操作对应的定点三维反卷积计算式为:

for c in channel:
    izp = is_izp_const ? izp_val : izp_vec[c]
    kzp = is_kzp_const ? kzp_val : kzp_vec[c]
    output = (input - izp) Deconv3D (weight - kzp) + bias[c]

其中Deconv3D表示反卷积计算。

要求input/weight的数据类型只能是INT8/UINT8。bias的数据类型要求是INT32/UINT32。 output可以是INT32/UINT32,不限制输出符号。

支持平台:BM1686

该操作属于 本地操作

matrix_mul_v2

矩阵乘计算。 matrix_result = matrix_left * matrix_right,对输入两个矩阵做乘法,例如:mat_l(m,k) * mat_r(k,n)输出的matrix是mat_res(m,n)。

void matrix_mul_v2(
  const vector<Tensor*> matrix_input, // [in]
  Tensor& matrix_result,              // [out]
  MatrixMulV2Param param);            // [in]
// example:
// vector<Tensor*> vec = {&tensor_left, &tensor_right, &tensor_bias};
// BMlang::MatrixMulV2Param param;
// param.xxx = xxx
// matrix_mul_v2(vec, tensor_output, param);

参数说明: matrix_input:依次压入matrix_left, matrix_right, bias(如果存在)的地址。 matrix_result:Tensor类型。

matrix_left的shape为2-5维,5维数据排列要求是[shape0, shape1, shape2, left_row, left_column],2维数据排列要求是[left_row, left_column]。其他维度以此类推。 matrix_right的shape有也是2-5维。5维数据排列要求是[shape0, shape1, shape2, right_row, right_column],right_row = left_column。 matrix_bias的shape要求是[right_column]。

param: MatrixMulV2Param类型,包含matrix_mul_v2各参数,定义如下

typedef struct MatrixMulV2Param {
  // The parameters for quantized computation
  bool              has_bias;         // 是否有bias
  bool              is_left_trans;    // matrix_left是否转置,如果true,shape[-2]=left_column,shape[-1]=left_row
  bool              is_right_trans;   // matrix_right是否转置,
  bool              is_lzp_const;     // matrix_left的zero_point是否为const
  int               lzp_val;          // matrix_left的zero point, if is_izp_const为true
  std::vector<int>  lzp_vec;          // matrix_left的zero point, if is_izp_const为false
  bool              is_rzp_const;     // matrix_right的zero_point是否为const
  int               rzp_val;          // matrix_right的zero point, if is_rzp_const为true
  std::vector<int>  rzp_vec;          // matrix_right的zero point, if is_rzp_const为false
} MatrixMulV2Param;

这里主要介绍定点下的二维卷积计算,该操作对应的定点二维卷积计算式为:

output = (left - zp_l) MatrixMul (right - zp_r) + bias;

其中Matrix表示矩阵乘计算。

要求left/right的数据类型只能是INT8/UINT8。bias的数据类型要求是INT32/UINT32。 output可以是INT32/UINT32,不限制输出符号。

支持平台:BM1686

该操作属于 全局操作

fc_int

全连接计算。

void fc_int(
  const std::vector<Tensor *> &inputs,  // [in]
  Tensor &output,                       // [out]
  const FCIntParam &param);             // [in]
// example:
// vector<Tensor*> vec = {&tensor_input, &tensor_weight, &tensor_bias};
// BMlang::FCIntParam param;
// param.xxx = xxx
// fc_int(vec, tensor_output, param);

参数说明: fc_input:依次压入tensor_input, tensor_kernel, tensor_bias(如果存在)的地址。 fc_result:Tensor类型。

input的shape为3维,数据排列要求是[batch, left_row, accum_depth]。 kernel的shape有也是2维。数据排列要求是[accum_depth, output_depth]。 bias的shape要求是[output_depth]。

param: FCIntParam类型,包含fc_int各参数,定义如下

typedef struct FCIntParam {
  // The parameters for quantized computation
  bool              has_bias;         // 是否有bias
  bool              weight_trans;     // tensor_kernel是否转置,如果true,shape=[output_depth,accum_depth]
  bool              is_izp_const;     // input的zero_point是否为const
  int               izp_val;          // input的zero point, if is_izp_const为true
  std::vector<int>  izp_vec;          // input的zero point, if is_izp_const为false
  bool              is_kzp_const;     // kernel的zero_point是否为const
  int               kzp_val;          // kernel的zero point, if is_kzp_const为true
  std::vector<int>  kzp_vec;          // kernel的zero point, if is_kzp_const为false
} FCIntParam;

这里主要介绍定点下的二维卷积计算,该操作对应的定点二维卷积计算式为:

output = (left - zp_l) FC (right - zp_r) + bias;

其中FC表示全连接计算。

要求input/kernel的数据类型只能是INT8/UINT8。bias的数据类型要求是INT32/UINT32。 output可以是INT32/UINT32,不限制输出符号。

支持平台:BM1686

该操作属于 全局操作

softmax_int

softmax定点计算。

void softmax_int(
  const Tensor &inputs,             // [in]
  Tensor &output,                   // [out]
  const SoftmaxIntParam &param);    // [in]
// example:
// BMlang::SoftmaxIntParam param;
// param.xxx = xxx
// softmax_int(tensor_input, tensor_output, param);

参数说明: softmax_input和softmax_result:Tensor类型。

input的shape与数据排列为NCHW或NC

param: SoftmaxIntParam类型,包含softmax_int各参数,定义如下

typedef struct SoftmaxIntParam {
  float table[256];     // exp table
  float scale;
  int zero_point;
} SoftmaxIntParam;

这里主要介绍定点下的二维卷积计算,该操作对应的定点二维卷积计算式为:

for n,h,w in N,H,W
  max_val = max(input[n,c,h,w] for c in C)
  sum_exp = sum(table[max_val - input[n,c,h,w]] for c in C)
  for c in C
    prob = table[max_val - input[n,c,h,w]] / sum_exp
    output[n,c,h,w] = saturate(int(round(prob * scale)) + zero_point),    其中saturate饱和到output数据类型

要求input的数据类型只能是INT8/UINT8。 output的数据类型与input一致。

支持平台:BM1686

该操作属于 本地操作

Base Element-wise Operator

mul

tensor_o = tensor_i0 * tensor_i1,实现两个tensor按元素乘。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void mul(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:tensor的数据类型可以是FLOAT32/INT32/INT8/UINT8。INT32会被转成FLOAT32来计算。tensor_i0和tensor_i1是INT8/UINT8时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。定点计算时,若结果超出位宽时将做饱和处理。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8。

该操作属于 本地操作

div

tensor_o = tensor_i0 / tensor_i1,实现两个tensor按元素除。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void div(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型只能是FLOAT32。

  • BM1686(TODO):tensor的数据类型可以是FLOAT32/FLOAT16。

该操作属于 本地操作

add

tensor_o = tensor_i0 + tensor_i1,实现两个tensor按元素加。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void add(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:tensor的数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。INT32会被转成FLOAT32来计算。tensor_i0和tensor_i1是INT8/UINT8/INT16/UINT16时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。如果tensor_o是UINT16,tensor_i0和tensor_i1不能有INT16数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT32/UINT32/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

sub

tensor_o = tensor_i0 - tensor_i1,实现两个tensor按元素减。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void sub(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:tensor的数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。INT32会被转成FLOAT32来计算。tensor_i0和tensor_i1是INT8/UINT8/INT16/UINT16时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。如果tensor_o是UINT16,tensor_i0和tensor_i1不能有INT16数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT32/UINT32/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

max

tensor_o = max(tensor_i0, tensor_i1),实现两个tensor按元素取最大值。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void max(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:tensor的数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。INT32会被转成FLOAT32来计算。输入输出数据类型要求一致。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT32/UINT32/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

min

tensor_o = min(tensor_i0, tensor_i1),实现两个tensor按元素取最小值。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void min(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:tensor的数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。INT32会被转成FLOAT32来计算。输入输出数据类型要求一致。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT32/UINT32/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

adds

tensor_o = tensor_i0 + scalar,实现tensorA中每个元素都加上scalar。

void adds(
const Tensor& tensor_i0, // [in]
const Scalar& scalar,    // [in]
Tensor& tensor_o)        // [out]
  • BM1682:数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。INT32会被转成FLOAT32来计算。tensor_i0和scalar是INT8/UINT8/INT16/UINT16时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。定点计算时,若结果超出位宽将做饱和处理。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/UINT32/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

subs

tensor_o = tensor_i0 - scalar,实现tensorA中每个元素都减去scalar。

void subs(
const Tensor& tensor_i0, // [in]
const Scalar& scalar,    // [in]
Tensor& tensor_o)        // [out]
  • BM1682:数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。INT32会被转成FLOAT32来计算。tensor_i0和scalar是INT8/UINT8/INT16/UINT16时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。如果tensor_o是UINT16,tensor_i0和scalar不能有INT16数据类型存在。定点计算时,若结果超出位宽将做饱和处理。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/UINT32/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

muls

tensor_o = tensor_i0 * scalar,实现tensorA中每个元素都乘以scalar。

void muls(
const Tensor& tensor_i0, // [in]
const Scalar& scalar,    // [in]
Tensor& tensor_o)        // [out]
  • BM1682:数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8。INT32会被转成FLOAT32来计算。tensor_i0和scalar是INT8/UINT8时,tensor_o可以是INT8/UINT8/INT16/UINT16,不要求输入输出数据类型一致。定点计算时,若结果超出位宽将做饱和处理。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8。

该操作属于 本地操作

divs

tensor_o = tensor_i0 / scalar,实现tensorA中每个元素都除以scalar。

void divs(
const Tensor& tensor_i0, // [in]
const Scalar& scalar,    // [in]
Tensor& tensor_o)        // [out]
  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型只能是FLOAT32。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16。

该操作属于 本地操作

rsubs

tensor_o = scalar - tensor_i,实现scalar都减去tensorA中每个元素。

void rsubs(
const Scalar& scalar,    // [in]
const Tensor& tensor_i,  // [in]
Tensor& tensor_o)        // [out]
  • BM1682:数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。INT32会被转成FLOAT32来计算。tensor_i0和scalar是INT8/UINT8/INT16/UINT16时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。如果tensor_o是UINT16,tensor_i0和scalar不能有INT16数据类型存在。若结果超出位宽则做饱和处理。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/UINT32/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

rdivs

tensor_o = scalar / tensor_i,实现scalar都除以tensorA中每个元素。

void rdivs(
const Scalar& scalar,    // [in]
const Tensor& tensor_i,  // [in]
Tensor& tensor_o)        // [out]
  • BM1684:数据类型可以是FLOAT32。

  • BM1686(TODO):tensor的数据类型可以是FLOAT32/FLOAT16。

该操作属于 本地操作

axpy

实现运算:tensor_o = scalar * tensor_i + tensor_o。

void axpy(
const Tensor& tensor_i,  // [in]
const Scalar& scalar,    // [in]
Tensor& tensor_o)        // [in/out]
  • BM1684:数据类型可以是FLOAT32。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16。

该操作属于 本地操作

maxs

tensor_o = max(tensor_i0, scalar),实现tensorA中每个元素都与scalar比较大小,取大值输出。

void maxs(
const Tensor& tensor_i0, // [in]
const Scalar& scalar,    // [in]
Tensor& tensor_o)        // [out]
  • BM1682:数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。INT32会被转成FLOAT32来计算。要求输入输出数据类型保持一致。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/UINT32/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

mins

tensor_o = min(tensor_i0, scalar),实现tensorA中每个元素都与scalar比较大小,取小值输出。

void mins(
const Tensor& tensor_i0, // [in]
const Scalar& scalar,    // [in]
Tensor& tensor_o)        // [out]
  • BM1682:数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。INT32会被转成FLOAT32来计算。要求输入输出数据类型保持一致。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/UINT32/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

active

对输入的tensor使用激活函数进行处理,激活类型在bmlang_common.h文件中ActiveType定义。 支持的active type如下:

typedef enum {
  ACTIVE_TANH   ,
  ACTIVE_SIGMOID,
  ACTIVE_RELU   ,
  ACTIVE_EXP    ,
  ACTIVE_ELU    ,
  ACTIVE_SQRT   ,
  ACTIVE_SQUARE ,
  ACTIVE_RSQRT  ,
  ACTIVE_ABSVAL ,
  ACTIVE_LN     ,     //(ln对数)
  ACTIVE_ROUND  ,
  ACTIVE_CEIL   ,
  ACTIVE_FLOOR  ,
  ACTIVE_SIN    ,
  ACTIVE_COS    ,
  ACTIVE_LEAKY_RELU,
  UNKNOWN_ACTIVE_TYPE
} ActiveType;

void active(
const Tensor& tensor_i,  // [in]
Tensor& tensor_o,        // [out]
ActiveType active_type); // [in]

参数说明:

tensor_i,tensor_o均是Tensor类型;

active_type是ActiveType类型,指定激活函数的类型。注意如果配置active_type==ACTIVE_LEAKY_RELU,在此接口中无法配置negative_slope,等价于negative_slope使用默认值0,此时的leaky_relu等价与relu。

  • BM1682:数据类型只能是FLOAT32。

  • BM1684:ACTIVE_RELU、ACTIVE_LEAKY_RELU、ACTIVE_ABSVAL的输入输出可以是FLOAT32/INT8/UINT8/INT16/UINT16,其它数据类型只能是FLOAT32。ACTIVE_RELU、ACTIVE_ABSVAL输入是INT8/UINT8/INT16/UINT16,输出可以是INT8/UINT8/INT16/UINT16,输入输出数据类型不要求一致,结果超出位宽时做饱和处理。

  • BM1686:ACTIVE_RELU、ACTIVE_LEAKY_RELU、ACTIVE_ABSVAL额外支持FLOAT16,其余同BM1684。

该操作属于 本地操作

active_param

对输入的tensor使用激活函数进行处理,激活类型在bmlang_common.h文件中ActiveType定义。 支持的active type如下:

typedef enum {
  ACTIVE_TANH   ,
  ACTIVE_SIGMOID,
  ACTIVE_RELU   ,
  ACTIVE_EXP    ,
  ACTIVE_ELU    ,
  ACTIVE_SQRT   ,
  ACTIVE_SQUARE ,
  ACTIVE_RSQRT  ,
  ACTIVE_ABSVAL ,
  ACTIVE_LN     ,     //(ln对数)
  ACTIVE_ROUND  ,
  ACTIVE_CEIL   ,
  ACTIVE_FLOOR  ,
  ACTIVE_SIN    ,
  ACTIVE_COS    ,
  ACTIVE_LEAKY_RELU,
  UNKNOWN_ACTIVE_TYPE
} ActiveType;

void active_param(
const Tensor& tensor_i,          // [in]
Tensor& tensor_o,                // [out]
ActiveType active_type,          // [in]
std::vector<float> params = {}); // [in]

参数说明:

tensor_i,tensor_o均是Tensor类型;

active_type是ActiveType类型,指定激活函数的类型。

params是vector<float>类型,用来存放传入的其他浮点参数。目前配置active_type==ACTIVE_LEAKY_RELU后,params用来传入negative_slope,如果改vector为空的话则等同negative_slope==0的情况;配置active_type为非ACTIVE_LEAKY_RELU则与active接口含义相同,此时params参数会被忽略。

  • BM1682:数据类型只能是FLOAT32。

  • BM1684:ACTIVE_RELU、ACTIVE_LEAKY_RELU、ACTIVE_ABSVAL的输入输出可以是FLOAT32/INT8/UINT8/INT16/UINT16,其它数据类型只能是FLOAT32。ACTIVE_RELU、ACTIVE_ABSVAL输入是INT8/UINT8/INT16/UINT16,输出可以是INT8/UINT8/INT16/UINT16,输入输出数据类型不要求一致,结果超出位宽时做饱和处理。

  • BM1686:ACTIVE_RELU、ACTIVE_LEAKY_RELU、ACTIVE_ABSVAL额外支持FLOAT16,其余同BM1684。

该操作属于 本地操作

ceil

数据向上取整函数,只支持float32数据类型

void ceil(const Tensor& tensor_i, // [in]
          Tensor& tensor_o);      // [out]

该操作属于 本地操作

  • BM1684:数据类型只能是FLOAT32。

  • BM1686:数据类型只能是FLOAT32。

floor

向下取整函数,只支持float32数据类型

void floor(const Tensor& tensor_i, // [in]
           Tensor& tensor_o);      // [out]

该操作属于 本地操作

  • BM1684:数据类型只能是FLOAT32。

  • BM1686:数据类型只能是FLOAT32。

round

四舍五入取整函数,只支持float32数据类型

void floor(const Tensor& tensor_i, // [in]
           Tensor& tensor_o);      // [out]

该操作属于 本地操作

  • BM1684:数据类型只能是FLOAT32。

  • BM1686:数据类型只能是FLOAT32。

clamp

将输入tensor data限制在按照最大最小值区间内。

void clamp(const Tensor& tensor_i, // [in]
           const Scalar& min,      // [in]
           const Scalar& max,      // [in]
           Tensor& tensor_o);      // [out]
  • BM1682:数据类型只能是FLOAT32和INT32。INT32会被转成FLOAT32来计算。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。INT32会被转成FLOAT32来计算。输入输出数据类型要求一致。

  • BM1686:同BM1684。

该操作属于 本地操作

cast

数据类型转换

void cast(
const Tensor& tensor_i, // [in]
Tensor& tensor_o)       // [out]
  • BM1682:支持FLOAT32<->INT32,FLOAT32<->INT8/UINT8的相互转换。

  • BM1684:支持FLOAT32<->INT32,INT16/UINT16<->FLOAT32,INT8/UINT8<->FLOAT32,INT16/UINT16<->INT8/UINT8,INT16<->UINT16,INT8<->UINT8的相互转换。数据转换时,若位宽不够则做饱和处理。浮点向定点转换时,做四舍五入处理。

  • BM1686:新增FLOAT16,支持FLOAT16和其他格式互转,其余同BM1684。

该操作属于 受限的本地操作 。BM1682下,满足FLOAT32->INT32时才能做本地操作。 BM1684下,不是INT32->FLOAT32时即可做本地操作。

mul_shift

tensor_o = (tensor_i0 * tensor_i1) >> shift,实现tensor_i0和tensor_i1的每个元素相乘后再四舍五入的算术右移shift位。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

不同于定点mul操作加一次arith_rshifts操作,mul_shift数据相乘以INT32为中间结果保存,然后在INT32基础上做一次四舍五入的算数右移操作。

void mul_shift(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
unsigned int shift,      // [in]
Tensor& tensor_o)        // [out]

四舍五入的算术右移操作即:

// x是被右移的数据
// shift是右移值
// result是结果
if (shift > 0) {
  result = ( (x >> (shfit - 1)) + 1 ) >> 1;
} else {
  // do nothing
}
  • BM1682:不支持该操作。

  • BM1684:tensor_i0可以是INT8/UINT8/INT16/UINT16,tensor_i1只能是INT8/UINT8,tensor_o可以是INT8/UINT8/INT16/UINT16,不要求输入输出位宽一致,结果超过位宽时做饱和处理。当tensor_i0是INT16/UINT16时,若tensor_i0或tensor_i1至少有一个是有符号数,则输出要求是有符号数。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

add_shift

tensor_o = (tensor_i0 + tensor_i1) >> shift,实现tensor_i0和tensor_i1的每个元素相加后再四舍五入的算术右移shift位。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

不同于定点add操作加一次arith_rshifts操作,add_shift数据相加后以INT32为中间结果保存,然后在INT32基础上做一次四舍五入的算数右移操作。

void add_shift(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
unsigned int shift,      // [in]
Tensor& tensor_o)        // [out]
  • BM1682:不支持该操作。

  • BM1684:输入数据类型均可以是INT8/UINT8/INT16/UINT16。不要求输入输出位宽一致,结果超过位宽时做饱和处理。若输入输出都为INT16/UINT16且输入中至少有一个为有符号数时,输出则要求是有符号数。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

sub_shift

tensor_o = (tensor_i0 - tensor_i1) >> shift,实现tensor_i0和tensor_i1的每个元素相减后再四舍五入的算术右移shift位。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

不同于定点sub操作加一次arith_rshifts操作,sub_shift数据相减后以INT32为中间结果保存,然后在INT32基础上做一次四舍五入的算数右移操作。

void sub_shift(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
unsigned int shift,      // [in]
Tensor& tensor_o)        // [out]
  • BM1682:不支持该操作。

  • BM1684:输入数据类型均可以是INT8/UINT8/INT16/UINT16。不要求输入输出位宽一致,结果超过位宽时做饱和处理。输出符号位要求是有符号的。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

muls_shift

tensor_o = (tensor_i * scalar) >> shift,实现tensor_i每个元素乘scalar后再四舍五入的算术右移shift位。

不同于定点muls操作加一次arith_rshifts操作,muls_shift数据相乘以INT32为中间结果保存,然后在INT32基础上做一次四舍五入的算数右移操作。

void muls_shift(
const Tensor& tensor_i, // [in]
const Scalar& scalar,   // [in]
unsigned int shift,     // [in]
Tensor& tensor_o)       // [out]
  • BM1682:不支持该操作。

  • BM1684:tensor_i可以是INT8/UINT8/INT16/UINT16,scalar只能是INT8/UINT8,tensor_o可以是INT8/UINT8/INT16/UINT16,不要求输入输出位宽一致,结果超过位宽时做饱和处理。当tensor_i是INT16/UINT16时,若tensor_i或scalar至少有一个是有符号数,则输出要求是有符号数。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

adds_shift

tensor_o = (tensor_i + scalar) >> shift,实现tensor_i每个元素加scalar后再四舍五入的算术右移shift位。

不同于定点adds操作加一次arith_rshifts操作,adds_shift数据相加后以INT32为中间结果保存,然后在INT32基础上做一次四舍五入的算数右移操作。

void adds_shift(
const Tensor& tensor_i, // [in]
const Scalar& scalar,   // [in]
unsigned int shift,     // [in]
Tensor& tensor_o)       // [out]
  • BM1682:不支持该操作。

  • BM1684:输入数据类型均可以是INT8/UINT8/INT16/UINT16。不要求输入输出位宽一致,结果超过位宽时做饱和处理。若输入输出都为INT16/UINT16且输入中至少有一个为有符号数时,输出则要求是有符号数。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

subs_shift

tensor_o = (tensor_i - scalar) >> shift,实现tensor_i每个元素减scalar后再四舍五入的算术右移shift位。

不同于定点subs操作加一次arith_rshifts操作,subs_shift数据相减后以INT32为中间结果保存,然后在INT32基础上做一次四舍五入的算数右移操作。

void subs_shift(
const Tensor& tensor_i, // [in]
const Scalar& scalar,   // [in]
unsigned int shift,     // [in]
Tensor& tensor_o)       // [out]
  • BM1682:不支持该操作。

  • BM1684:输入数据类型均可以是INT8/UINT8/INT16/UINT16。不要求输入输出位宽一致,结果超过位宽时做饱和处理。输出符号位要求是有符号的。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

rsubs_shift

tensor_o = (scalar - tensor_i) >> shift,实现scalar减tensor_i每个元素后再四舍五入的算术右移shift位。

不同于定点rsubs操作加一次arith_rshifts操作,rsubs_shift数据相减后以INT32为中间结果保存,然后在INT32基础上做一次四舍五入的算数右移操作。

void rsubs_shift(
const Scalar& scalar,   // [in]
const Tensor& tensor_i, // [in]
unsigned int shift,     // [in]
Tensor& tensor_o)       // [out]
  • BM1682:不支持该操作。

  • BM1684:输入数据类型均可以是INT8/UINT8/INT16/UINT16。不要求输入输出位宽一致,结果超过位宽时做饱和处理。输出符号位要求是有符号的。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

copy

将输入数据复制到输出Tensor中。要求输入输出数据类型一致。

void copy(
const Tensor& tensor_i, // [in]
Tensor& tensor_o);      // [out]
  • BM1682:数据类型能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。

该操作当前属于 全局操作

Element-wise Compare Operator

gt

tensor_o = tensor_i0 > tensor_i1 ? 1 : 0,两个tensor按元素比较,如果A大于B输出1,否则输出0。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void gt(
const Tensor& tensor_i0 , // [in]
const Tensor& tensor_i1,  // [in]
Tensor& tensor_o)         // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

ge

tensor_o = tensor_i0 >= tensor_i1 ? 1 : 0,两个tensor按元素比较,如果A大于等于B输出1,否则输出0。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void ge(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

lt

tensor_o = tensor_i0 < tensor_i1 ? 1 : 0,两个tensor按元素比较,如果A小于B输出1,否则输出0。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void lt(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

le

tensor_o = tensor_i0 <= tensor_i1 ? 1 : 0,两个tensor按元素比较,如果A小于等于B输出1,否则输出0。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void le(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

eq

tensor_o = tensor_i0 == tensor_i1 ? 1 : 0,两个tensor按元素比较,如果A等于B输出1,否则输出0。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void eq(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

ne

tensor_o = tensor_i0 != tensor_i1 ? 1 : 0,两个tensor按元素比较,如果A不等于B输出1,否则输出0。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void ne(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

eqs

tensor_i0中每个元素与scalar_i1进行比较,如果等于输出1, 否则输出0。

void eqs(
const Tensor& tensor_i0, // [in]
const Scalar& scalar_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

nes

tensor_i0中每个元素与scalar_i1进行比较,如果不等于输出1, 否则输出0。

void nes(
const Tensor& tensor_i0, // [in]
const Scalar& scalar_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

ges

tensor_i0中每个元素与scalar_i1进行比较,如果大于等于输出1, 否则输出0。

void nes(
const Tensor& tensor_i0, // [in]
const Scalar& scalar_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

gts

tensor_i0中每个元素与scalar_i1进行比较,如果大于输出1, 否则输出0。

void gts(
const Tensor& tensor_i0, // [in]
const Scalar& scalar_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

les

tensor_i0中每个元素与scalar_i1进行比较,如果小于等于输出1, 否则输出0。

void les(
const Tensor& tensor_i0, // [in]
const Scalar& scalar_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

lts

tensor_i0中每个元素与scalar_i1进行比较,如果小于输出1, 否则输出0。

void lts(
const Tensor& tensor_i0, // [in]
const Scalar& scalar_i1, // [in]
Tensor& tensor_o)        // [out]
  • BM1682:tensor的数据类型只能是FLOAT32。

  • BM1684:tensor的数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

  • BM1686:tensor的数据类型可以是FLOAT32/FLOAT16/INT8/UINT8/INT16/UINT16。输入输出数据类型要求相同。

该操作属于 本地操作

Element-Wise Bit Logic Operator

arith_lshift

对每个tensor_i的元素进行算术左移位操作。 tensor_num可以是coeff。

该操作支持tensor_num的shape广播。

void arith_lshift(
   const Tensor& tensor_i,   // [in]
   const Tensor& tensor_num, // [in]
   Tensor& tensor_o)         // [out]

参数说明: tensor_i: 需要移位的输入数据。 tensor_num: 表示tensor_i中每个元素左移位数。 tensor_num中的元素若>=0, 则是算术左移;若<0,则做算术右移。 tensor_o: 输出tensor。

  • BM1682:不支持该操作。

  • BM1684:tensor的数据类型可以是INT32/INT16/UINT16。若tensor_i是INT32,tensor_num要求是INT32。若tensor_i是INT16/UINT16,tensor_num要求是INT16。tensor_i/tensor_o要求数据类型相同。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

arith_lshifts

对每个tensor_i的元素进行左移位操作。

void arith_lshifts(
   const Tensor& tensor_i,   // [in]
   const Scalar& scalar_num, // [in]
   Tensor& tensor_o)         // [out]

参数说明: tensor_i: 需要移位的输入数据。 scalar_num: 其值表示tensor_i中每个元素左移位数。 scalar_num若>=0,则是算术左移;若<0,则做算术右移。 tensor_o: 输出tensor。

  • BM1682:不支持该操作。

  • BM1684:数据类型可以是INT32/INT16/UINT16。tensor_i/tensor_o要求数据类型相同。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

arith_rshift

对每个tensor_i的元素进行算术右移位操作。 tensor_num可以是coeff。

该操作支持tensor_num的shape广播。

void arith_rshift(
   const Tensor& tensor_i,   // [in]
   const Tensor& tensor_num, // [in]
   Tensor& tensor_o)         // [out]

参数说明: tensor_i: 需要移位的输入数据。 tensor_num: 表示tensor_i中每个元素右移位数。 tensor_num中的元素若>=0, 则是算术右移;若<0,则做算术左移。 tensor_o: 输出tensor。

  • BM1682:不支持该操作。

  • BM1684:tensor的数据类型可以是INT32/INT16/UINT16。若tensor_i是INT32,tensor_num要求是INT32。若tensor_i是INT16/UINT16,tensor_num要求是INT16。tensor_i/tensor_o要求数据类型相同。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

arith_rshifts

对每个tensor_i的元素进行右移位操作

void arith_rshifts(
   const Tensor& tensor_i,   // [in]
   const Scalar& scalar_num, // [in]
   Tensor& tensor_o)         // [out]

参数说明: tensor_i: 需要移位的输入数据。 scalar_num: 其值表示tensor_i中每个元素右移位数。 scalar_num若>=0,则是算术右移;若<0,则做算术左移。 tensor_o: 输出tensor。

  • BM1682:不支持该操作。

  • BM1684:数据类型可以是INT32/INT16/UINT16。tensor_i/tensor_o要求数据类型相同。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

round_rshift

对每个tensor_i的元素进行四舍五入的右移位操作。 tensor_num可以是coeff。

该操作支持tensor_num的shape广播。

void round_rshift(
   const Tensor& tensor_i,   // [in]
   const Tensor& tensor_num, // [in]
   Tensor& tensor_o)         // [out]

参数说明: tensor_i: 需要移位的输入数据。 tensor_num: shape与tensor_i相同,表示tensor_i中每个元素右移位数。 tensor_o: 输出tensor。

四舍五入的算术右移操作即:

// x是被右移的数据
// shift是右移值
// result是结果
if (shift > 0) {
  result = ( (x >> (shfit - 1)) + 1 ) >> 1;
} else {
  // do nothing
}
  • BM1682:不支持该操作。

  • BM1684:tensor_i数据类型要求是INT16/UINT16,tensor_num要求是INT16,tensor_o数据类型可以是INT16/UINT16/INT8/UINT8。输入输出要求正负符号一致,但不要求位宽一致。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

round_rshifts

对每个tensor_i的元素进行四舍五入的右移位操作。

void round_rshifts(
   const Tensor& tensor_i,   // [in]
   const Scalar& tensor_num, // [in]
   Tensor& tensor_o)         // [out]

参数说明: tensor_i: 需要移位的输入数据。 scalar_num: 其值表示tensor_i中每个元素右移位数。 tensor_o: 输出tensor。

  • BM1682:不支持该操作。

  • BM1684:tensor_i数据类型要求是INT16/UINT16,tensor_o数据类型可以是INT16/UINT16/INT8/UINT8。输入输出要求正负符号一致,但不要求位宽一致。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

bit_and

tensor_i0与tensor_i1进行比特位与操作。

void bit_and(
   const Tensor& tensor_i0, // [in]
   const Tensor& tensor_i1, // [in]
   Tensor& tensor_o)        // [out]
  • BM1682:不支持该操作。

  • BM1684:数据类型可以是INT32/INT8/UINT8/INT16/UINT16。要求输入输出的数据类型都相同。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

bit_ands

tensor_i与scalar_i进行比特位与操作

void bit_ands(
   const Tensor& tensor_i, // [in]
   const Scalar& scalar_i, // [in]
   Tensor& tensor_o)       // [out]
  • BM1682:不支持该操作。

  • BM1684:数据类型可以是INT32/INT8/UINT8/INT16/UINT16。要求输入输出的数据类型都相同。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

bit_or

tensor_i0与tensor_i1进行比特位或操作

void bit_or(
   const Tensor& tensor_i0, // [in]
   const Tensor& tensor_i1, // [in]
   Tensor& tensor_o)        // [out]
  • BM1682:不支持该操作。

  • BM1684:数据类型可以是INT32/INT8/UINT8/INT16/UINT16。要求输入输出的数据类型都相同。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

bit_ors

tensor_i与scalar_i进行比特位或操作

void bit_ors(
   const Tensor& tensor_i, // [in]
   const Scalar& scalar_i, // [in]
   Tensor& tensor_o)       // [out]
  • BM1682:不支持该操作。

  • BM1684:数据类型可以是INT32/INT8/UINT8/INT16/UINT16。要求输入输出的数据类型都相同。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

bit_xor

tensor_i0与tensor_i1进行比特位异或操作

void bit_xor(
   const Tensor& tensor_i0, // [in]
   const Tensor& tensor_i1, // [in]
   Tensor& tensor_o)        // [out]
  • BM1682:不支持该操作。

  • BM1684:数据类型可以是INT32/INT8/UINT8/INT16/UINT16。要求输入输出的数据类型都相同。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

bit_xors

tensor_i与scalar_i进行比特位异或操作

void bit_xors(
   const Tensor& tensor_i, // [in]
   const Scalar& scalar_i, // [in]
   Tensor& tensor_o)       // [out]
  • BM1682:不支持该操作。

  • BM1684:数据类型可以是INT32/INT8/UINT8/INT16/UINT16。要求输入输出的数据类型都相同。

  • BM1686(TODO):同BM1684。

该操作属于 本地操作

Triangle Operator

sin

正弦函数计算。

void sin(const Tensor& tensor_i, // [in]
         Tensor& tensor_o);      // [out]
  • BM1682:只支持FLOAT32数据类型。

  • BM1684:只支持FLOAT32数据类型。

  • BM1686:只支持FLOAT32数据类型。

该操作属于 本地操作

cos

余弦函数计算。

void cos(const Tensor& tensor_i, // [in]
         Tensor& tensor_o);      // [out]
  • BM1682:只支持FLOAT32数据类型。

  • BM1684:只支持FLOAT32数据类型。

  • BM1686:只支持FLOAT32数据类型。

该操作属于 本地操作

Stride Element-Wise Operator

stride_add

tensor_o = tensorA_i + tensorB_i,依据各个dimension上设置的stride值执行两个tensor相应index的元素加。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_add(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效;

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT16/UINT16/INT8/UINT8。 tensor_i0和tensor_i1是INT8/UINT8/INT16/UINT16时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。 如果tensor_o是UINT16,tensor_i0和tensor_i1不能有INT16数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

  • BM1686(TODO):在BM1684的基础上增加FLOAT16的支持,其余同BM1684。

该操作属于 本地操作

stride_sub

tensor_o = tensorA_i - tensorB_i,依据各个dimension上设置的stride值执行两个tensor相应index的元素减。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_sub(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效;

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT16/UINT16/INT8/UINT8。 tensor_i0和tensor_i1是INT8/UINT8/INT16/UINT16时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。 如果tensor_o是UINT16,tensor_i0和tensor_i1不能有INT16数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

  • BM1686(TODO):在BM1684的基础上增加FLOAT16的支持,其余同BM1684。

该操作属于 本地操作

stride_mul

tensor_o = tensorA_i * tensorB_i,依据各个dimension上设置的stride值执行两个tensor相应index的元素乘。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_mul(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效;

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT8/UINT8。 tensor_i0和tensor_i1是INT8/UINT8时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。定点计算时,若结果超出位宽时将做饱和处理。

  • BM1686(TODO):在BM1684的基础上增加FLOAT16的支持,其余同BM1684。

该操作属于 本地操作

stride_div

tensor_o = tensorA_i / tensorB_i,依据各个dimension上设置的stride值执行两个tensor相应index的元素除。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_div(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效;

  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型只能是FLOAT32。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16。

该操作属于 本地操作

stride_max

tensor_o = max(tensorA_i, tensorB_i),依据各个dimension上设置的stride值执行两个tensor相应index的元素比较,取大值输出。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_max(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效;

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT16/UINT16/INT8/UINT8。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

stride_min

tensor_o = min(tensorA_i, tensorB_i),依据各个dimension上设置的stride值执行两个tensor相应index的元素比较,取小值输出。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_min(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效;

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT16/UINT16/INT8/UINT8。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

stride_cpy

依据各个dimension上设置的stride,将输入Tensor相应index的元素依次复制到输出Tensor中。要求输入输出数据类型一致。

void stride_cpy(
const Tensor& tensor_i, // [in]
Tensor& tensor_o,       // [out]
vector<int> stride)     // [in]

参数说明: tensor_i,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride;

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT16/UINT16/INT8/UINT8。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

stride_add_offset

tensor_o = tensorA_i_offset + tensorB_i_offset,以各个dimension上设置的offset为起点,并依据设置的stride值执行两个tensor相应index的元素加。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_add_offset(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride,      // [in]
vector<int> offset)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效; offset用于指定shape每个维度上的offset,仅对非广播的维度有效。

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT16/UINT16/INT8/UINT8。 tensor_i0和tensor_i1是INT8/UINT8/INT16/UINT16时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。 如果tensor_o是UINT16,tensor_i0和tensor_i1不能有INT16数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

  • BM1686(TODO):在BM1684的基础上增加FLOAT16的支持,其余同BM1684。

该操作属于 本地操作

stride_sub_offset

tensor_o = tensorA_i_offset - tensorB_i_offset,以各个dimension上设置的offset为起点,并依据设置的stride值执行两个tensor相应index的元素减。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_sub_offset(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride,      // [in]
vector<int> offset)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效; offset用于指定shape每个维度上的offset,仅对非广播的维度有效。

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT16/UINT16/INT8/UINT8。 tensor_i0和tensor_i1是INT8/UINT8/INT16/UINT16时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。 如果tensor_o是UINT16,tensor_i0和tensor_i1不能有INT16数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

  • BM1686(TODO):在BM1684的基础上增加FLOAT16的支持,其余同BM1684。

该操作属于 本地操作

stride_mul_offset

tensor_o = tensorA_i_offset * tensorB_i_offset,以各个dimension上设置的offset为起点,并依据设置的stride值执行两个tensor相应index的元素乘。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_mul_offset(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride,      // [in]
vector<int> offset)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效; offset用于指定shape每个维度上的offset,仅对非广播的维度有效。

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT8/UINT8。 tensor_i0和tensor_i1是INT8/UINT8时,tensor_o可以是INT8/UINT8/INT16/UINT16,此时不要求输入输出数据类型一致。定点计算时,若结果超出位宽时将做饱和处理。

  • BM1686(TODO):在BM1684的基础上增加FLOAT16的支持,其余同BM1684。

该操作属于 本地操作

stride_div_offset

tensor_o = tensorA_i_offset / tensorB_i_offset,以各个dimension上设置的offset为起点,并依据设置的stride值执行两个tensor相应index的元素除。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_div_offset(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride,      // [in]
vector<int> offset)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效; offset用于指定shape每个维度上的offset,仅对非广播的维度有效。

  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型只能是FLOAT32。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16。

该操作属于 本地操作

stride_max_offset

tensor_o = max(tensorA_i_offset, tensorB_i_offset),以各个dimension上设置的offset为起点,并依据设置的stride值执行两个tensor相应index的元素比较,取大值输出。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_max_offset(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride,      // [in]
vector<int> offset)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效; offset用于指定shape每个维度上的offset,仅对非广播的维度有效。

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT16/UINT16/INT8/UINT8。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

stride_min_offset

tensor_o = min(tensorA_i_offset, tensorB_i_offset),以各个dimension上设置的offset为起点,并依据设置的stride值执行两个tensor相应index的元素比较,取小值输出。 tensor_i0或者tensor_i1可以被指定为COEFF_TENSOR。

该操作支持shape广播。

void stride_min_offset(
const Tensor& tensor_i0, // [in]
const Tensor& tensor_i1, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride,      // [in]
vector<int> offset)      // [in]

参数说明: tensor_i0,tensor_i1,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride,仅对非广播的维度有效; offset用于指定shape每个维度上的offset,仅对非广播的维度有效。

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT16/UINT16/INT8/UINT8。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

stride_cpy_offset

以各个dimension上设置的offset为起点,并依据设置的stride,将输入Tensor相应index的元素依次复制到输出Tensor中。要求输入输出数据类型一致。

void stride_cpy_offset(
const Tensor& tensor_i, // [in]
Tensor& tensor_o,        // [out]
vector<int> stride,      // [in]
vector<int> offset)      // [in]

参数说明: tensor_i0,tensor_o均是Tensor类型; stride用于指定shape每个维度上的stride; offset用于指定shape每个维度上的offset。

  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT16/UINT16/INT8/UINT8。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16/INT16/UINT16/INT8/UINT8。

该操作属于 本地操作

Data Arrange Operator

permute

置换tensor shape的axis,并相应进行数据的交换。 例如:输入shape为(6,7,8,9),置换参数order为(1,3,2,0),则输出的shape为(7,9,8,6)。

void permute(
const Tensor& tensor_i, // [in]
Tensor& tensor_o,       // [out]
vector<int>& order)     // [in]

参数说明: order是vector<int>类型,指定permute order参数。

  • BM1682:数据类型可以是FLOAT32/INT32/INT8/UINT8。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。

该操作当前属于 全局操作

tile

在指定的维度重复复制数据。std::vector<int>& reps指定每个维度的复制份数。 要求reps.size()与tensor_i和tensor_o的shape维度相等。

void tile(const Tensor& tensor_i,  // [in]
          Tensor& tensor_o,        // [out]
          std::vector<int>& reps); // [in]
// Examples
// tensor_i ==> [[1,2,3],[4,5,6]], tensor_i.shape() = [2,3]
// reps ==> [2,2]
// tile(tensor_i, tensor_o, reps)
// tensor_o ==>
// [ [1,2,3,1,2,3],
//   [4,5,6,4,5,6],
//   [1,2,3,1,2,3],
//   [4,5,6,4,5,6] ]
  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。

该操作当前属于 受限本地操作 。当reps[1] == 1时才能作为局部操作进行合并优化。

tile_v2(TODO)

功能与tile相同,不同的是reps以Tensor的形式存在。 reps的shape要求是1维的。reps可以是其他operator的输出, 该目的是让tile的复制份数可以在运行时改变。

void tile_v2(const Tensor& tensor_i, // [in]
          const Tensor& reps,        // [in]
          Tensor& tensor_o);         // [out]
  • BM1682:tensor_i/tensor_o只能是FLOAT32。reps需要是INT32。

  • BM1684:tensor_i/tensor_o可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。reps需要是INT32。

该操作当前属于 全局操作

broadcast

将输入tensor数据广播到输出。

void broadcast (
const Tensor& tensor_i, // [in]
Tensor& tensor_o,       // [out]
vector<int> times)      // [in]

参数说明: times是vector<int>类型,指定每个维度广播的份数。

该操作各项功能、属性同tile,是tile的翻版。详细信息请见tile。

extract

对tensor各个维度上的数据做带stride的抽取操作。

输出tensor的每个axis的shape值的计算方式为:ceil((end[i] – start[i]) / (float)stride[i])。 例如某个axis的值为10,start为1,end为7,stride为2,则extract之后输出axis的值为(7-1)/ 2 = 3,index分别为1,3,5。

void extract(
const Tensor& tensor_i, // [in]
Tensor& tensor_o,       // [out]
vector<int> start,      // [in]
vector<int> end,        // [in]
vector<int> stride);    // [in]
// Examples
// tensor_i ==> [[1,2,3],[4,5,6]], tensor_i.shape() = [2,3]
// start ==> [0,0], end ==> [2,3], stride ==> [1,2]
// tensor_o ==> [[1,3],[4,6]]

参数说明: start, end, stride是vector<int>类型,指定data extract method参数。

  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。

该操作属于 受限本地操作 。当不会对tensor_i的第[1]维进行抽取操作时,才会做局部操作。

extract_v2

功能同extract,不同的是start/end/stride以Tensor的形式存在。 start/end/stride的shape要求是1维的,且各自的元素数量要等于tensor_i的shape维度。 该目的是让start/end/stride可以在运行时改变。

void extract_v2(
const Tensor& tensor_i, // [in]
const Tensor& start,    // [in]
const Tensor& end,      // [in]
const Tensor& stride,   // [in]
Tensor& tensor_o);      // [out]
  • BM1682:tensor_i/tensor_o只能是FLOAT32。start/end/stride需要是INT32。

  • BM1684:tensor_i/tensor_o可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。start/end/stride需要是INT32。

  • BM1686:新增FLOAT16支持,其余同BM1684。

该操作当前属于 全局操作

interleave

数据交叉排列。

要求tensor_i0和tensor_i1的shape要相同。

void interleave(
    const Tensor& tensor_i0, // [in]
    const Tensor& tensor_i1, // [in]
    Tensor& tensor_o,        // [out]
    int axis,                // [in]
    int step);               // [in]
// Examples
// tensor_i0 ==> [[1,2,3,4],[5,6,7,8]], tensor_i0.shape() = [2,4]
// tensor_i0 ==> [[9,10,11,12],[13,14,15,16]], tensor_i0.shape() = [2,4]
// axis = 1, step = 2
// tensor_o ==>
//  [ [1,2,9,10,3,4,11,12], [5,6,13,14,7,8,15,16] ]
  • BM1682:数据类型能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8。

该操作当前属于 全局操作

concat

对多个tensor 在指定的轴上进行拼接。 要求tensor_i中的每个tensor具有相同的shape维度。

void concat (
const vector<Tensor*>& tensor_i, // [in]
Tensor& tensor_o,                // [out]
int axis);                       // [in]

参数说明: tensor_i是vector<Tensor*>类型,多个tensor的指针; tensor_o是Tensor类型; axis是int类型,指定在哪一个轴上进行拼接。

  • BM1682:数据类型能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。

该操作当前属于 受限本地操作 。当axis != 1时才能做本地操作。 对于BM1684,axis=0且数据类型是INT8/UINT8/INT16/UINT16时,此时做全局操作。

split

将输入tensor_i安装指定axis拆成多个tensor。concat 的逆操作。

void split (
const Tensor& tensor_i,    // [in]
vector<Tensor*>& tensor_o, // [out]
int axis,                  // [in]
int num,                   // [in]
vector<int> size)          // [in]

参数说明: tensor_i是Tensor类型; tensor_o是vector<Tensor*>类型,多个tensor的指针; axis是int类型,指定在哪个轴上split; num是int类型,分裂份数; size是vector<int>类型,非平均分裂时,指定每一份大小,平均分裂时,设置为空。

  • BM1682:数据类型能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。

该操作当前属于 全局操作

pad

边缘补充数据。pad_val是PAD_CONSTANT时要填充的常量数据。 paddings.size()要求等于tensor_i的shape维度乘以2。

void pad(
    const Tensor& tensor_i,           // [in]
    Tensor& tensor_o,                 // [out]
    const Scalar& pad_val,            // [in]
    std::vector<int> paddings,        // [in]
    PadType pad_mode = PAD_CONSTANT); // [in]
// Padding mode
typedef enum {
  PAD_CONSTANT  = 0,
  PAD_REFLECT   = 1,
  PAD_SYMMETRIC = 2,
  PAD_EDGE      = 3
} PadType;
// Examples
// tensor_i ==> [[1,2,3],[4,5,6],[7,8,9]]
// paddings = [2,1,1,2]
// pad_val = 0
// if pad_mode == PAD_CONSTANT:
//   tensor_o ==>
//     [ [0,0,0,0,0,0],
//       [0,0,0,0,0,0],
//       [0,1,2,3,0,0],
//       [0,4,5,6,0,0],
//       [0,7,8,9,0,0],
//       [0,0,0,0,0,0] ]
// if pad_mode == PAD_REFLECT:
//   tensor_o ==>
//     [ [8,7,8,9,8,7],
//       [5,4,5,6,5,4],
//       [2,1,2,3,2,1],
//       [5,4,5,6,5,4],
//       [8,7,8,9,8,7],
//       [5,4,5,6,5,4] ]
// if pad_mode == PAD_SYMMETRIC:
//   tensor_o ==>
//     [ [4,4,5,6,6,5],
//       [1,1,2,3,3,0],
//       [1,1,2,3,3,2],
//       [4,4,5,6,6,5],
//       [7,7,8,9,9,8],
//       [7,7,8,9,9,8] ]
// if pad_mode == PAD_EDGE:
//   tensor_o ==>
//     [ [1,1,2,3,3,3],
//       [1,1,2,3,3,3],
//       [1,1,2,3,3,3],
//       [4,4,5,6,6,6],
//       [7,7,8,9,9,9],
//       [7,7,8,9,9,9] ]
  • BM1682:数据类型能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。

  • BM1686(TODO):数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。

该操作当前属于 受限本地操作 。当前padding的前4个值等于0时,该操作才能做本地操作。

pad_v2

边缘补充数据,功能与pad相同。 不同的是padding以Tensor的形式存在,padding的shape要求是[dim * 2], 其中dim是tensor_i的维度数量。

该操作的目的是让padding能在运行时改变。

void pad_v2(
    const Tensor& tensor_i,            // [in]
    const Tensor& paddings,            // [in]
    Tensor& tensor_o,                  // [out]
    const Scalar& pad_val,             // [in]
    PadType pad_mode = PAD_CONSTANT);  // [in]
  • BM1682:数据类型能是FLOAT32。paddings要求是INT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。paddings要求是INT32。

该操作当前属于 全局操作

space_to_batch

按照block_size的大小,将h,w维度的数据重新排列到batch(n)方向。

目前该操作要求tensor_i的shape是4维,按照NCHW排列。block_size要求包含2个元素,pad要求 包含4个元素。

完成操作后,tensor_o的shape为: (N*block_size[0]*block_size[1], C, (H+pad[0]+pad[1])/block_size[0], (W+pad[2]+pad[3])/block_size[1])。

void space_to_batch(
    const Tensor& tensor_i,                // [in]
    Tensor& tensor_o,                      // [out]
    const std::vector<int>& block_size,    // [in]
    const std::vector<int>& pad);          // [in]
// Examples
// tensor_i ==> [ [[[1,2],[3,4]], [[5,6], [7,8]]],
//                [[[9,10],[11,12]], [[13,14], [15,16]]] ]
// tensor_i.shape() = [2, 2, 2, 2]
// block_size = [2,2]
// pad = [0,0,1,1]
// tensor_o ==> [ [[[0,2]],[[0,6]]],
//                [[[0,10]],[[0,14]]],
//                [[[1,0]],[[5,0]]],
//                [[[9,0]],[[13,0]]],
//                [[[0,4]],[[0,8]]],
//                [[[0,12]],[[0,6]]],
//                [[[3,0]],[[7,0]]],
//                [[[11,0]],[[15,0]]],
// tensor_o.shape() = [8, 2, 1, 2]
  • BM1682:数据类型能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8。

该操作当前属于 全局操作

space_to_batch_v2(TODO)

功能同space_to_batch,不同的是block_size和pad以Tensor的形式存在, 目的是block_size和pad可在runtime时变化。

void space_to_batch_v2(
    const Tensor& tensor_i,    // [in]
    const Tensor& block_size,  // [in]
    const Tensor& pad,         // [in]
    Tensor& tensor_o);         // [out]
  • BM1682:数据类型能是FLOAT32。block_size和pad要求是INT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8。block_size和pad要求是INT32。

  • BM1686:新增FLOAT16支持,其余同BM1684。

该操作当前属于 全局操作

batch_to_space

space_to_batch的逆操作,按照block_size的大小,将batch维度的数据重新排列到h和w维度。

目前该操作要求tensor_i的shape是4维,按照NCHW排列。block_size要求包含2个元素,crop_size 要求包含4个元素。

完成操作后,tensor_o的shape为: (N/block_size[0]/block_size[1], C, H*block_size[0]-crop[0]-crop[1], W*block_size[1]-crop[2]-crop[3])。

void batch_to_space(
    const Tensor& tensor_i,             // [in]
    Tensor& tensor_o,                   // [out]
    const std::vector<int>& block_size, // [in]
    const std::vector<int>& crop_size); // [in]
// Examples
// tensor_i ==> [ [[[0,2]],[[0,6]]],
//                [[[0,10]],[[0,14]]],
//                [[[1,0]],[[5,0]]],
//                [[[9,0]],[[13,0]]],
//                [[[0,4]],[[0,8]]],
//                [[[0,12]],[[0,6]]],
//                [[[3,0]],[[7,0]]],
//                [[[11,0]],[[15,0]]],
// tensor_i.shape() = [8, 2, 1, 2]
// block_size = [2,2]
// crop_size = [0,0,1,1]
// tensor_o ==> [ [[[1,2],[3,4]], [[5,6], [7,8]]],
//                [[[9,10],[11,12]], [[13,14], [15,16]]] ]
// tensor_o.shape() = [2, 2, 2, 2]
  • BM1682:数据类型能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8。

  • BM1686:新增FLOAT16支持,其余同BM1684。

该操作当前属于 全局操作

batch_to_space_v2(TODO)

功能同batch_to_space,不同的是block_size和crop_size以Tensor的形式存在, 目的是block_size和crop_size可在runtime时变化。

void batch_to_space_v2(
    const Tensor& tensor_i,   // [in]
    const Tensor& block_size, // [in]
    const Tensor& crop_size,  // [in]
    Tensor& tensor_o);        // [out]
  • BM1682:数据类型能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8。

该操作当前属于 全局操作

repeat

在指定的维度重复复制数据。std::vector<int>& reps指定每个维度的复制份数。 要求reps.size()与tensor_i和tensor_o的shape维度相等。

void repeat(const Tensor& tensor_i,  // [in]
          Tensor& tensor_o,          // [out]
          std::vector<int>& reps);   // [in]
  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。

功能同tile。

该操作当前属于 全局操作

Select Operator

condition_select

tensor_o = cond > 0 ? tensor_sel0 : tensor_sel1,tensor cond按元素与0比较,大于0时输出tensor_sel0对应位置元素,否则输出tensor_sel1的元素。

cond 不能为COEFF_TENSOR,tensor_sel0和tensor_sel1 可以为COEFF_TENSOR。 当tensor_sel0或tensor_sel1为COEFF_TENSOR时,它们的shape要求只有一个元素。

void condition_select(
const Tensor& tensor_cond, // [in]
const Tensor& tensor_sel0, // [in]
const Tensor& tensor_sel1, // [in]
Tensor& tensor_o)          // [out]
  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT8/UINT8。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT8/UINT8。

该操作属于 本地操作

select

select有两种method:

typedef enum {
  GREATER_THAN,
  GREATER_EQUAL,
  UNKNOWN_SELECT_OP
} SelectType;

// GREATER_THAN:
// tensor按元素比较,a大于b时输出tensor_c对应位置的元素值,否则输出tensor_d。
// tensor_o = tensor_a > tensor_b ?  tensor_c : tensor_d;

// GREATER_ EQUAL:
// tensor按元素比较,a大于等于b时输出tensor_c对应位置的元素值,否则输出tensor_d。
// tensor_o = tensor_a >= tensor_b  ?  tensor_c : tensor_d;

tensor_a和tensor_b其中之一可以为常系数,需要设置tensor type为COEFF_TENSOR。 tensor_a和tensor_b之间支持shape广播。

tensor_c和tensor_d可以为常系数,需要设置tensor type 为COEFF_TENSOR。 当tensor_c或tensor_d为COEFF_TENSOR时,它们的shape要求只有一个元素。

void select(
const Tensor& tensor_a, // [in]
const Tensor& tensor_b, // [in]
const Tensor& tensor_c, // [in]
const Tensor& tensor_d, // [in]
Tensor& tensor_o,       // [out]
SelectType select_type) // [in]

参数说明: tensor_a,tensor_b,tensor_c,tensor_d,tensor_o均是Tensor类型; select_type是SelectType类型,指定select method。

  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT8/UINT8。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT8/UINT8。

该操作属于 本地操作

masked_select

从tensor_i中抽取对应mask值为非0的数,最终将抽取的数据作为一维的tensor输出。

tensor_i与mask之间目前仅支持以下形式的shape广播:
tensor_i: [2, 5, 10, 1000]

mask : [1, 5, 10, 1000]/[1, 1, 10, 1000]/[1, 1, 1, 1000]

void masked_select(
    const Tensor& tensor_i, // [in]
    const Tensor& mask,     // [in]
    Tensor& tensor_o);      // [out]
  • BM1682:数据类型只能是FLOAT32。

  • BM1684: tensor_i/mask数据类型可以是FLOAT32/INT32,不要求数据类型一致。tensor_o与tensor_i要求数据类型一致。

  • BM1686(TODO):输入类型新增FLOAT16支持,其余同BM1684。

该操作属于 全局操作

index_select

在指定的维度上根据index抽取输入tensor的数据。

要求index只能是一维。

void index_select(
    const Tensor& tensor_i, // [in]
    int dim,                // [in]
    const Tensor& index,    // [in] only 1-d
    Tensor& tensor_o);      // [out]

/* example
   tensor_i = {{0.1427,  0.0231, -0.5414, -1.0009},
               {-0.4664,  0.2647, -0.1228, -1.1068},
               {-1.1734, -0.6571,  0.7230, -0.6004}};
   index = {0, 2}

   index_select(tensor_i, 0, index, tensor_o);
   tensor_o = {{ 0.1427,  0.0231, -0.5414, -1.0009},
               {-1.1734, -0.6571,  0.7230, -0.6004}};

   index_select(tensor_i, 1, index, tensor_o);
   tensor_o = {{ 0.1427, -0.5414},
               {-0.4664, -0.1228},
               {-1.1734,  0.7230}};
*/
  • BM1682:tensor_i/tensor_o数据类型只能是FLOAT32,index数据类型要求是INT32。

  • BM1684:tensor_i/tensor_o数据类型要求是FLOAT32,index数据类型要求是INT32。

  • BM1686(TODO):tensor_i/tensor_o数据类型要求是FLOAT32,index数据类型要求是INT32。

该操作属于 全局操作

where

抽取输入tensor data为true时对应的shape信息(n,c,h,w),输入为float32(由于芯片不支持bool数据类型,因此用float32类型来代替),输出为int32类型。

void where(const Tensor& tensor_i, // [in]
           Tensor& tensor_o);      // [out]

/* example
   tensor_i = ({0, 1, 1}, {1, 0, 0});
   tensor_o = ({0, 1}, {0, 2}, {1, 0});
*/
  • BM1682:tensor_i数据类型只能是FLOAT32,index数据类型要求是INT32。

  • BM1684:tensor_i数据类型目前只能是FLOAT32,index数据类型要求是INT32。

  • BM1686(TODO):tensor_i数据类型目前只能是FLOAT32,index数据类型要求是INT32。

该操作属于 全局操作

lut

对输入tensor进行查表,table长度为256。 tensor_i为INT8或UINT8类型。 table和tensor_o类型需要一致,可以为INT8、UINT8或者FLOAT32。

tensor_i或者table都可以设置为COEFF_TENSOR。

void lut(
const Tensor& tensor_i, // [in]
const Tensor& table,    // [in]
Tensor& tensor_o);      // [out]
  • BM1682:不支持该操作。

  • BM1684:支持。

  • BM1686(TODO):支持。

该操作属于 本地操作

Up/Down Scaling Operator

pool

对输入tensor进行池化处理。

参数说明: tensor_i,tensor_o均是Tensor类型; pool_param是PoolParam类型,指定池化相关参数。

void pool(
const Tensor& tensor_i,      // [in]
Tensor& tensor_o,            // [out]
const PoolParam& pool_param) // [in]

typedef struct {
  int stride_h;
  int stride_w;
  int pad_h = 0; // up_pad_h = pad_h, down_pad_h = pad_h + pad_h_offset
  int pad_w = 0; // left_pad_w = pad_w, right_pad_w = pad_w + pad_w_offset
  int pad_h_offset = 0;
  int pad_w_offset = 0;
  int kernel_h; // if global pooling, no need to specify kernel height and weight.
  int kernel_w;
  PoolType pooling_type = MAX;

  bool is_global_pooling = false;    // 是否将h*w个点pooling成1个点
  bool is_ceil_mode = false;         // 计算output shape时是否向上取整
  bool is_ave_count_zero_pad = true; // 做average pool时,边缘处是否考虑pad的0
  bool ensure_pool_image = false;    // 做pool时,是否要保证窗口里有image的数据
} PoolParam;

typedef enum {
  MAX, // max pooling
  AVE, // average pooling
  UNKNOWN
} PoolType;
  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT8/UINT8。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT8/UINT8。

该操作属于 本地操作

pool_int

二维池化处理。

void pool_int(
  const Tensor& tensor_i,         // [in]
  std::vector<Tensor*> tensor_o,  // [out]
  const PoolIntParam& param);     // [in]
// example:
// vector<Tensor*> vec = {&tensor_output, &tensor_mask};
// BMlang::PoolIntParam param;
// param.xxx = xxx
// pool_int(tensor_intput, vec, param);

参数说明: tensor_i是Tensor类型; tensor_o:依次压入tensor_output,tensor_mask(如果存在)的地址。

tensor_input要求是NCHW的shape和数据排列。

param:PoolIntParam类型,包含pooling相关参数,定义如下

typedef struct {
  int stride_h;           // 纵向的stride值
  int stride_w;           // 横向的stride值
  int pad_h_t = 0;        // 纵向top的padding值
  int pad_h_b = 0;        // 纵向bottom的padding值
  int pad_w_l = 0;        // 横向left的padding值
  int pad_w_r = 0;        // 横向right的padding值
  int kernel_h;           // 横向的kernel值
  int kernel_w;           // 纵向的kernel值
  bool is_avg_pooling;    // true为average pooling, false为max pooling
  int out_ceil_mode;      // 计算output shape时,0:向下取整;1:向上取整;
  // average pooling参数
  int quant_mode;         // 量化模式
  int scale;              // 量化乘子系数
  int rshift;             // 量化移位系数
} PoolIntParam;

二维池化即深度学习中普遍的二维池化计算。这里主要介绍定点下的二维池化定点计算, 该操作对应的定点二维AVERAGE池化计算式为:

for i in NCHW
  sum_value = sum(input[h, w]) for h in kernel_h, w in kernel_w
  if quant_mode == 1:
    output[i] = round(sum_value / kernel_count), half_away_from_zero
  else if quant_mode == 2:
    output[i] = round(sum_value * scale >> rshift), round_half_up

其中sum_value为kernel_h*kernel_w中有效kernel的值的和,kernel_count为kernel_h*kernel_w中有效kernel的个数。

该操作对应的定点二维MAX池化计算式为:

for i in NCHW
  max_value = max(input[h,w]) for h in kernel_h, w in kernel_w
  output[i] = max_value

其中max_value为kernel_h*kernel_w中有效kernel的值中的最大值。

  • BM1686:数据类型可以是INT8/UINT8/INT16。

该操作属于 本地操作

pool3d_int

三维池化处理。

void pool3d_int(
  const Tensor& tensor_i,         // [in]
  std::vector<Tensor*> tensor_o,  // [out]
  const Pool3DIntParam& param);   // [in]
// example:
// vector<Tensor*> vec = {&tensor_output, &tensor_mask};
// BMlang::Pool3DIntParam param;
// param.xxx = xxx
// pool3d_int(tensor_intput, vec, param);

参数说明: tensor_i是Tensor类型; tensor_o:依次压入tensor_output,tensor_mask(如果存在)的地址。

tensor_input要求是NCTHW的shape和数据排列。

param:Pool3DIntParam类型,包含pooling相关参数,定义如下

typedef struct {
  int stride_t;           // t向的stride值
  int stride_h;           // 纵向的stride值
  int stride_w;           // 横向的stride值
  int pad_t_0 = 0;        // t向top的padding值
  int pad_t_1 = 0;        // t向bottom的padding值
  int pad_h_0 = 0;        // 纵向top的padding值
  int pad_h_1 = 0;        // 纵向bottom的padding值
  int pad_w_0 = 0;        // 横向left的padding值
  int pad_w_1 = 0;        // 横向right的padding值
  int kernel_t;           // t向的kernel值
  int kernel_h;           // 横向的kernel值
  int kernel_w;           // 纵向的kernel值
  bool is_avg_pooling;    // true为average pooling, false为max pooling
  int out_ceil_mode;      // 计算output shape时,0:向下取整;1:向上取整;
  // average pooling参数
  int quant_mode;         // 量化模式
  int scale;              // 量化乘子系数
  int rshift;             // 量化移位系数
} PoolIntParam;

三维池化即深度学习中普遍的三维池化计算。这里主要介绍定点下的三维池化定点计算, 该操作对应的定点三维AVERAGE池化计算式为:

for i in NCHW
  sum_value = sum(input[t, h, w]) for t in kernel_t, h in kernel_h, w in kernel_w
  if quant_mode == 1:
    output[i] = round(sum_value / kernel_count), half_away_from_zero
  else if quant_mode == 2:
    output[i] = round(sum_value * scale >> rshift), round_half_up

其中sum_value为kernel_t*kernel_h*kernel_w中有效kernel的值的和,kernel_count为kernel_t*kernel_h*kernel_w中有效kernel的个数。

该操作对应的定点三维MAX池化计算式为:

for i in NCHW
  max_value = max(input[h,w]) for t in kernel_t, h in kernel_h, w in kernel_w
  output[i] = max_value

其中max_value为kernel_t*kernel_h*kernel_w中有效kernel的值中的最大值。

  • BM1686:数据类型可以是INT8/UINT8/INT16。

该操作属于 本地操作

upsample

在h和w维度对输入tensor数据进行scale倍重复扩展输出。

// 接口
void upsample(
    const Tensor& tensor_i, // [in]
    Tensor& tensor_o,       // [out]
    int scale);             // [in]

// example
Tensor tensor_input, tensor_output;
upsample(tensor_input, tensor_output, scale);
/*
 * int n = 1, c = 1, h = 2, w = 3;
 * int scale = 2;
 * float input_data[6] = {2, 3, 4,
 *                        7, 8, 9};
 * output_data = {2, 2, 3, 3, 4, 4,
 *                2, 2, 3, 3, 4, 4,
 *                7, 7, 8, 8, 9, 9,
 *                7, 7, 8, 8, 9, 9};
 */
  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT8/UINT8。

  • BM1686:数据类型可以是FLOAT32/INT8/UINT8。

该操作属于 本地操作

reduce

依据axis_list,对输入的tensor做reduce操作。 reduce的算子类型如下:

void reduce(
const Tensor& tensor_i,    // [in]
Tensor& tensor_o,          // [out]
ReduceParam reduce_param); // [in]

//reduce 参数如下:
typedef struct ReduceOp {
  ReduceOp() {
    method     = REDUCE_MEAN;
    keep_dims  = true;
  }
  ReduceMethodType method;
  int axis_list[MAX_DIMS];
  int axis_num;
  bool keep_dims;
} ReduceParam;
/*
method指定reduce算子类型;
axis_num指定reduce轴的数目;
axis_list指定需要redece的轴:
*/
typedef enum {
  REDUCE_MEAN = 0,
  REDUCE_SUM = 1,
  REDUCE_MAX = 2,
  REDUCE_MIN = 3,
  REDUCE_PROD= 4
} ReduceMethodType;
// 对被reduce的所有轴求平均,求和,求最大值,求最小值,求内积。

参数说明: tensor_i,tensor_o均是Tensor类型; reduce_param是ReduceParam类型,指定reduce相关参数。

//For example:
tensor_i_shape = {10, 20, 30, 40}
axis_num = 2
axis_list[0] = 1
axis_list[1] = 3
tensor_o_shape = {10, 1, 30, 1}
  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT8/UINT8。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT8/UINT8。

该操作目前属于 受限本地操作 ,在数据类型是FLOAT32时才有可能作为本地操作。

hw_avg

HW维平均算子。

void hw_avg(
  const Tensor &tensor_i,   // [in]
  const Tensor &tensor_hw,  // [in]
  Tensor &tensor_o,         // [out]
  int mode);                // [in]
// example:
// hw_avg(tensor_intput, tensor_hw, tensor_output, mode);

参数说明: tensor_i, tensor_hw, tensor_o是Tensor类型;mode取值范围为(0,2)

tensor_i要求是NCHW的shape和数据排列。 tensor_hw要求shape为[2],保存数据为tensor_i的H、W。

当mode==0时:

该操作对应的计算式为:

hw = input_hw[0] * input_hw[1]
output = float(input) / hw
  • BM1686:input数据类型可以是INT32/UINT32, output数据类型可以是FLOAT32

当mode==1时:

该操作对应的计算式为:

hw = input_hw[0] * input_hw[1]
output = int(round(float(input) / hw)),       其中round为half_up
  • BM1686:input数据类型可以是INT32/UINT32, output数据类型与input数据类型一致。

当mode==2时:

该操作对应的计算式为:

hw = input_hw[0] * input_hw[1]
output = int(round(float(input) / hw)),       其中round为half_away_from_zero
  • BM1686:input数据类型可以是INT32/UINT32, output数据类型与input数据类型一致。

该操作属于 本地操作

hw_mul

HW维乘积算子。

void hw_mul(
  const Tensor &tensor_i,   // [in]
  const Scalar &scale,      // [in]
  Tensor &tensor_o);        // [out]
// example:
// hw_mul(tensor_intput, scale, tensor_output);

参数说明: tensor_i, tensor_o是Tensor类型;scale是Scalar类型;

tensor_i要求shape为[2],保存数据为H、W。

该操作对应的计算式为:

output = input_i[0] * input_i[1] *scale
  • BM1686:input数据类型可以是INT32/UINT32, output数据类型可以是FLOAT32

该操作属于 本地操作

Sort Operator

arg

对输入tensor的指定的axis求最大或最小值,输出对应的index,并将该axis的dim设置为1。 Arg参数结构体如下:

typedef struct {
  int axis;
  int method;  // 0->max, 1->min
} ArgParam;

void arg(
const Tensor& tensor_i, // [in]
Tensor& tensor_o,       // [out]
ArgParam arg_param);    // [in]

参数说明: tensor_i,tensor_o均是Tensor类型; arg_param是ArgParam类型,指定处理的轴和操作(max or min)。

  • BM1682:数据类型是FLOAT32。

  • BM1684:tensor_i数据类型可以是FLOAT32/INT8/UINT8。tensor_o数据类型可以是INT32/FLOAT32。tensor_i数据类型为INT8/UINT8时,tensor_o只能为INT32。

  • BM1686:同BM1686。

该操作属于 受限本地操作 ,当axis > 1时才能做本地操作。

topk

计算指定维度(axis)上输入tensor的前k个最大/最小值,输出对应的数值(value)和索引(index)tensor。

// 接口
void topk(
    const Tensor& tensor_i,  // [in]
    Tensor& tensor_val,      // [out]
    Tensor& tensor_idx,      // [out]
    const TopkParam& param); // [in]

// TopkParam definition
typedef struct TopkParam{
  TopkParam(int k = 1, int axis = 0, bool descending = true) {
    this->k    = k;
    this->axis = axis;
    this->descending = descending;
  }

  int k;
  int axis;
  bool descending;
} TopkParam;

// example
Tensor tensor_input, tensor_val, tensor_idx;
TopkParam param(k, axis, descending);
topk(tensor_input, tensor_val, tensor_idx, param);
说明:
  1. 可以根据descending来设置输出按照升序或降序排列,descending=true降序排列,descending=false升序排列。

  2. tensor_input, tensor_val, tensor_idx依次为输入tensor、输出数值(value)tensor和对应的索引值(index)tensor。

  3. topk是不稳定排序。

  • BM1682:数据类型是FLOAT32。

  • BM1684:tensor_i/tensor_val数据类型要求是FLOAT32,tensor_idx数据类型要求是INT32。

  • BM1686:同BM1686。

该操作属于 全局操作

sort

在指定的维度上对tensor_i数据进行排序。输出包括数据排序后的输出tensor_o, 以及输出tensor_o中各个数据在tensor_i中第dim维度的索引。

如果dim没有赋值,则选择最后一维的输入数据进行排序。

参数stable是false表示对于相同大小的数据,不需要每次都获取到相同的排序结果。 比如(3,3,3)排序,index_o可以是(0,1,2),也可以是(1,0,2)。 参数stable是true则表示每次排序都要求获得相同的排序结果。stable是false的性能 要优于stable是true的性能。BM1684仅支持stable为false。

参数descending是true表示使用升序排序,false则是降序排序。

void sort(
    const Tensor& tensor_i,   // [in]
    Tensor& index_o,          // [out]
    Tensor& tensor_o,         // [out]
    int dim = -1,             // [in]
    bool stable = false,      // [in]
    bool descending = false); // [in]
  • BM1682:数据类型是FLOAT32。

  • BM1684:tensor_i/tensor_o数据类型可以是FLOAT32。index_o数据类型可以是INT32。

  • BM1686:同BM1686。

该操作属于 全局操作

argsort

在指定的维度上对tensor_i数据进行排序。输出为排序后各个数据在tensor_i中第dim维度的索引。

如果dim没有赋值,则选择最后一维的输入数据进行排序。

参数stable是false表示对于相同大小的数据,不需要每次都获取到相同的排序结果。 比如(3,3,3)排序,index_o可以是(0,1,2),也可以是(1,0,2)。 参数stable是true则表示每次排序都要求获得相同的排序结果。stable是false的性能 要优于stable是true的性能。BM1684仅支持stable为false。

参数descending是true表示使用升序排序,false则是降序排序。

void argsort(
    const Tensor& tensor_i,  // [in]
    Tensor& index_o,         // [out]
    int dim = -1,            // [in]
    bool stable = false,     // [in]
    bool descending = false);// [in]
  • BM1682:数据类型是FLOAT32。

  • BM1684:tensor_i数据类型可以是FLOAT32。index_o数据类型可以是INT32/FLOAT32。

  • BM1686:同BM1686。

该操作属于 全局操作

Shape About Operator

squeeze

降维操作,去掉输入tensor shape指定的某个1维的轴,如果没有指定轴(axis)则去除所有是1维的轴

// 接口
void squeeze(
    const Tensor& tensor_i,   // [in]
    Tensor& tensor_o,         // [out]
    vector<int> axis = {} );  // [in]

// example
Tensor tensor_input, tensor_output;
squeeze(tensor_input, tensor_output, axis);
/*
 * input_shape[] = {1, 3, 8, 1};
 * if: axis = {3},  output_shape[] = {1, 3, 8}
 * if: axis = {},   output_sahpe[] = {3, 8}
 * if: axis = {-1}, output_shape[] = {1, 3, 8}
 */
  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求一致。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求一致。

该操作当前属于 全局操作

expand_dims

增维操作。在axis指定的位置增加ndims个1。

void expand_dims(
    const Tensor& tensor_i,        // [in]
    Tensor& tensor_o,              // [out]
    const ExpandDimsParam& param); // [in]

typedef struct ExpandDimsParam {
  ExpandDimsParam() {
    ndims = 1;
  }
  int axis;
  int ndims;
} ExpandDimsParam;
  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求一致。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求一致。

该操作当前属于 全局操作

reshape

对输入tensor做reshape的操作。

void reshape (
const Tensor& tensor_i,    // [in]
Tensor& tensor_o,          // [out]
vector<int> reshape_param) // [in]

参数说明: tensor_i和tensor_o均是Tensor类型; reshape_param是vector<int>类型,指定reshape参数: 0表示该轴的shape值与输入相同; -1表示该轴的shape值需要通过推导得出,且只能设置一个轴; 其他正数值表示设置该轴的shape值。

Example:

tensor_i_shape = (10, 20, 30, 40)
reshape_param = (0, 10, -1, 10)
tensor_o_shape = (10, 10, 240, 10)
  • BM1682:数据类型可以是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求一致。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。输入输出数据类型要求一致。

该操作当前属于 全局操作

reshape_v2

对输入tensor做reshape的操作。

void reshape (
const Tensor& tensor_i,    // [in]
const Tensor& shape_info,  // [in]
Tensor& tensor_o)          // [out]

参数说明: 功能与reshape相同,不同的是reshape的参数(shape_info)是以Tensor的形式存在。该目的是让Tensor的shape信息在运行时能够改变。 shape_info存储了目的tensor的shape信息,它只能是一维的,其大小表示输出shape维度,数值依次表示该轴的尺寸。 0表示该轴的shape值与输入相同;-1表示该轴的shape值需要通过推导得出,且只能设置一个轴;其他正数值表示设置该轴的shape值。

Example:

tensor_i.shape = (10, 20, 30, 40)
shape_info.shape = (4), shape_info.data = [0, 10, -1, 10]
tensor_o.shape = (10, 10, 240, 10)
  • BM1682:tensor_i的数据类型只能是FLOAT32,shape_info的数据类型需要是INT32。

  • BM1684:数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16,输入输出数据类型要求一致。shape_info的数据类型需要是INT32。

  • BM1686:数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16,输入输出数据类型要求一致。shape_info的数据类型需要是INT32。

该操作当前属于 全局操作

shape_fetch

对输入tensor取指定轴(axis)之间的shape信息,输出tensor为int32类型。

void shape_fetch(
    const Tensor& tensor_i,        // [in]
    Tensor& tensor_o,              // [out]
    const ShapeFetchParam& param); // [in]

ShapeFetchParam是一个结构体,定义如下:
typedef struct ShapeFetchParam {
  ShapeFetchParam() {
    begin_axis = 0;
    end_axis = 1;
    step = 1;
  }
  int begin_axis;
  int end_axis;
  int step;
} ShapeFetchParam;
begin_axis和end_axis指定了需要取input tensor shape的范围,step代表步长。
  • BM1682:tensor_i数据类型是FLOAT32,tensor_o数据类型要求是INT32。

  • BM1684:tensor_i数据类型可以是FLOAT32/INT32/INT8/UINT8/INT16/UINT16。tensor_o数据类型要求是INT32。

  • BM1686:tensor_i数据类型可以是FLOAT32/FLOAT16/INT32/INT8/UINT8/INT16/UINT16。tensor_o数据类型要求是INT32。

该操作当前属于 全局操作

Quant Operator

requant_fp32_to_int

对输入tensor进行量化处理。

void requant_fp32_to_int(
  const Tensor& tensor_i,                 // [in]
  Tensor& tensor_o,                       // [out]
  const RequantFp32toIntParam& param);   // [in]

参数说明: tensor_i,tensor_o均是Tensor类型; param是RequantFp32toIntParam类型,指定量化相关参数,定义如下。

typedef struct RequantFp32toIntParam {
  bool is_scale_pc;                 // scale是否为per channel
  float scale_val;                  // scale if is_scale_pc == false
  std::vector<float> scale_vec;     // scale if is_scale_pc == true
  bool is_offset_pc;                // offset是否为per channel
  int offset_val;                   // offset if is_offset_pc == false && mode == 0
  std::vector<int> offset_vec;      // offset if is_offset_pc == true && mode == 0
  float offset_fp_val;              // offset if is_offset_pc == false && mode == 1
  std::vector<float> offset_fp_vec; // offset if is_offset_pc == true && mode == 1
  int mode;                         // quant mode: (0, 1)
} RequantFp32toIntParam, DequantInttoFp32Param;

当mode==0时:

该操作对应的计算式为:

output = saturate(int(round(input * scale)) + offset),         其中saturate为饱和到output的数据类型
  • BM1686:input数据类型可以是FLOAT32, output数据类型可以是INT16/UINT16/INT8/UINT8

当mode==1时(TODO):

该操作对应的计算式为:

output = saturate(int(round(float(input) * scale + offset))),  其中saturate为饱和到output的数据类型
  • BM1686:input数据类型可以是INT32/INT16/UINT16, output数据类型可以是INT16/UINT16/INT8/UINT8

该操作属于 本地操作

requant_int32

对输入tensor进行量化处理。

void requant_int32(
  const Tensor& tensor_i,         // [in]
  Tensor& tensor_o,               // [out]
  const RequantInt32Param& param, // [in]
  int mode);                      // [in]

参数说明: tensor_i,tensor_o均是Tensor类型;mode取值范围为(0,2); param是RequantInt32Param类型,指定量化相关参数,定义如下。

typedef struct RequantInt32Param {
  bool is_mul_shift_pc;             // multiplier和shift是否为per channel
  int multiplier_val;               // multiplier if is_mul_shift_pc == false
  char scale_val;                   // shift if is_mul_shift_pc == false
  std::vector<int> multiplier_vec;  // multiplier if is_mul_shift_pc == true
  std::vector<cahr> scale_vec;      // shift if is_mul_shift_pc == true
  bool is_offset_pc;                // offset是否为per channel
  int offset_val;                   // offset if is_offset_pc == false
  std::vector<int> offset_vec;      // offset if is_offset_pc == true
} RequantInt32Param;

当mode==0时:

该操作对应的计算式为:

output = shift > 0 ? (input << shift) : input
output = saturate((output * multiplier) >> 31),     其中 >> 为round_half_up, saturate饱和到INT32
output = shift < 0 ? (output >> -shift) : output,   其中 >> 为round_half_away_from_zero
output = saturate(output + offset),                 其中saturate饱和到output数据类型
  • BM1686:input数据类型可以是INT32/INT16/UINT16/INT8/UINT8, output数据类型可以是INT32/INT16/INT8

当mode==1时:

该操作对应的计算式为:

output = saturate((input * multiplier) >> 31),     其中 >> 为round_half_up, saturate饱和到INT32
output = saturate(output >> -shift + offset),      其中 >> 为round_half_away_from_zero, saturate饱和到output数据类型
  • BM1686:input数据类型可以是INT32/INT16/UINT16/INT8/UINT8, output数据类型可以是INT32/INT16/INT8

当mode==2时:

该操作对应的计算式为:

output = input * multiplier
output = shift > 0 ? (output << shift) : (output >> -shift),    其中 >> 为round_half_up
output = saturate(output + offset),                             其中 saturate饱和到output数据类型
  • BM1686:input数据类型可以是INT32/INT16/UINT16, output数据类型可以是INT16/UINT16/INT8/UINT8

该操作属于 本地操作

dequant_int_to_fp32

对输入tensor进行反量化处理。

void dequant_int_to_fp32(
  const Tensor& tensor_i,                 // [in]
  Tensor& tensor_o,                       // [out]
  const DequantInttoFp32Param& param);   // [in]

参数说明: tensor_i,tensor_o均是Tensor类型; param是DequantInttoFp32Param类型,指定量化相关参数,详细请见操作requant_fp32_to_int

该操作对应的计算式为:

output = (input - offset) * scale
  • BM1686:input数据类型可以是INT16/UINT16/INT8/UINT8, output数据类型可以是FLOAT32

该操作属于 本地操作

Data Genenrate Operator

constdata

将Tensor变成一个常量Tensor。在使用该操作之前,要求该tensor只是被声明过, 且用set_data接口赋予过该tensor数据,而且要求tensor没有被其他操作使用过。

该操作后,tensor可以作为其它操作的输入,但不能作为其它操作的输出。

该操作用于对固定数据进行计算。在TPU运行时,这些固定数据会和系数一样, 在运行前就保存在DDR空间里。

void constdata(
const Tensor& tensor);  // [out]

参数说明: tensor是tensor类型。

  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16/INT32。

  • BM1686:数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16/INT32。

该操作虽然属于 全局操作 ,但是在TPU运行过程中,没有时间开销。

number_like

构建和tensor_like一样shape,数据全是scalar_i。 tensor_o和scalar_i的数据类型要求一致。

void number_like(
    const Tensor& tensor_like, // [in]
    const Scalar& scalar_i,    // [in]
    Tensor& tensor_o);         // [out]
  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16/INT32。

  • BM1686:数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16/INT32。

该操作当前属于 全局操作

sequence_gen

生成shape_tensor指定shape的序列数,序列数从0开始。

shape_tensor要求是1维的。

void sequence_gen(
    const Tensor& shape_tensor, // [in]
    Tensor& tensor_o);          // [out]
// Example
// shape_tensor = [2, 3, 4]
// tensor_o =
// [[[0, 1, 2, 3],
//   [4, 5, 6, 7],
//   [8, 9, 10, 11]]
//  [[12, 13, 14, 15],
//   [16, 17, 18, 19],
//   [20, 21, 22, 23]]]
  • BM1682:不支持。

  • BM1684:shape_tensor数据类型只能是INT32,tensor_o数据类型可以是FLOAT32/INT32。

  • BM1686(TODO):shape_tensor数据类型只能是INT32,tensor_o数据类型可以是FLOAT32/INT32。

该操作当前属于 全局操作

Vision Operator

nms

非极大值抑制算法(Non-maximum suppression, NMS)。

按照参数scores的降序贪婪的选择边界框的子集。 删除掉那些与之前的选择的边框具有很高的IOU的边框。 边框是以[y1,x1,y2,x2],(y1,x1)和(y2,x2)是边框的对角坐标,当然也可以提供被归一化的坐标。 返回的是被选中的那些留下来的边框在参数boxes里面的下标位置。

void nms(
    const Tensor& boxes,  // [in] Shape [N, 4]
    const Tensor& scores, // [in] Shape [N]
    const Scalar& threshold, // [in]
    Tensor& tensor_o,     // [out] index of selected box
    bool stable = false); // [in] output index with same score keep original order
  • boxes要求是2维FLOAT32的张量,shape要求是[num_boxes, 4]。

  • scores要求1维FLOAT32的张量,shape要求是[num_boxes]。

  • threshold要求是一个浮点值,IOU阙值展示的是否与选中的那个边框具有较大的重叠度。

  • tensor_o要求是一个1维INT32的张量,表示被选box的索引。

该操作属于 全局操作

nms_v2(TODO)

非极大值抑制算法(Non-maximum suppression, NMS)。

void nms(
    const Tensor& boxes,  // [in] Shape [N, 4]
    const Tensor& scores, // [in] Shape [N]
    const Scalar& iou_threshold,   // [in]
    const Scalar& score_threshold, // [in]
    unsigned int max_output_size,  // [in]
    Tensor& tensor_o,     // [out] index of selected box
    bool stable = false); // [in] output index with same score keep original order
  • boxes要求是2维FLOAT32的张量,shape要求是[num_boxes, 4]。

  • scores要求1维FLOAT32的张量,shape要求是[num_boxes]。

  • iou_threshold要求是一个浮点值,IOU阙值展示的是否与选中的那个边框具有较大的重叠度。

  • score_threshold要求是一个浮点数,用来决定过滤低分值的边框。

  • max_output_size代表最多可以利用NMS选中多少个边框。

  • tensor_o要求是一个1维INT32的张量,表示被选box的索引。

该操作属于 全局操作

interpolate

插值算法。

void interpolate(
    const Tensor& tensor_i,           // [in]
    Tensor& tensor_o,                 // [out]
    std::vector<int> size,            // [in]
    std::vector<float> scale_factor,  // [in]
    const InterpolateParam& param)    // [in]

typedef struct InterpolateParam {
    PlatForm platform;
    InterpolateMode method;
    bool align_corners;
    bool half_pixel_centers;
} InterpolateParam;

typedef enum {
    CAFFE      = 0,
    TENSORFLOW = 1,
    PYTORCH    = 2,
    OPENCV     = 3,
} PlatForm;

typedef enum {
    NEAREST = 0,
    BILINEAR = 1,
} InterpolateMode;

参数说明:

  • tensor_i,tensor_o:均是Tensor类型,分别对应输入输出tensor,要求是NCHW的4维tensor;

  • size:vector<int>类型;如果不为空,要求该vector长度为2,表示tensor_o的shape后两维;如果为空,则tensor_o的shape后两维由tensor_i的shape和scale_factor共同确定;

  • scale_factor:vector<int>类型;在size为空的情况下,此时该vector长度为2,tensor_o的shape后两维由tensor_i的shape和scale_factor共同确定;

  • param:InterpolateParam类型,platform参数当前可配OPENCV和TENSORFLOW,method表示插值方法,在platform取OPENCV的情况下限定BILINEAR;align_corners是bool型,如果为True,则将输入和输出张量的4个角落像素的中心对齐,并保留角点像素的值;half_pixel_centers是bool型,如果为True,则会在计算缩放尺寸时先给像素坐标加上0.5之后再进行运算。

该操作属于 全局操作

  • BM1686:tensor_i和tensor_o类型相同,可以为FLOAT32/FLOAT16型。

Custom Operator

customed_ops

用户自定义算子,和user_cpu layer结合使用。

void customed_ops(const std::vector<Tensor*> tensor_i, // [in]
                  std::vector<Tensor*> tensor_o,       // [out]
                  void* param,                         // [in]
                  int param_size);                     // [in]

// param是在user_bmcpu_common.h文件中的user_cpu_param_t结构体定义的参数
// 具体如下:
typedef struct user_cpu_param {
  int op_type;   /* USER_CPU_LAYER_TYPE_T */
  union {
    user_cpu_exp_param_t exp;
  }u;
} user_cpu_param_t;
// param_size则是sizeof(user_cpu_param_t)
  • BM1682:数据类型只能是FLOAT32。

  • BM1684:数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16/INT32。

  • BM1686(TODO):数据类型可以是FLOAT32/INT8/UINT8/INT16/UINT16/INT32。

该操作属于 全局操作

Shift Operator

lshift

对输入tensor在指定维度上进行整体左移,左移后超过的部分丢弃,右边补0。

参数说明:

tensor_i,tensor_o:均是Tensor类型,分别对应输入输出tensor;

num:int型,表示位移的位数;

axis:int型,表示进行位移运算的维度,目前默认且仅支持axis==1。

void lshift(
const Tensor& tensor_i,      // [in]
Tensor& tensor_o,            // [out]
int num,                     // [in]
int axis = 1)                // [in]

用法示例:

给定参数num=2,axis=1,输入tensor_i的shape为[2,3,2,3],值如下:

[[[[-2.8400023  -3.0926123   0.8007528 ]
   [-4.425494    3.1243792  -1.8667252 ]]

  [[ 2.6016338  -4.5330453   3.3297958 ]
   [ 0.4723102  -3.9454443   2.9412758 ]]

  [[ 1.639079    0.9966435  -4.565726  ]
   [-4.4187098  -4.164262   -2.1304157 ]]]

 [[[-1.0305262   0.29448375  2.296344  ]
   [ 4.6640167   4.8765826   4.213974  ]]

  [[-0.5052162   2.5084617  -1.0592794 ]
   [ 3.5504768  -1.8535931   2.8203747 ]]

  [[ 2.269553    1.8395575  -0.29201797]
   [ 3.826423    1.2334696  -3.597132  ]]]]

则输出tensor_o为:

[[[[ 1.639079    0.9966435  -4.565726  ]
   [-4.4187098  -4.164262   -2.1304157 ]]

  [[ 0.          0.          0.        ]
   [ 0.          0.          0.        ]]

  [[ 0.          0.          0.        ]
   [ 0.          0.          0.        ]]]

 [[[ 2.269553    1.8395575  -0.29201797]
   [ 3.826423    1.2334696  -3.597132  ]]

  [[ 0.          0.          0.        ]
   [ 0.          0.          0.        ]]

  [[ 0.          0.          0.        ]
   [ 0.          0.          0.        ]]]]
  • BM1684:数据类型可以是FLOAT32/INT8/UINT8。

  • BM1686(TODO):数据类型可以是FLOAT32/INT8/UINT8。

该操作属于 本地操作

rshift

对输入tensor在指定维度上进行整体右移,右移后超过的部分丢弃,左边补0。

参数说明:

tensor_i,tensor_o:均是Tensor类型,分别对应输入输出tensor;

num:int型,表示位移的位数;

axis:int型,表示进行位移运算的维度,目前默认且仅支持axis==1。

void rshift(
const Tensor& tensor_i,      // [in]
Tensor& tensor_o,            // [out]
int num,                     // [in]
int axis = 1)                // [in]

用法示例:

给定参数num=2,axis=1,输入tensor_i的shape为[2,3,2,3],值如下:

[[[[-2.9186313  -0.24356237  1.2540053 ]
   [-4.8955007  -4.2767916   2.6306164 ]]

  [[ 0.4980812  -3.5192926  -3.6721635 ]
   [-2.4307063  -4.778728   -1.1970373 ]]

  [[-0.8761543  -3.8434331   4.1573873 ]
   [-1.0016538  -2.423648    4.227273  ]]]

 [[[-0.6212847  -3.8671243  -2.8993464 ]
   [ 3.8161297  -1.1340241   3.7225533 ]]

  [[ 1.4913342  -2.3859684  -4.793918  ]
   [-3.1233387  -3.7450933   0.23620334]]

  [[ 0.7224776  -0.17362665 -1.212464  ]
   [-1.4175521   2.4217072   1.9185396 ]]]]

则输出tensor_o为:

[[[[ 0.          0.          0.        ]
   [ 0.          0.          0.        ]]

  [[ 0.          0.          0.        ]
   [ 0.          0.          0.        ]]

  [[-2.9186313  -0.24356237  1.2540053 ]
   [-4.8955007  -4.2767916   2.6306164 ]]]

 [[[ 0.          0.          0.        ]
   [ 0.          0.          0.        ]]

  [[ 0.          0.          0.        ]
   [ 0.          0.          0.        ]]

  [[-0.6212847  -3.8671243  -2.8993464 ]
   [ 3.8161297  -1.1340241   3.7225533 ]]]]
  • BM1684:数据类型可以是FLOAT32/INT8/UINT8。

  • BM1686(TODO):数据类型可以是FLOAT32/INT8/UINT8。

该操作属于 本地操作

clshift

对输入tensor在指定维度上进行整体循环左移,左移后超过的部分会依次补到右边。

参数说明:

tensor_i,tensor_o:均是Tensor类型,分别对应输入输出tensor;

num:int型,表示位移的位数;

axis:int型,表示进行位移运算的维度,目前默认且仅支持axis==1。

void clshift(
const Tensor& tensor_i,      // [in]
Tensor& tensor_o,            // [out]
int num,                     // [in]
int axis = 1)                // [in]

用法示例:

给定参数num=2,axis=1,输入tensor_i的shape为[2,3,2,3],值如下:

[[[[-1.4399457   1.3908076   4.605652  ]
   [ 4.1669855  -4.5294094  -2.269803  ]]

  [[-2.791052    0.24600852 -0.31004244]
   [-2.2961752  -3.7278128   3.9250836 ]]

  [[ 3.9799519   0.10813443  4.395123  ]
   [-4.0098004  -4.0820565   3.7188065 ]]]

 [[[-0.9577033  -0.9451188   4.2339325 ]
   [-3.3796852   2.1229327  -2.6846838 ]]

  [[ 4.5255566   2.3164961   4.5181227 ]
   [-0.37370363 -4.586216    3.908726  ]]

  [[-0.17074646  1.3929528  -4.4028926 ]
   [ 0.6453225  -4.983816    2.3636074 ]]]]

则输出tensor_o为:

[[[[ 3.9799519   0.10813443  4.395123  ]
   [-4.0098004  -4.0820565   3.7188065 ]]

  [[-1.4399457   1.3908076   4.605652  ]
   [ 4.1669855  -4.5294094  -2.269803  ]]

  [[-2.791052    0.24600852 -0.31004244]
   [-2.2961752  -3.7278128   3.9250836 ]]]

 [[[-0.17074646  1.3929528  -4.4028926 ]
   [ 0.6453225  -4.983816    2.3636074 ]]

  [[-0.9577033  -0.9451188   4.2339325 ]
   [-3.3796852   2.1229327  -2.6846838 ]]

  [[ 4.5255566   2.3164961   4.5181227 ]
   [-0.37370363 -4.586216    3.908726  ]]]]
  • BM1684:数据类型可以是FLOAT32/INT8/UINT8。

  • BM1686(TODO):数据类型可以是FLOAT32/INT8/UINT8。

该操作属于 本地操作

crshift

对输入tensor在指定维度上进行整体循环右移,右移后超过的部分会依次补到左边。

参数说明:

tensor_i,tensor_o:均是Tensor类型,分别对应输入输出tensor;

num:int型,表示位移的位数;

axis:int型,表示进行位移运算的维度,目前默认且仅支持axis==1。

void crshift(
const Tensor& tensor_i,      // [in]
Tensor& tensor_o,            // [out]
int num,                     // [in]
int axis = 1)                // [in]

用法示例:

给定参数num=2,axis=1,输入tensor_i的shape为[2,3,2,3],值如下:

[[[[ 0.19381493 -1.3157253  -0.7534135 ]
   [-3.4642425   2.8708158  -0.02517204]]

  [[-0.2214326   1.6934406  -4.934953  ]
   [-2.593857    0.6439782  -4.3378534 ]]

  [[-4.404575   -4.548932   -3.44572   ]
   [-1.871432   -3.1994293   3.7281854 ]]]

 [[[ 4.6499877  -4.407126   -1.496588  ]
   [-3.5752625   4.5654907  -3.6933322 ]]

  [[-4.4067974   2.0822976  -0.22787085]
   [-1.5884587   0.04195577 -2.4798908 ]]

  [[-3.8945446  -0.90788925 -3.20682   ]
   [ 2.5059738   4.5769157  -2.5235941 ]]]]

则输出tensor_o为:

[[[[-0.2214326   1.6934406  -4.934953  ]
   [-2.593857    0.6439782  -4.3378534 ]]

  [[-4.404575   -4.548932   -3.44572   ]
   [-1.871432   -3.1994293   3.7281854 ]]

  [[ 0.19381493 -1.3157253  -0.7534135 ]
   [-3.4642425   2.8708158  -0.02517204]]]


 [[[-4.4067974   2.0822976  -0.22787085]
   [-1.5884587   0.04195577 -2.4798908 ]]

  [[-3.8945446  -0.90788925 -3.20682   ]
   [ 2.5059738   4.5769157  -2.5235941 ]]

  [[ 4.6499877  -4.407126   -1.496588  ]
   [-3.5752625   4.5654907  -3.6933322 ]]]]
  • BM1684:数据类型可以是FLOAT32/INT8/UINT8。

  • BM1686(TODO):数据类型可以是FLOAT32/INT8/UINT8。

该操作属于 本地操作

arithmetic_shift(TODO)

对输入tensor进行算术位移。

参数说明:

tensor_i,tensor_o:均是Tensor类型,分别对应输入输出tensor;

shift:int型,表示位移的位数,值为正时表示左移,值为负表示右移;

rounding_mode:RoundingMode型,表示取整方式。

void arithmetic_shift(
const Tensor& tensor_i,      // [in]
int shift,                   // [in]
RoundingMode rounding_mode,  // [in]
Tensor& tensor_o)            // [out]

typedef enum {
     ROUNDING_HALF_TO_EVEN        = 0,
     ROUNDING_HALF_AWAY_FROM_ZERO = 1,
     ROUNDING_TOWARDS_ZERO        = 2,
     ROUNDING_DOWN                = 3,   /* FLOOR */
     ROUNDING_UP                  = 4,   /* CEIL */
     ROUNDING_HALF_UP             = 5,
     ROUNDING_HALF_DOWN           = 6,
     ROUNDING_UNKNOWN             = -1
 } RoundingMode;
  • BM1686:tensor_i/tensor_o数据类型可以是INT32/UINT32/INT16/UINT16/INT8/UINT8,且tensor_i和tensor_o必须同时为无符号型或有符号型。

该操作属于 本地操作

arithmetic_pc_shift(TODO)

对输入tensor进行算术位移,位移量为一个tensor。

参数说明:

tensor_i,tensor_o:均是Tensor类型,分别对应输入输出tensor;

tensor_shift:Tensor类型,表示位移的位数,每个元素值为正表示左移,值为负表示右移;shape为[tensor_i.shape(0)];

rounding_mode:RoundingMode型,表示取整方式。

void arithmetic_pc_shift(
const Tensor& tensor_i,      // [in]
const Tensor &tensor_shift,  // [in]
RoundingMode rounding_mode,  // [in]
Tensor& tensor_o)            // [out]

typedef enum {
     ROUNDING_HALF_TO_EVEN        = 0,
     ROUNDING_HALF_AWAY_FROM_ZERO = 1,
     ROUNDING_TOWARDS_ZERO        = 2,
     ROUNDING_DOWN                = 3,   /* FLOOR */
     ROUNDING_UP                  = 4,   /* CEIL */
     ROUNDING_HALF_UP             = 5,
     ROUNDING_HALF_DOWN           = 6,
     ROUNDING_UNKNOWN             = -1
 } RoundingMode;
  • BM1686:tensor_i/tensor_o数据类型可以是INT32/UINT32/INT16/UINT16/INT8/UINT8,且tensor_i和tensor_o必须同时为无符号型或有符号型。tensor_shift的数据类型可以是INT32/INT16/INT8;tensor_shift的数据类型大小不能超过tensor_i的数据类型大小。

该操作属于 本地操作

logical_shift(TODO)

对输入tensor进行逻辑位移。

参数说明:

tensor_i,tensor_o:均是Tensor类型,分别对应输入输出tensor;

shift:int型,表示位移的位数,值为正时表示左移,值为负表示右移;

rounding_mode:RoundingMode型,表示取整方式。

void logical_shift(
const Tensor& tensor_i,      // [in]
int shift,                   // [in]
RoundingMode rounding_mode,  // [in]
Tensor& tensor_o)            // [out]

typedef enum {
     ROUNDING_HALF_TO_EVEN        = 0,
     ROUNDING_HALF_AWAY_FROM_ZERO = 1,
     ROUNDING_TOWARDS_ZERO        = 2,
     ROUNDING_DOWN                = 3,   /* FLOOR */
     ROUNDING_UP                  = 4,   /* CEIL */
     ROUNDING_HALF_UP             = 5,
     ROUNDING_HALF_DOWN           = 6,
     ROUNDING_UNKNOWN             = -1
 } RoundingMode;
  • BM1686:tensor_i/tensor_o数据类型可以是UINT32/UINT16/UINT8。

该操作属于 本地操作

logical_pc_shift(TODO)

对输入tensor进行逻辑位移,位移量为一个tensor。

参数说明:

tensor_i,tensor_o:均是Tensor类型,分别对应输入输出tensor;

tensor_shift:Tensor类型,表示位移的位数,每个元素值为正表示左移,值为负表示右移;shape为[tensor_i.shape(0)];

rounding_mode:RoundingMode型,表示取整方式。

void logical_pc_shift(
const Tensor& tensor_i,      // [in]
const Tensor &tensor_shift,  // [in]
RoundingMode rounding_mode,  // [in]
Tensor& tensor_o)            // [out]

typedef enum {
     ROUNDING_HALF_TO_EVEN        = 0,
     ROUNDING_HALF_AWAY_FROM_ZERO = 1,
     ROUNDING_TOWARDS_ZERO        = 2,
     ROUNDING_DOWN                = 3,   /* FLOOR */
     ROUNDING_UP                  = 4,   /* CEIL */
     ROUNDING_HALF_UP             = 5,
     ROUNDING_HALF_DOWN           = 6,
     ROUNDING_UNKNOWN             = -1
 } RoundingMode;
  • BM1686:tensor_i/tensor_o数据类型可以是UINT32/UINT16/UINT8。tensor_shift的数据类型可以是INT32/INT16/INT8;tensor_shift的数据类型大小不能超过tensor_i的数据类型大小。

该操作属于 本地操作