mirror of
https://github.com/Tencent/ncnn.git
synced 2026-10-17 04:41:47 +08:00
arm/riscv: avoid fp16 GELU overflow (#7060)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
+20
-1
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user