Browse Source

Optimize avx convolution activation (#3299)

* 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 activation
tags/20211122
zhiliu6 GitHub 4 years ago
parent
commit
a08f700775
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 63 deletions
  1. +1
    -6
      src/layer/x86/avx_mathfun.h
  2. +19
    -22
      src/layer/x86/convolution_x86.cpp
  3. +5
    -2
      src/layer/x86/convolutiondepthwise_x86.cpp
  4. +4
    -4
      src/layer/x86/swish_x86.cpp
  5. +2
    -2
      src/layer/x86/x86_activation.h
  6. +27
    -27
      src/layer/x86/x86_usability.h

+ 1
- 6
src/layer/x86/avx_mathfun.h View File

@@ -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)


+ 19
- 22
src/layer/x86/convolution_x86.cpp View File

@@ -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);
}
}
}



+ 5
- 2
src/layer/x86/convolutiondepthwise_x86.cpp View File

@@ -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;
}
}


+ 4
- 4
src/layer/x86/swish_x86.cpp View File

@@ -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__


+ 2
- 2
src/layer/x86/x86_activation.h View File

@@ -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)


+ 27
- 27
src/layer/x86/x86_usability.h View File

@@ -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)
{


Loading…
Cancel
Save