- 正文前感谢昇腾各位工作人员,没有你们的辛勤就没有我们的进步
- 本文立意交流大赛FastGelu算子编译过程
- FastGelu算子千万别被公式吓到,其实很简单,应该说中规中矩,是道送分题
- 算子要求fp16,fp32 ,计算类型符合所有的API公式限制,也就是说不需要类型转换
- 只有一个输入,一个输出,并不需要大幅度的数据搬迁
- 唯一需要解决的就是compute的算法设计
- 不过有一点可能是计算的精度限制,在mindspore中有提供一个案例如下,提供了结果
- 通过手搓一段np代码,如下并运行
- 发现答案有一定的精度误差,可能是mindspore的精度误差,这里也没细追究
input_x = np.array([[-1.0, 4.0, -8.0], [2.0, -5.0, 9.0]]).astype(former)
y = (input_x*np.exp(0.851*(input_x-np.abs(input_x)))/(1+ np.exp(-1.702*np.abs(input_x)))).astype(former_out)
# [[-1.5420423e-01 3.9955850e+00 -9.7664270e-06]
# [ 1.9356586e+00 -1.0070159e-03 8.9999981e+00]] y
复制
- 当然官方测试案例的计算公式也做了测试,结果一致,仍有精度误差
- 这里不做细追究,有知晓原因的老师还望告知
input_x = np.array([[-1.0, 4.0, -8.0], [2.0, -5.0, 9.0]]).astype(former)
attr = 1.702
attr_opp = 0 - attr
attr_half = attr / 2
abs_x = np.abs(input_x)
mul_abs_x = abs_x * attr_opp
exp_abs_x = np.exp(mul_abs_x)
div_down = exp_abs_x + 1.0
pn_x = input_x - abs_x
mul_pn_x = pn_x * attr_half
exp_pn_x = np.exp(mul_pn_x)
div_up = input_x * exp_pn_x
y = div_up / div_down
[[-1.5420423e-01 3.9955850e+00 -9.7664270e-06]
[ 1.9356586e+00 -1.0070159e-03 8.9999981e+00]] y
复制
- compute代码用到了API比较多,但是也不难,只需要查好文档即可
__aicore__ inline void Compute(int32_t progress) {
LocalTensor<DTYPE_X> inLocal = inQueueIN.DeQue<DTYPE_X>();
LocalTensor<DTYPE_X> xLocal = inLocal;
LocalTensor<DTYPE_Y> outLocal = outQueueOUT.AllocTensor<DTYPE_Y>();
LocalTensor<DTYPE_Y> tempTensor1 = calcBuf.Get<DTYPE_Y>();
// y = (input_x*np.exp(0.851*(input_x-np.abs(input_x)))/(1+ np.exp(-1.702*np.abs(input_x)))).astype(former_out)
Abs(outLocal, xLocal, this->tileLength);
Sub(outLocal, xLocal, outLocal, this->tileLength);
Muls(outLocal, outLocal, (DTYPE_Y)0.851, this->tileLength);
Exp(outLocal, outLocal, this->tileLength);
Mul(outLocal, outLocal, xLocal, this->tileLength);
Abs(tempTensor1, xLocal, this->tileLength);
Muls(tempTensor1, tempTensor1, (DTYPE_Y)(-1.702), this->tileLength);
Exp(tempTensor1, tempTensor1, this->tileLength);
Adds(tempTensor1, tempTensor1, (DTYPE_Y)(1), this->tileLength);
Div(outLocal, outLocal, tempTensor1, this->tileLength);
outQueueOUT.EnQue<DTYPE_Y>(outLocal);
inQueueIN.FreeTensor(inLocal);
}
复制