@@ -152,9 +152,14 @@ pub(crate) unsafe fn fast_exp_sigmoid_sse(x: __m128) -> __m128 {
152152 let n_f = _mm_cvtepi32_ps ( n_i) ;
153153 let r = _mm_sub_ps ( x, _mm_mul_ps ( n_f, _mm_set1_ps ( std:: f32:: consts:: LN_2 ) ) ) ;
154154
155- let mut poly = _mm_add_ps ( _mm_set1_ps ( 0.5 ) , _mm_mul_ps ( r, _mm_set1_ps ( 1.0 / 6.0 ) ) ) ;
156- poly = _mm_add_ps ( _mm_set1_ps ( 1.0 ) , _mm_mul_ps ( r, poly) ) ;
157- poly = _mm_add_ps ( _mm_set1_ps ( 1.0 ) , _mm_mul_ps ( r, poly) ) ;
155+ // minimax deg-4 — точность сигмоиды важна для conf-логитов (см. NEON)
156+ let mut poly = _mm_add_ps (
157+ _mm_set1_ps ( 0.167_781_98 ) ,
158+ _mm_mul_ps ( r, _mm_set1_ps ( 0.041_894_704 ) ) ,
159+ ) ;
160+ poly = _mm_add_ps ( _mm_set1_ps ( 0.499_990_85 ) , _mm_mul_ps ( r, poly) ) ;
161+ poly = _mm_add_ps ( _mm_set1_ps ( 0.999_971_3 ) , _mm_mul_ps ( r, poly) ) ;
162+ poly = _mm_add_ps ( _mm_set1_ps ( 1.000_000_1 ) , _mm_mul_ps ( r, poly) ) ;
158163
159164 let pow2n = {
160165 #[ cfg( target_arch = "x86" ) ]
@@ -261,12 +266,14 @@ pub(crate) unsafe fn fast_exp_sigmoid_avx(x: __m256) -> __m256 {
261266 _mm256_mul_ps ( n_f, _mm256_set1_ps ( std:: f32:: consts:: LN_2 ) ) ,
262267 ) ;
263268
269+ // minimax deg-4 — точность сигмоиды важна для conf-логитов (см. NEON)
264270 let mut poly = _mm256_add_ps (
265- _mm256_set1_ps ( 0.5 ) ,
266- _mm256_mul_ps ( r, _mm256_set1_ps ( 1.0 / 6.0 ) ) ,
271+ _mm256_set1_ps ( 0.167_781_98 ) ,
272+ _mm256_mul_ps ( r, _mm256_set1_ps ( 0.041_894_704 ) ) ,
267273 ) ;
268- poly = _mm256_add_ps ( _mm256_set1_ps ( 1.0 ) , _mm256_mul_ps ( r, poly) ) ;
269- poly = _mm256_add_ps ( _mm256_set1_ps ( 1.0 ) , _mm256_mul_ps ( r, poly) ) ;
274+ poly = _mm256_add_ps ( _mm256_set1_ps ( 0.499_990_85 ) , _mm256_mul_ps ( r, poly) ) ;
275+ poly = _mm256_add_ps ( _mm256_set1_ps ( 0.999_971_3 ) , _mm256_mul_ps ( r, poly) ) ;
276+ poly = _mm256_add_ps ( _mm256_set1_ps ( 1.000_000_1 ) , _mm256_mul_ps ( r, poly) ) ;
270277
271278 let pow2n = {
272279 #[ cfg( target_arch = "x86" ) ]
@@ -355,9 +362,15 @@ pub(crate) unsafe fn fast_exp_sigmoid_avx512(x: __m512) -> __m512 {
355362 _mm512_mul_ps ( n_f, _mm512_set1_ps ( std:: f32:: consts:: LN_2 ) ) ,
356363 ) ;
357364
358- let mut poly = _mm512_fmadd_ps ( r, _mm512_set1_ps ( 1.0 / 6.0 ) , _mm512_set1_ps ( 0.5 ) ) ;
359- poly = _mm512_fmadd_ps ( r, poly, _mm512_set1_ps ( 1.0 ) ) ;
360- poly = _mm512_fmadd_ps ( r, poly, _mm512_set1_ps ( 1.0 ) ) ;
365+ // minimax deg-4 — точность сигмоиды важна для conf-логитов (см. NEON)
366+ let mut poly = _mm512_fmadd_ps (
367+ r,
368+ _mm512_set1_ps ( 0.041_894_704 ) ,
369+ _mm512_set1_ps ( 0.167_781_98 ) ,
370+ ) ;
371+ poly = _mm512_fmadd_ps ( r, poly, _mm512_set1_ps ( 0.499_990_85 ) ) ;
372+ poly = _mm512_fmadd_ps ( r, poly, _mm512_set1_ps ( 0.999_971_3 ) ) ;
373+ poly = _mm512_fmadd_ps ( r, poly, _mm512_set1_ps ( 1.000_000_1 ) ) ;
361374
362375 _mm512_scalef_ps ( poly, n_f)
363376}
@@ -425,9 +438,12 @@ pub(crate) unsafe fn fast_exp_sigmoid_neon(x: float32x4_t) -> float32x4_t {
425438 vmulq_f32 ( vcvtq_f32_s32 ( n_i) , vdupq_n_f32 ( std:: f32:: consts:: LN_2 ) ) ,
426439 ) ;
427440 let pow2n = vreinterpretq_f32_s32 ( vshlq_n_s32 :: < 23 > ( vaddq_s32 ( n_i, vdupq_n_s32 ( 127 ) ) ) ) ;
428- let p = vfmaq_f32 ( vdupq_n_f32 ( 0.5 ) , r, vdupq_n_f32 ( 1.0 / 6.0 ) ) ;
429- let p = vfmaq_f32 ( vdupq_n_f32 ( 1.0 ) , r, p) ;
430- vmulq_f32 ( vfmaq_f32 ( vdupq_n_f32 ( 1.0 ) , r, p) , pow2n)
441+ // minimax deg-4 (как fast_exp_neon): обрезанный кубический Тейлор давал
442+ // ~6e-4 отн. ошибки, что заметно копится через десятки SiLU-слоёв
443+ let p = vfmaq_f32 ( vdupq_n_f32 ( 0.167_781_98 ) , r, vdupq_n_f32 ( 0.041_894_704 ) ) ;
444+ let p = vfmaq_f32 ( vdupq_n_f32 ( 0.499_990_85 ) , r, p) ;
445+ let p = vfmaq_f32 ( vdupq_n_f32 ( 0.999_971_3 ) , r, p) ;
446+ vmulq_f32 ( vfmaq_f32 ( vdupq_n_f32 ( 1.000_000_1 ) , r, p) , pow2n)
431447}
432448
433449// ===========================================================================
0 commit comments