char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
eafe15a5e
char/aliceai-t5-moe
1#ifndef HVX_SIGMOID_H 2#define HVX_SIGMOID_H 3 4#include "hvx-base.h" 5#include "hvx-inverse.h" 6#include "hvx-exp.h" 7 8#define FAST_SIGMOID_LOG2F (0x3fb8aa3b) // 1.442695022 9#define FAST_SIGMOID_C1 (0x3d009076) // 0.03138777 10#define FAST_SIGMOID_C2 (0x3e8d74bd) // 0.276281267 11#define FAST_SIGMOID_C3 (0x3f000000) // 0.5 12 13static inline HVX_Vector hvx_vec_fast_sigmoid_f32 (HVX_Vector v ) { 14v = Q6_Vqf32_vmpy_VsfVsf (v ,Q6_V_vsplat_R (FAST_SIGMOID_LOG2F )); 15v = Q6_Vqf32_vmpy_VsfVsf (Q6_Vsf_equals_Vqf32 (v ),Q6_V_vsplat_R (FAST_SIGMOID_C3 )); 16 17HVX_Vector in_int = hvx_vec_truncate_f32 (Q6_Vsf_equals_Vqf32 (v )); 18HVX_Vector x = Q6_Vqf32_vsub_Vqf32Vsf (v ,Q6_Vsf_equals_Vw (in_int )); 19HVX_Vector xx = Q6_Vqf32_vmpy_Vqf32Vqf32 (x ,x ); 20 21HVX_Vector v1 = Q6_Vqf32_vmpy_VsfVsf (Q6_Vsf_equals_Vqf32 (xx ),Q6_V_vsplat_R (FAST_SIGMOID_C2 )); 22v1 = Q6_Vqf32_vadd_Vqf32Vsf (v1 ,Q6_V_vsplat_R (FAST_SIGMOID_LOG2F )); 23 24HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (Q6_Vsf_equals_Vqf32 (x ),Q6_V_vsplat_R (FAST_SIGMOID_C1 )); 25v2 = Q6_Vqf32_vmpy_Vqf32Vqf32 (v2 ,xx ); 26v2 = Q6_Vqf32_vadd_Vqf32Vqf32 (v2 ,x ); 27 28HVX_Vector v3 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vadd_Vqf32Vqf32 (v2 ,v1 )); 29HVX_Vector v3_exponent = Q6_Vw_vasl_VwR (v3 ,1 ); 30v3_exponent = Q6_Vuw_vlsr_VuwR (v3_exponent ,24 ); 31v3_exponent = Q6_Vw_vadd_VwVw (in_int ,v3_exponent ); 32v3 = Q6_Vw_vaslacc_VwVwR (v3 ,in_int ,24 ); 33 34HVX_Vector v4 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vsub_Vqf32Vqf32 (v2 ,v1 )); 35HVX_Vector v5 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vsub_VsfVsf (v3 ,v4 )); 36 37HVX_Vector res = hvx_vec_inverse_f32 (v5 ); 38res = Q6_Vqf32_vmpy_VsfVsf (v3 ,res ); 39 40return Q6_Vsf_equals_Vqf32 (res ); 41} 42 43static inline HVX_Vector hvx_vec_fast_sigmoid_f32_guard (HVX_Vector v , 44HVX_Vector one , 45HVX_Vector max_exp , 46HVX_Vector min_exp ) { 47const HVX_VectorPred pred_max = Q6_Q_vcmp_gt_VsfVsf (max_exp ,v ); 48const HVX_VectorPred pred_min = Q6_Q_vcmp_gt_VsfVsf (v ,min_exp ); 49 50HVX_Vector out = hvx_vec_fast_sigmoid_f32 (v ); 51out = Q6_V_vmux_QVV (pred_max ,out ,one ); 52return Q6_V_vmux_QVV (pred_min ,out ,Q6_V_vzero ()); 53} 54 55static inline HVX_Vector hvx_vec_tanh_f32 (HVX_Vector x ) { 56// tanh(x) = 2 * sigmoid(2x) - 1 57HVX_Vector two = hvx_vec_splat_f32 (2.0f ); 58HVX_Vector one = hvx_vec_splat_f32 (1.0f ); 59HVX_Vector x2 = Q6_Vqf32_vmpy_VsfVsf (x ,two ); 60 61HVX_Vector max_exp = hvx_vec_splat_f32 (87.f ); 62HVX_Vector min_exp = hvx_vec_splat_f32 (-87.f ); 63 64HVX_Vector sig2x = hvx_vec_fast_sigmoid_f32_guard (Q6_Vsf_equals_Vqf32 (x2 ),one ,max_exp ,min_exp ); 65 66HVX_Vector res = Q6_Vqf32_vmpy_VsfVsf (sig2x ,two ); 67res = Q6_Vqf32_vsub_Vqf32Vsf (res ,one ); 68return Q6_Vsf_equals_Vqf32 (res ); 69} 70 71#define hvx_sigmoid_loop_body (dst_type ,src_type ,vec_store ) \ 72 do { \ 73 dst_type * restrict vdst = (dst_type *) dst; \ 74 src_type * restrict vsrc = (src_type *) src; \ 75 \ 76 const HVX_Vector one = hvx_vec_splat_f32(1.f); \ 77 const HVX_Vector max_exp = hvx_vec_splat_f32(87.f); \ 78 const HVX_Vector min_exp = hvx_vec_splat_f32(-87.f); \ 79 \ 80 const uint32_t epv = 128 / sizeof(float); \ 81 const uint32_t nvec = n / epv; \ 82 const uint32_t nloe = n % epv; \ 83 \ 84 uint32_t i = 0; \ 85 \ 86 _Pragma("unroll(4)") \ 87 for (; i < nvec; i++) { \ 88 vdst[i] = hvx_vec_fast_sigmoid_f32_guard(vsrc[i], one, max_exp, min_exp); \ 89 } \ 90 if (nloe) { \ 91 HVX_Vector tmp = hvx_vec_fast_sigmoid_f32_guard(vsrc[i], one, max_exp, min_exp); \ 92 vec_store((void *) &vdst[i], nloe * sizeof(float), tmp); \ 93 } \ 94 } while(0) 95 96#define hvx_tanh_loop_body (dst_type ,src_type ,vec_store ) \ 97 do { \ 98 dst_type * restrict vdst = (dst_type *) dst; \ 99 src_type * restrict vsrc = (src_type *) src; \ 100 \ 101 const uint32_t epv = 128 / sizeof(float); \ 102 const uint32_t nvec = n / epv; \ 103 const uint32_t nloe = n % epv; \ 104 \ 105 uint32_t i = 0; \ 106 \ 107 _Pragma("unroll(4)") \ 108 for (; i < nvec; i++) { \ 109 vdst[i] = hvx_vec_tanh_f32(vsrc[i]); \ 110 } \ 111 if (nloe) { \ 112 HVX_Vector tmp = hvx_vec_tanh_f32(vsrc[i]); \ 113 vec_store((void *) &vdst[i], nloe * sizeof(float), tmp); \ 114 } \ 115 } while(0) 116 117static inline void hvx_sigmoid_f32_aa (uint8_t * restrictdst ,const uint8_t * restrictsrc ,uint32_t n ) { 118assert ((unsigned long )dst %128 == 0 ); 119assert ((unsigned long )src %128 == 0 ); 120hvx_sigmoid_loop_body (HVX_Vector ,HVX_Vector ,hvx_vec_store_a ); 121} 122 123static inline void hvx_sigmoid_f32_au (uint8_t * restrictdst ,const uint8_t * restrictsrc ,uint32_t n ) { 124assert ((unsigned long )dst %128 == 0 ); 125hvx_sigmoid_loop_body (HVX_Vector ,HVX_UVector ,hvx_vec_store_a ); 126} 127 128static inline void hvx_sigmoid_f32_ua (uint8_t * restrictdst ,const uint8_t * restrictsrc ,uint32_t n ) { 129assert ((unsigned long )src %128 == 0 ); 130hvx_sigmoid_loop_body (HVX_UVector ,HVX_Vector ,hvx_vec_store_u ); 131} 132 133static inline void hvx_sigmoid_f32_uu (uint8_t * restrictdst ,const uint8_t * restrictsrc ,uint32_t n ) { 134hvx_sigmoid_loop_body (HVX_UVector ,HVX_UVector ,hvx_vec_store_u ); 135} 136 137static inline void hvx_tanh_f32_aa (uint8_t * restrictdst ,const uint8_t * restrictsrc ,uint32_t n ) { 138assert ((unsigned long )dst %128 == 0 ); 139assert ((unsigned long )src %128 == 0 ); 140hvx_tanh_loop_body (HVX_Vector ,HVX_Vector ,hvx_vec_store_a ); 141} 142 143static inline HVX_Vector hvx_vec_fast_sigmoid_f16 (HVX_Vector x_v ) { 144const HVX_Vector v_one = hvx_vec_splat_f16 (1.0f ); 145const HVX_Vector v_neg_log2e = hvx_vec_splat_f16 (- EXP_LOG2E_F ); 146const HVX_Vector em_mask = Q6_Vh_vsplat_R (0x7FFF ); 147 148// Compute absolute value of x_v 149HVX_Vector abs_x = Q6_V_vand_VV (x_v ,em_mask ); 150 151// Compute u = -abs_x * log2(e) <= 0. 152HVX_Vector u = hvx_vec_mul_f16_f16 (abs_x ,v_neg_log2e ); 153 154// Clamp input to prevent underflow in exp2 155const HVX_Vector v_clamp_min = hvx_vec_splat_f16 (-24.0f ); 156u = Q6_Vhf_vmax_VhfVhf (v_clamp_min ,u ); 157 158HVX_Vector exp_val = hvx_vec_exp2_f16 (u ); 159HVX_Vector denom = hvx_vec_add_f16_f16 (v_one ,exp_val ); 160HVX_Vector sig_abs = hvx_vec_inverse_f16 (denom ); 161 162// check if x_v < 0 (using integer comparison on absolute value) 163HVX_VectorPred is_neg = Q6_Q_vcmp_gt_VhVh (abs_x ,x_v ); 164 165// If x_v < 0, return 1.0f - sig_abs 166HVX_Vector sig_neg = Q6_Vhf_equals_Vqf16 (Q6_Vqf16_vsub_VhfVhf (v_one ,sig_abs )); 167return Q6_V_vmux_QVV (is_neg ,sig_neg ,sig_abs ); 168} 169 170static inline HVX_Vector hvx_vec_tanh_f16 (HVX_Vector x ) { 171// tanh(x) = 2 * sigmoid(2x) - 1 172const HVX_Vector v_two = hvx_vec_splat_f16 (2.0f ); 173 174HVX_Vector x2 = hvx_vec_mul_f16_f16 (x ,v_two ); 175HVX_Vector sig2x = hvx_vec_fast_sigmoid_f16 (x2 ); 176 177const HVX_Vector v_neg_one = hvx_vec_splat_f16 (-1.0f ); 178return hvx_vec_add_f16_f16 (hvx_vec_mul_f16_f16 (sig2x ,v_two ),v_neg_one ); 179} 180 181#endif /* HVX_SIGMOID_H */