* use general fmadd * forceline x86 fmadd for better performance * fix msvc compile warning * simplify swish implementation * Use activation layer for better performance * Optimize x86 ConvolutionDepthWise activationtags/20211122
| @@ -155,16 +155,11 @@ typedef union imm_xmm_union | |||
| } | |||
| #if _MSC_VER | |||
| #pragma WARNING(Using SSE2 to perform AVX2 bitshift ops) | |||
| #pragma message("Using SSE2 to perform AVX2 bitshift ops") | |||
| #else | |||
| #warning "Using SSE2 to perform AVX2 bitshift ops" | |||
| #endif | |||
| #if _MSC_VER | |||
| #pragma WARNING(Using SSE2 to perform AVX2 bitshift ops) | |||
| #else | |||
| #warning "Using SSE2 to perform AVX2 integer ops" | |||
| #endif | |||
| #endif /* __AVX2__ */ | |||
| AVX2_BITOP_USING_SSE2(slli_epi32) | |||
| AVX2_BITOP_USING_SSE2(srli_epi32) | |||
| @@ -495,42 +495,33 @@ int Convolution_x86::forward(const Mat& bottom_blob, Mat& top_blob, const Option | |||
| __m256 _val7 = _mm256_broadcast_ss((sptr + space_ofs[k] * 8) + 7); | |||
| __m256 _w0 = _mm256_loadu_ps(kptr); | |||
| __m256 _mul0 = _mm256_mul_ps(_val0, _w0); | |||
| __m256 _w1 = _mm256_loadu_ps(kptr + 8); | |||
| __m256 _mul1 = _mm256_mul_ps(_val1, _w1); | |||
| __m256 _w2 = _mm256_loadu_ps(kptr + 16); | |||
| __m256 _mul2 = _mm256_mul_ps(_val2, _w2); | |||
| __m256 _w3 = _mm256_loadu_ps(kptr + 24); | |||
| __m256 _mul3 = _mm256_mul_ps(_val3, _w3); | |||
| __m256 _w4 = _mm256_loadu_ps(kptr + 32); | |||
| __m256 _mul4 = _mm256_mul_ps(_val4, _w4); | |||
| __m256 _w5 = _mm256_loadu_ps(kptr + 40); | |||
| __m256 _mul5 = _mm256_mul_ps(_val5, _w5); | |||
| __m256 _w6 = _mm256_loadu_ps(kptr + 48); | |||
| __m256 _mul6 = _mm256_mul_ps(_val6, _w6); | |||
| __m256 _w7 = _mm256_loadu_ps(kptr + 56); | |||
| __m256 _mul7 = _mm256_mul_ps(_val7, _w7); | |||
| __m256 _sum01 = _mm256_add_ps(_mul0, _mul1); | |||
| __m256 _sum23 = _mm256_add_ps(_mul2, _mul3); | |||
| __m256 _sum45 = _mm256_add_ps(_mul4, _mul5); | |||
| __m256 _sum67 = _mm256_add_ps(_mul6, _mul7); | |||
| __m256 _sum_lo = _mm256_add_ps(_sum01, _sum23); | |||
| __m256 _sum_hi = _mm256_add_ps(_sum45, _sum67); | |||
| __m256 _sum_all = _mm256_add_ps(_sum_lo, _sum_hi); | |||
| _sum = _mm256_add_ps(_sum_all, _sum); | |||
| _mm256_comp_fmadd_ps8(_sum, | |||
| _val0, _val1, _val2, _val3, _val4, _val5, _val6, _val7, | |||
| _w0, _w1, _w2, _w3, _w4, _w5, _w6, _w7); | |||
| kptr += 64; | |||
| } | |||
| } | |||
| _sum = activation_avx(_sum, activation_type, activation_params); | |||
| _mm256_storeu_ps(outptr + j * 8, _sum); | |||
| } | |||
| outptr += outw * 8; | |||
| } | |||
| } | |||
| if (activation) | |||
| { | |||
| activation->forward_inplace(top_blob, opt); | |||
| } | |||
| } | |||
| } | |||
| @@ -591,14 +582,17 @@ int Convolution_x86::forward(const Mat& bottom_blob, Mat& top_blob, const Option | |||
| } | |||
| } | |||
| _sum = activation_avx(_sum, activation_type, activation_params); | |||
| _mm256_storeu_ps(outptr + j * 8, _sum); | |||
| } | |||
| outptr += outw * 8; | |||
| } | |||
| } | |||
| if (activation) | |||
| { | |||
| activation->forward_inplace(top_blob, opt); | |||
| } | |||
| } | |||
| } | |||
| @@ -650,14 +644,17 @@ int Convolution_x86::forward(const Mat& bottom_blob, Mat& top_blob, const Option | |||
| } | |||
| } | |||
| _sum = activation_avx(_sum, activation_type, activation_params); | |||
| _mm256_storeu_ps(outptr + j * 8, _sum); | |||
| } | |||
| outptr += outw * 8; | |||
| } | |||
| } | |||
| if (activation) | |||
| { | |||
| activation->forward_inplace(top_blob, opt); | |||
| } | |||
| } | |||
| } | |||
| @@ -428,8 +428,6 @@ int ConvolutionDepthWise_x86::forward(const Mat& bottom_blob, Mat& top_blob, con | |||
| _sum = _mm256_comp_fmadd_ps(_val, _w, _sum); | |||
| } | |||
| _sum = activation_avx(_sum, activation_type, activation_params); | |||
| _mm256_storeu_ps(outptr + j * 8, _sum); | |||
| } | |||
| @@ -437,6 +435,11 @@ int ConvolutionDepthWise_x86::forward(const Mat& bottom_blob, Mat& top_blob, con | |||
| } | |||
| } | |||
| if (activation) | |||
| { | |||
| activation->forward_inplace(top_blob, opt); | |||
| } | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -47,7 +47,7 @@ int Swish_x86::forward_inplace(Mat& bottom_top_blob, const Option& opt) const | |||
| for (int i = 0; i < size; i++) | |||
| { | |||
| __m256 _p = _mm256_loadu_ps(ptr); | |||
| _mm256_storeu_ps(ptr, _mm256_mul_ps(_p, sigmoid_avx(_p))); | |||
| _mm256_storeu_ps(ptr, swish_avx(_p)); | |||
| ptr += 8; | |||
| } | |||
| } | |||
| @@ -66,7 +66,7 @@ int Swish_x86::forward_inplace(Mat& bottom_top_blob, const Option& opt) const | |||
| for (int i = 0; i < size; i++) | |||
| { | |||
| __m128 _p = _mm_loadu_ps(ptr); | |||
| _mm_storeu_ps(ptr, _mm_mul_ps(_p, sigmoid_sse(_p))); | |||
| _mm_storeu_ps(ptr, swish_sse(_p)); | |||
| ptr += 4; | |||
| } | |||
| } | |||
| @@ -86,14 +86,14 @@ int Swish_x86::forward_inplace(Mat& bottom_top_blob, const Option& opt) const | |||
| for (; i + 7 < size; i += 8) | |||
| { | |||
| __m256 _p = _mm256_loadu_ps(ptr); | |||
| _mm256_storeu_ps(ptr, _mm256_mul_ps(_p, sigmoid_avx(_p))); | |||
| _mm256_storeu_ps(ptr, swish_avx(_p)); | |||
| ptr += 8; | |||
| } | |||
| #endif // __AVX__ | |||
| for (; i + 3 < size; i += 4) | |||
| { | |||
| __m128 _p = _mm_loadu_ps(ptr); | |||
| _mm_storeu_ps(ptr, _mm_mul_ps(_p, sigmoid_sse(_p))); | |||
| _mm_storeu_ps(ptr, swish_sse(_p)); | |||
| ptr += 4; | |||
| } | |||
| #endif // __SSE2__ | |||
| @@ -45,7 +45,7 @@ static NCNN_FORCEINLINE __m128 mish_sse(__m128 inputs) | |||
| static NCNN_FORCEINLINE __m128 swish_sse(__m128 inputs) | |||
| { | |||
| const __m128 one = _mm_set1_ps(1.0f); | |||
| return _mm_div_ps(inputs, _mm_add_ps(one, exp_ps(_mm_sub_ps(_mm_setzero_ps(), inputs)))); | |||
| return _mm_mul_ps(inputs, sigmoid_sse(inputs)); | |||
| } | |||
| static NCNN_FORCEINLINE __m128 hardswish_sse(__m128 inputs, __m128 a, __m128 b) | |||
| @@ -147,7 +147,7 @@ static NCNN_FORCEINLINE __m256 mish_avx(__m256 inputs) | |||
| static NCNN_FORCEINLINE __m256 swish_avx(__m256 inputs) | |||
| { | |||
| const __m256 one = _mm256_set1_ps(1.0f); | |||
| return _mm256_div_ps(inputs, _mm256_add_ps(one, exp256_ps(_mm256_sub_ps(_mm256_setzero_ps(), inputs)))); | |||
| return _mm256_mul_ps(inputs, sigmoid_avx(inputs)); | |||
| } | |||
| static NCNN_FORCEINLINE __m256 hardswish_avx(__m256 inputs, __m256 a, __m256 b) | |||
| @@ -17,7 +17,7 @@ | |||
| static inline signed char float2int8(float v) | |||
| { | |||
| int int32 = round(v); | |||
| int int32 = (int)round(v); | |||
| if (int32 > 127) return 127; | |||
| if (int32 < -127) return -127; | |||
| return (signed char)int32; | |||
| @@ -42,14 +42,14 @@ static inline int64_t float2int8_sse(const __m128& _v0, const __m128& _v1) | |||
| int v0_i[4]; | |||
| int v1_i[4]; | |||
| v0_i[0] = round(v0[0]); | |||
| v0_i[1] = round(v0[1]); | |||
| v0_i[2] = round(v0[2]); | |||
| v0_i[3] = round(v0[3]); | |||
| v1_i[0] = round(v1[0]); | |||
| v1_i[1] = round(v1[1]); | |||
| v1_i[2] = round(v1[2]); | |||
| v1_i[3] = round(v1[3]); | |||
| v0_i[0] = (int)round(v0[0]); | |||
| v0_i[1] = (int)round(v0[1]); | |||
| v0_i[2] = (int)round(v0[2]); | |||
| v0_i[3] = (int)round(v0[3]); | |||
| v1_i[0] = (int)round(v1[0]); | |||
| v1_i[1] = (int)round(v1[1]); | |||
| v1_i[2] = (int)round(v1[2]); | |||
| v1_i[3] = (int)round(v1[3]); | |||
| __m128i _v0_i = _mm_loadu_si128((const __m128i*)v0_i); | |||
| __m128i _v1_i = _mm_loadu_si128((const __m128i*)v1_i); | |||
| @@ -82,22 +82,22 @@ static inline __m128i float2int8_sse(const __m128& _v0, const __m128& _v1, const | |||
| int v1_i[4]; | |||
| int v2_i[4]; | |||
| int v3_i[4]; | |||
| v0_i[0] = round(v0[0]); | |||
| v0_i[1] = round(v0[1]); | |||
| v0_i[2] = round(v0[2]); | |||
| v0_i[3] = round(v0[3]); | |||
| v1_i[0] = round(v1[0]); | |||
| v1_i[1] = round(v1[1]); | |||
| v1_i[2] = round(v1[2]); | |||
| v1_i[3] = round(v1[3]); | |||
| v2_i[0] = round(v2[0]); | |||
| v2_i[1] = round(v2[1]); | |||
| v2_i[2] = round(v2[2]); | |||
| v2_i[3] = round(v2[3]); | |||
| v3_i[0] = round(v3[0]); | |||
| v3_i[1] = round(v3[1]); | |||
| v3_i[2] = round(v3[2]); | |||
| v3_i[3] = round(v3[3]); | |||
| v0_i[0] = (int)round(v0[0]); | |||
| v0_i[1] = (int)round(v0[1]); | |||
| v0_i[2] = (int)round(v0[2]); | |||
| v0_i[3] = (int)round(v0[3]); | |||
| v1_i[0] = (int)round(v1[0]); | |||
| v1_i[1] = (int)round(v1[1]); | |||
| v1_i[2] = (int)round(v1[2]); | |||
| v1_i[3] = (int)round(v1[3]); | |||
| v2_i[0] = (int)round(v2[0]); | |||
| v2_i[1] = (int)round(v2[1]); | |||
| v2_i[2] = (int)round(v2[2]); | |||
| v2_i[3] = (int)round(v2[3]); | |||
| v3_i[0] = (int)round(v3[0]); | |||
| v3_i[1] = (int)round(v3[1]); | |||
| v3_i[2] = (int)round(v3[2]); | |||
| v3_i[3] = (int)round(v3[3]); | |||
| __m128i _v0_i = _mm_loadu_si128((const __m128i*)v0_i); | |||
| __m128i _v1_i = _mm_loadu_si128((const __m128i*)v1_i); | |||
| @@ -282,7 +282,7 @@ static inline void float2int8_loop(const __m256& _v0, signed char* output) | |||
| } | |||
| #endif | |||
| static inline void _mm256_comp_fmadd_ps4(__m256& _sum, | |||
| static NCNN_FORCEINLINE void _mm256_comp_fmadd_ps4(__m256& _sum, | |||
| const __m256& _w0, const __m256& _w1, const __m256& _w2, const __m256& _w3, | |||
| const __m256& _v0, const __m256& _v1, const __m256& _v2, const __m256& _v3) | |||
| { | |||
| @@ -296,7 +296,7 @@ static inline void _mm256_comp_fmadd_ps4(__m256& _sum, | |||
| _sum = _mm256_add_ps(_sum, _sum0123); | |||
| } | |||
| static inline void _mm256_comp_fmadd_ps8(__m256& _sum, | |||
| static NCNN_FORCEINLINE void _mm256_comp_fmadd_ps8(__m256& _sum, | |||
| const __m256& _w0, const __m256& _w1, const __m256& _w2, const __m256& _w3, const __m256& _w4, const __m256& _w5, const __m256& _w6, const __m256& _w7, | |||
| const __m256& _v0, const __m256& _v1, const __m256& _v2, const __m256& _v3, const __m256& _v4, const __m256& _v5, const __m256& _v6, const __m256& _v7) | |||
| { | |||