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]
  BMlangConvParam param)    // [in]
//example:
//vector<Tensor*> vec = {&tensor_input, &tensor_filter, &tensor_bias};
//BMlangConvParam 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是量化计算参数, 仅在量化计算时才会被用到。

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

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种量化计算模式。

该操作属于 本地操作

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。

该操作属于 本地操作

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种量化计算模式。

该操作属于 全局操作

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,此时不要求输入输出数据类型一致。定点计算时,若结果超出位宽时将做饱和处理。

该操作属于 本地操作

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。

该操作属于 本地操作

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数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

该操作属于 本地操作

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数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

该操作属于 本地操作

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来计算。输入输出数据类型要求一致。

该操作属于 本地操作

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来计算。输入输出数据类型要求一致。

该操作属于 本地操作

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,此时不要求输入输出数据类型一致。定点计算时,若结果超出位宽将做饱和处理。

该操作属于 本地操作

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数据类型存在。定点计算时,若结果超出位宽将做饱和处理。

该操作属于 本地操作

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,不要求输入输出数据类型一致。定点计算时,若结果超出位宽将做饱和处理。

该操作属于 本地操作

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。

该操作属于 本地操作

rsubs

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

void rsubs(
const Scalar& scalar,    // [in]
const Tensor& tensor_i0, // [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数据类型存在。若结果超出位宽则做饱和处理。

该操作属于 本地操作

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来计算。要求输入输出数据类型保持一致。

该操作属于 本地操作

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来计算。要求输入输出数据类型保持一致。

该操作属于 本地操作

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对数)
  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类型,指定激活函数的类型。

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

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

该操作属于 本地操作

ceil

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

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

该操作属于 本地操作

floor

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

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

该操作属于 本地操作

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来计算。输入输出数据类型要求一致。

该操作属于 本地操作

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的相互转换。数据转换时,若位宽不够则做饱和处理。浮点向定点转换时,做四舍五入处理。

该操作属于 受限的本地操作 。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至少有一个是有符号数,则输出要求是有符号数。

该操作属于 本地操作

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且输入中至少有一个为有符号数时,输出则要求是有符号数。

该操作属于 本地操作

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。不要求输入输出位宽一致,结果超过位宽时做饱和处理。输出符号位要求是有符号的。

该操作属于 本地操作

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至少有一个是有符号数,则输出要求是有符号数。

该操作属于 本地操作

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且输入中至少有一个为有符号数时,输出则要求是有符号数。

该操作属于 本地操作

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。不要求输入输出位宽一致,结果超过位宽时做饱和处理。输出符号位要求是有符号的。

该操作属于 本地操作

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。不要求输入输出位宽一致,结果超过位宽时做饱和处理。输出符号位要求是有符号的。

该操作属于 本地操作

copy

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

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

  • BM1682:数据类型可以是FLOAT32/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。输入输出数据类型要求相同。

该操作属于 本地操作

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。输入输出数据类型要求相同。

该操作属于 本地操作

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。输入输出数据类型要求相同。

该操作属于 本地操作

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。输入输出数据类型要求相同。

该操作属于 本地操作

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。输入输出数据类型要求相同。

该操作属于 本地操作

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。输入输出数据类型要求相同。

该操作属于 本地操作

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。输入输出数据类型要求相同。

该操作属于 本地操作

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。输入输出数据类型要求相同。

该操作属于 本地操作

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。输入输出数据类型要求相同。

该操作属于 本地操作

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。输入输出数据类型要求相同。

该操作属于 本地操作

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。输入输出数据类型要求相同。

该操作属于 本地操作

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。输入输出数据类型要求相同。

该操作属于 本地操作

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要求数据类型相同。

该操作属于 本地操作

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要求数据类型相同。

该操作属于 本地操作

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要求数据类型相同。

该操作属于 本地操作

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要求数据类型相同。

该操作属于 本地操作

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。输入输出要求正负符号一致,但不要求位宽一致。

该操作属于 本地操作

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。输入输出要求正负符号一致,但不要求位宽一致。

该操作属于 本地操作

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。要求输入输出的数据类型都相同。

该操作属于 本地操作

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。要求输入输出的数据类型都相同。

该操作属于 本地操作

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。要求输入输出的数据类型都相同。

该操作属于 本地操作

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。要求输入输出的数据类型都相同。

该操作属于 本地操作

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。要求输入输出的数据类型都相同。

该操作属于 本地操作

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。要求输入输出的数据类型都相同。

该操作属于 本地操作

Triangle Operator

sin

正弦函数计算。

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

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

该操作属于 本地操作

cos

余弦函数计算。

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

  • BM1684:只支持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数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

该操作属于 本地操作

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数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

该操作属于 本地操作

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,此时不要求输入输出数据类型一致。定点计算时,若结果超出位宽时将做饱和处理。

该操作属于 本地操作

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。

该操作属于 本地操作

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。

该操作属于 本地操作

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。

该操作属于 本地操作

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。

该操作属于 本地操作

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数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

该操作属于 本地操作

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数据类型存在。定点计算时,若结果超出位宽时将做饱和处理。

该操作属于 本地操作

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,此时不要求输入输出数据类型一致。定点计算时,若结果超出位宽时将做饱和处理。

该操作属于 本地操作

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。

该操作属于 本地操作

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。

该操作属于 本地操作

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。

该操作属于 本地操作

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。

该操作属于 本地操作

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。

该操作当前属于 全局操作

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。

该操作当前属于 受限本地操作 。当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。

该操作属于 受限本地操作 。当不会对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。

该操作当前属于 全局操作

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。

该操作当前属于 全局操作

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。

该操作当前属于 受限本地操作 。当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。

该操作当前属于 全局操作

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。

该操作当前属于 受限本地操作 。当前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。

该操作当前属于 全局操作

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。

该操作当前属于 全局操作

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。

该操作当前属于 全局操作

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。

该操作属于 本地操作

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。

该操作属于 本地操作

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要求数据类型一致。

该操作属于 全局操作

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。

该操作属于 全局操作

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, 1, 1, 0}, {2});
   输入信息代表input data = true时h, w,第二维代表tensor的维度
*/
  • BM1682:tensor_i数据类型只能是FLOAT32,index数据类型要求是INT32。

  • BM1684: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:支持。

该操作属于 本地操作

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。

该操作属于 本地操作

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。

该操作属于 本地操作

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。

该操作目前属于 受限本地操作 ,在数据类型是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。

该操作属于 受限本地操作 ,当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。

该操作属于 全局操作

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的性能。

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

void sort(
    const Tensor& tensor_i,   // [in]
    Tensor& tensor_o,         // [out]
    Tensor& index_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。

该操作属于 全局操作

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的性能。

参数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。

该操作属于 全局操作

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。输入输出数据类型要求一致。

该操作当前属于 全局操作

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。输入输出数据类型要求一致。

该操作当前属于 全局操作

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。输入输出数据类型要求一致。

该操作当前属于 全局操作

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。

该操作当前属于 全局操作

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。

该操作当前属于 全局操作

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。

该操作虽然属于 全局操作 ,但是在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。

该操作当前属于 全局操作

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。

该操作当前属于 全局操作

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的索引。

该操作属于 全局操作

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。

该操作属于 全局操作