| 44 | const int default_prio = 300; |
| 45 | |
| 46 | void selu_kernel(int i, int id, void* data, const float* input, float* output, float alpha, float lambda) |
| 47 | { |
| 48 | float alpha_lambda = alpha * lambda; |
| 49 | int step = ((int*)data)[0]; |
| 50 | float32x4_t _one = vdupq_n_f32(1.f); |
| 51 | float32x4_t _zero = vdupq_n_f32(0.f); |
| 52 | float32x4_t _alpha_lambda = vdupq_n_f32(alpha_lambda); |
| 53 | float32x4_t _lambda = vdupq_n_f32(lambda); |
| 54 | const float* cur_input = input + id * step; |
| 55 | float* cur_output = output + id * step; |
| 56 | for(int i = 0; i < (step & -4); i += 4) |
| 57 | { |
| 58 | float32x4_t _p = vld1q_f32(cur_input); |
| 59 | uint32x4_t _lemask = vcleq_f32(_p, _zero); |
| 60 | |
| 61 | float32x4_t _nps = exp_ps(_p); |
| 62 | _nps = vsubq_f32(_nps, _one); |
| 63 | _nps = vmulq_f32(_nps, _alpha_lambda); |
| 64 | |
| 65 | _p = vmulq_f32(_p, _lambda); |
| 66 | |
| 67 | _p = vbslq_f32(_lemask, _nps, _p); |
| 68 | vst1q_f32(cur_output, _p); |
| 69 | cur_input += 4; |
| 70 | cur_output += 4; |
| 71 | } |
| 72 | for(int i = step & ~3; i < step; i++) |
| 73 | { |
| 74 | if (cur_input[0] < 0.f) |
| 75 | cur_output[0] = (exp(cur_input[0]) - 1.f) * alpha_lambda; |
| 76 | else |
| 77 | cur_output[0] = cur_input[0] * lambda; |
| 78 | cur_input ++; |
| 79 | cur_output++; |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | struct SeluOps : public NodeOps |
| 84 | { |