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表示四舍五入。
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下能获取最好的芯片性能。
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。
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表示四舍五入。
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下能获取最好的芯片性能。
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。
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);
- 说明:
可以根据descending来设置输出按照升序或降序排列,descending=true降序排列,descending=false升序排列。
tensor_input, tensor_val, tensor_idx依次为输入tensor、输出数值(value)tensor和对应的索引值(index)tensor。
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。
该操作属于 全局操作 。