diff --git a/src/layer/arm/neon_mathfun_fp16s.h b/src/layer/arm/neon_mathfun_fp16s.h index ff6f91d47..c26ddb673 100644 --- a/src/layer/arm/neon_mathfun_fp16s.h +++ b/src/layer/arm/neon_mathfun_fp16s.h @@ -844,7 +844,7 @@ static inline float16x4_t gelu_ps_f16(float16x4_t x) float16x4_t _half = vdup_n_f16(0.5f); float16x4_t _blob = vmul_f16(vdup_n_f16(-0.70710678f), x); _blob = erfc_ps_f16(_blob); - return vmul_f16(_half, vmul_f16(_blob, x)); + return vmul_f16(vmul_f16(_half, _blob), x); } static inline float16x8_t gelu_ps_f16(float16x8_t x) @@ -852,7 +852,7 @@ static inline float16x8_t gelu_ps_f16(float16x8_t x) float16x8_t _half = vdupq_n_f16(0.5f); float16x8_t _blob = vmulq_f16(vdupq_n_f16(-0.70710678f), x); _blob = erfc_ps_f16(_blob); - return vmulq_f16(_half, vmulq_f16(_blob, x)); + return vmulq_f16(vmulq_f16(_half, _blob), x); } static inline float16x4_t fast_gelu_ps_f16(float16x4_t x) @@ -865,7 +865,7 @@ static inline float16x4_t fast_gelu_ps_f16(float16x4_t x) _blob = vfma_f16(_blob, vdup_n_f16(0.79788452f), x); _blob = tanh_ps_f16(_blob); _blob = vadd_f16(_one, _blob); - return vmul_f16(_half, vmul_f16(_blob, x)); + return vmul_f16(vmul_f16(_half, _blob), x); } static inline float16x8_t fast_gelu_ps_f16(float16x8_t x) @@ -878,7 +878,7 @@ static inline float16x8_t fast_gelu_ps_f16(float16x8_t x) _blob = vfmaq_f16(_blob, vdupq_n_f16(0.79788452f), x); _blob = tanh_ps_f16(_blob); _blob = vaddq_f16(_one, _blob); - return vmulq_f16(_half, vmulq_f16(_blob, x)); + return vmulq_f16(vmulq_f16(_half, _blob), x); } static inline float16x4_t selu_ps_f16(float16x4_t x, float16x4_t alphaxlambda, float16x4_t lambda) diff --git a/src/layer/riscv/gelu_riscv_zfh.cpp b/src/layer/riscv/gelu_riscv_zfh.cpp index ce819111a..64ba66820 100644 --- a/src/layer/riscv/gelu_riscv_zfh.cpp +++ b/src/layer/riscv/gelu_riscv_zfh.cpp @@ -49,8 +49,8 @@ int GELU_riscv::forward_inplace_fp16s(Mat& bottom_top_blob, const Option& opt) c vfloat16m4_t _one = __riscv_vfmv_v_f_f16m4((__fp16)1.f, vl); _tanharg = __riscv_vfadd_vv_f16m4(_tanharg, _one, vl); + _tanharg = __riscv_vfmul_vf_f16m4(_tanharg, (__fp16)0.5f, vl); _p = __riscv_vfmul_vv_f16m4(_p, _tanharg, vl); - _p = __riscv_vfmul_vf_f16m4(_p, (__fp16)0.5f, vl); __riscv_vse16_v_f16m4(ptr, _p, vl); n -= vl; diff --git a/tests/test_gelu.cpp b/tests/test_gelu.cpp index d330f5e2a..71d2d9bf5 100644 --- a/tests/test_gelu.cpp +++ b/tests/test_gelu.cpp @@ -89,6 +89,24 @@ static int test_gelu_4() || test_gelu(RandomMat(128, -2000.f, 2000.f), true); } +static int test_gelu_5() +{ + // finite fp16 inputs must not overflow when multiplying by 1 + tanh(...) + const float values[] = {-65504.f, -40000.f, -32768.f, -32752.f, -1.f, -0.f, 0.f, 1.f, 32752.f, 32768.f, 40000.f, 65504.f}; + ncnn::Mat a(128); + ncnn::Mat b(127); + for (int i = 0; i < a.w; i++) + a[i] = values[i % 12]; + for (int i = 0; i < b.w; i++) + b[i] = values[i % 12]; + + return 0 + || test_gelu(a, false) + || test_gelu(a, true) + || test_gelu(b, false) + || test_gelu(b, true); +} + int main() { SRAND(7767517); @@ -98,5 +116,6 @@ int main() || test_gelu_1() || test_gelu_2() || test_gelu_3() - || test_gelu_4(); + || test_gelu_4() + || test_gelu_5(); }