| @@ -25,6 +25,112 @@ DEFINE_LAYER_CREATOR(PReLU_arm) | |||
| int PReLU_arm::forward_inplace(Mat& bottom_top_blob, const Option& opt) const | |||
| { | |||
| int dims = bottom_top_blob.dims; | |||
| int elempack = bottom_top_blob.elempack; | |||
| if (opt.use_packing_layout) | |||
| { | |||
| if (elempack == 4) | |||
| { | |||
| float32x4_t _zero = vdupq_n_f32(0.f); | |||
| if (dims == 1) | |||
| { | |||
| int w = bottom_top_blob.w; | |||
| float* ptr = bottom_top_blob; | |||
| if (num_slope > 1) | |||
| { | |||
| const float* slope = slope_data; | |||
| #pragma omp parallel for num_threads(opt.num_threads) | |||
| for (int i=0; i<w; i++) | |||
| { | |||
| float32x4_t _p = vld1q_f32(ptr); | |||
| float32x4_t _slope = vld1q_f32(slope); | |||
| uint32x4_t _lemask = vcleq_f32(_p, _zero); | |||
| float32x4_t _ps = vmulq_f32(_p, _slope); | |||
| _p = vbslq_f32(_lemask, _ps, _p); | |||
| vst1q_f32(ptr, _p); | |||
| ptr += 4; | |||
| slope += 4; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| float32x4_t _slope = vdupq_n_f32(slope_data[0]); | |||
| #pragma omp parallel for num_threads(opt.num_threads) | |||
| for (int i=0; i<w; i++) | |||
| { | |||
| float32x4_t _p = vld1q_f32(ptr); | |||
| uint32x4_t _lemask = vcleq_f32(_p, _zero); | |||
| float32x4_t _ps = vmulq_f32(_p, _slope); | |||
| _p = vbslq_f32(_lemask, _ps, _p); | |||
| vst1q_f32(ptr, _p); | |||
| ptr += 4; | |||
| } | |||
| } | |||
| } | |||
| if (dims == 2) | |||
| { | |||
| int w = bottom_top_blob.w; | |||
| int h = bottom_top_blob.h; | |||
| #pragma omp parallel for num_threads(opt.num_threads) | |||
| for (int i=0; i<h; i++) | |||
| { | |||
| float* ptr = bottom_top_blob.row(i); | |||
| float32x4_t _slope = num_slope > 1 ? vld1q_f32((const float*)slope_data + i * 4) : vdupq_n_f32(slope_data[0]); | |||
| for (int j=0; j<w; j++) | |||
| { | |||
| float32x4_t _p = vld1q_f32(ptr); | |||
| uint32x4_t _lemask = vcleq_f32(_p, _zero); | |||
| float32x4_t _ps = vmulq_f32(_p, _slope); | |||
| _p = vbslq_f32(_lemask, _ps, _p); | |||
| vst1q_f32(ptr, _p); | |||
| ptr += 4; | |||
| } | |||
| } | |||
| } | |||
| if (dims == 3) | |||
| { | |||
| int w = bottom_top_blob.w; | |||
| int h = bottom_top_blob.h; | |||
| int channels = bottom_top_blob.c; | |||
| int size = w * h; | |||
| #pragma omp parallel for num_threads(opt.num_threads) | |||
| for (int q=0; q<channels; q++) | |||
| { | |||
| float* ptr = bottom_top_blob.channel(q); | |||
| float32x4_t _slope = num_slope > 1 ? vld1q_f32((const float*)slope_data + q * 4) : vdupq_n_f32(slope_data[0]); | |||
| for (int i=0; i<size; i++) | |||
| { | |||
| float32x4_t _p = vld1q_f32(ptr); | |||
| uint32x4_t _lemask = vcleq_f32(_p, _zero); | |||
| float32x4_t _ps = vmulq_f32(_p, _slope); | |||
| _p = vbslq_f32(_lemask, _ps, _p); | |||
| vst1q_f32(ptr, _p); | |||
| ptr += 4; | |||
| } | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| } // opt.use_packing_layout | |||
| if (dims != 3) | |||
| return PReLU::forward_inplace(bottom_top_blob, opt); | |||