char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
f027c4f1b
char/aliceai-t5-moe
1#ifndef HVX_NORM_H 2#define HVX_NORM_H 3 4#include <stdint.h> 5#include "hvx-base.h" 6#include "hvx-reduce.h" 7#include "hvx-inverse.h" 8#include "hvx-sqrt.h" 9#include "hvx-repl.h" 10 11static inline void hvx_fast_rms_norm_f32 (const uint8_t * restrictsrc , 12uint8_t * restrictdst , 13const int num_elems , 14float epsilon ) { 15 16const HVX_Vector * restrictv_src = (HVX_Vector * )src ; 17HVX_Vector * restrictv_dst = (HVX_Vector * )dst ; 18 19const int nvec = num_elems /VLEN_FP32 ;// number of full vectors 20const int nloe = num_elems %VLEN_FP32 ;// leftover elements 21 22// Compute sum of squares for full vectors 23HVX_Vector sum_v = Q6_V_vsplat_R (0x00000000 ); 24HVX_Vector epsilon_v = hvx_vec_splat_f32 (epsilon ); 25 26#pragma unroll(4) 27for (int i = 0 ;i < nvec ;i ++ ) { 28HVX_Vector v1 = v_src [i ]; 29HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,v1 ); 30sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,v2 ); 31 } 32 33// Handle tail elements using vectorized ops with masking 34if (nloe > 0 ) { 35HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * 4 ); 36HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 37HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,v1 ); 38sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,v2 ); 39 } 40 41// Reduce HVX sum 42sum_v = hvx_vec_reduce_sum_f32 (Q6_Vsf_equals_Vqf32 (sum_v )); 43 44HVX_Vector t_v = hvx_vec_splat_f32 ((float )num_elems ); 45HVX_Vector denom_v = hvx_vec_inverse_f32 (t_v ); 46HVX_Vector mean_v = Q6_Vqf32_vmpy_VsfVsf (sum_v ,denom_v ); 47HVX_Vector mean_epsilon_v = Q6_Vqf32_vadd_Vqf32Vsf (mean_v ,epsilon_v ); 48 49// Scale full vectors 50HVX_Vector scale_v = hvx_vec_rsqrt_f32 (Q6_Vsf_equals_Vqf32 (mean_epsilon_v )); 51 52#pragma unroll(4) 53for (int i = 0 ;i < nvec ;i ++ ) { 54HVX_Vector v1 = v_src [i ]; 55HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,scale_v ); 56v_dst [i ]= Q6_Vsf_equals_Vqf32 (v2 ); 57 } 58 59// Handle tail elements using vectorized ops with masking 60if (nloe > 0 ) { 61HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * 4 ); 62HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 63HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,scale_v ); 64HVX_Vector result = Q6_Vsf_equals_Vqf32 (v2 ); 65 66// Store with masking to avoid overwriting memory beyond the tensor 67hvx_vec_store_a (& v_dst [nvec ],nloe * 4 ,result ); 68 } 69} 70 71static inline void hvx_fast_rms_norm_mul_f32 (const uint8_t * restrictsrc , 72const uint8_t * restrictweight , 73uint8_t * restrictdst , 74const int num_elems , 75float epsilon ) { 76const HVX_Vector * restrictv_src = (const HVX_Vector * )src ; 77const HVX_Vector * restrictv_weight = (const HVX_Vector * )weight ; 78HVX_Vector * restrictv_dst = (HVX_Vector * )dst ; 79 80const int nvec = num_elems /VLEN_FP32 ;// number of full vectors 81const int nloe = num_elems %VLEN_FP32 ;// leftover elements 82 83// Compute sum of squares for full vectors 84HVX_Vector sum_v = Q6_V_vsplat_R (0x00000000 ); 85HVX_Vector epsilon_v = hvx_vec_splat_f32 (epsilon ); 86 87#pragma unroll(4) 88for (int i = 0 ;i < nvec ;i ++ ) { 89HVX_Vector v1 = v_src [i ]; 90HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,v1 ); 91sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,v2 ); 92 } 93 94// Handle tail elements using vectorized ops with masking 95if (nloe > 0 ) { 96HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * 4 ); 97HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 98HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,v1 ); 99sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,v2 ); 100 } 101 102// Reduce HVX sum 103sum_v = hvx_vec_reduce_sum_f32 (Q6_Vsf_equals_Vqf32 (sum_v )); 104 105HVX_Vector t_v = hvx_vec_splat_f32 ((float )num_elems ); 106HVX_Vector denom_v = hvx_vec_inverse_f32 (t_v ); 107HVX_Vector mean_v = Q6_Vqf32_vmpy_VsfVsf (sum_v ,denom_v ); 108HVX_Vector mean_epsilon_v = Q6_Vqf32_vadd_Vqf32Vsf (mean_v ,epsilon_v ); 109 110// Scale and multiply 111HVX_Vector scale_v = hvx_vec_rsqrt_f32 (Q6_Vsf_equals_Vqf32 (mean_epsilon_v )); 112 113#pragma unroll(4) 114for (int i = 0 ;i < nvec ;i ++ ) { 115HVX_Vector v1 = v_src [i ]; 116HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,scale_v ); 117HVX_Vector v3 = Q6_Vsf_equals_Vqf32 (v2 ); 118HVX_Vector result = Q6_Vqf32_vmpy_VsfVsf (v3 ,v_weight [i ]); 119v_dst [i ]= Q6_Vsf_equals_Vqf32 (result ); 120 } 121 122// Handle tail elements using vectorized ops with masking 123if (nloe > 0 ) { 124HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * 4 ); 125HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 126HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,scale_v ); 127HVX_Vector v3 = Q6_Vsf_equals_Vqf32 (v2 ); 128HVX_Vector result = Q6_Vqf32_vmpy_VsfVsf (v3 ,v_weight [nvec ]); 129HVX_Vector res_v = Q6_Vsf_equals_Vqf32 (result ); 130 131// Store with masking to avoid overwriting memory beyond the tensor 132hvx_vec_store_a (& v_dst [nvec ],nloe * 4 ,res_v ); 133 } 134} 135 136static inline void hvx_fast_norm_f32 (const uint8_t * restrictsrc , 137uint8_t * restrictdst , 138const int num_elems , 139float epsilon ) { 140 141const HVX_Vector * restrictv_src = (HVX_Vector * )src ; 142HVX_Vector * restrictv_dst = (HVX_Vector * )dst ; 143 144const int nvec = num_elems /VLEN_FP32 ;// number of full vectors 145const int nloe = num_elems %VLEN_FP32 ;// leftover elements 146 147// Compute sum of squares and sum of values for full vectors 148HVX_Vector sum_sq_v = Q6_V_vsplat_R (0x00000000 ); 149HVX_Vector sum_x_v = Q6_V_vsplat_R (0x00000000 ); 150HVX_Vector epsilon_v = hvx_vec_splat_f32 (epsilon ); 151 152#pragma unroll(4) 153for (int i = 0 ;i < nvec ;i ++ ) { 154HVX_Vector v1 = v_src [i ]; 155HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,v1 ); 156sum_sq_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_sq_v ,v2 ); 157sum_x_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_x_v ,Q6_Vqf32_vadd_VsfVsf (v1 ,Q6_V_vzero ())); 158 } 159 160// Handle tail elements using vectorized ops with masking 161if (nloe > 0 ) { 162HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * 4 ); 163HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 164HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,v1 ); 165sum_sq_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_sq_v ,v2 ); 166sum_x_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_x_v ,Q6_Vqf32_vadd_VsfVsf (v1 ,Q6_V_vzero ())); 167 } 168 169// Reduce HVX sums 170sum_sq_v = hvx_vec_reduce_sum_f32 (Q6_Vsf_equals_Vqf32 (sum_sq_v )); 171sum_x_v = hvx_vec_reduce_sum_f32 (Q6_Vsf_equals_Vqf32 (sum_x_v )); 172 173HVX_Vector t_v = hvx_vec_splat_f32 ((float )num_elems ); 174HVX_Vector denom_v = hvx_vec_inverse_f32 (t_v ); 175HVX_Vector mean_sq_v = Q6_Vqf32_vmpy_VsfVsf (sum_sq_v ,denom_v ); 176HVX_Vector mean_x_v = Q6_Vqf32_vmpy_VsfVsf (sum_x_v ,denom_v ); 177HVX_Vector mean_x_sq_v = Q6_Vqf32_vmpy_VsfVsf (Q6_Vsf_equals_Vqf32 (mean_x_v ),Q6_Vsf_equals_Vqf32 (mean_x_v )); 178HVX_Vector var_v = Q6_Vqf32_vsub_Vqf32Vqf32 (mean_sq_v ,mean_x_sq_v ); 179HVX_Vector var_epsilon_v = Q6_Vqf32_vadd_Vqf32Vsf (var_v ,epsilon_v ); 180 181// scale = rsqrt(variance + epsilon), mean_x broadcast for subtraction 182HVX_Vector scale_v = hvx_vec_rsqrt_f32 (Q6_Vsf_equals_Vqf32 (var_epsilon_v )); 183HVX_Vector mean_x_b = hvx_vec_repl_f32 (Q6_Vsf_equals_Vqf32 (mean_x_v )); 184 185#pragma unroll(4) 186for (int i = 0 ;i < nvec ;i ++ ) { 187HVX_Vector v1 = v_src [i ]; 188HVX_Vector v2 = Q6_Vqf32_vsub_VsfVsf (v1 ,mean_x_b ); 189HVX_Vector v3 = Q6_Vqf32_vmpy_VsfVsf (Q6_Vsf_equals_Vqf32 (v2 ),scale_v ); 190v_dst [i ]= Q6_Vsf_equals_Vqf32 (v3 ); 191 } 192 193// Handle tail elements using vectorized ops with masking 194if (nloe > 0 ) { 195HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * 4 ); 196HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 197HVX_Vector v2 = Q6_Vqf32_vsub_VsfVsf (v1 ,mean_x_b ); 198HVX_Vector v3 = Q6_Vqf32_vmpy_VsfVsf (Q6_Vsf_equals_Vqf32 (v2 ),scale_v ); 199HVX_Vector result = Q6_Vsf_equals_Vqf32 (v3 ); 200 201// Store with masking to avoid overwriting memory beyond the tensor 202hvx_vec_store_a (& v_dst [nvec ],nloe * 4 ,result ); 203 } 204} 205 206static inline void hvx_fast_l2_norm_f32 (const uint8_t * restrictsrc , 207uint8_t * restrictdst , 208const int num_elems , 209float epsilon ) { 210 211const HVX_Vector * restrictv_src = (HVX_Vector * )src ; 212HVX_Vector * restrictv_dst = (HVX_Vector * )dst ; 213 214HVX_Vector sum_v = hvx_vec_splat_f32 (0.0f ); 215 216const int nvec = num_elems /VLEN_FP32 ; 217const int nloe = num_elems %VLEN_FP32 ; 218 219#pragma unroll(4) 220for (int i = 0 ;i < nvec ;i ++ ) { 221HVX_Vector v1 = v_src [i ]; 222HVX_Vector sq = Q6_Vqf32_vmpy_VsfVsf (v1 ,v1 ); 223sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,sq ); 224 } 225 226// Include tail elements in the sum-of-squares using a predicate mask 227if (nloe > 0 ) { 228HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * 4 ); 229HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 230HVX_Vector sq = Q6_Vqf32_vmpy_VsfVsf (v1 ,v1 ); 231sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,sq ); 232 } 233 234// Compute scale = 1/fmax(sqrt(sum), epsilon) entirely in HVX registers. 235// hvx_vec_rsqrt_f32 + hvx_vec_inverse_f32 avoids scalar extraction. 236HVX_Vector sum_sf = hvx_vec_reduce_sum_f32 (Q6_Vsf_equals_Vqf32 (sum_v )); 237HVX_Vector rsqrt_v = hvx_vec_rsqrt_f32 (sum_sf );// 1/sqrt(sum) 238HVX_Vector sqrt_v = hvx_vec_inverse_f32 (rsqrt_v );// sqrt(sum) 239HVX_Vector epsilon_v = hvx_vec_splat_f32 (epsilon ); 240HVX_Vector denom_v = Q6_Vsf_vmax_VsfVsf (sqrt_v ,epsilon_v );// fmax(sqrt(sum), epsilon) 241HVX_Vector scale_v = hvx_vec_inverse_f32 (denom_v );// 1/fmax(sqrt(sum), epsilon) 242 243#pragma unroll(4) 244for (int i = 0 ;i < nvec ;i ++ ) { 245HVX_Vector v1 = v_src [i ]; 246v_dst [i ]= Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (v1 ,scale_v )); 247 } 248 249if (nloe > 0 ) { 250HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * 4 ); 251HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 252HVX_Vector result = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (v1 ,scale_v )); 253hvx_vec_store_a (& v_dst [nvec ],nloe * 4 ,result ); 254 } 255} 256 257// F16 norm kernels: reduce and scale in f32 (via promote/narrow), matching the 258// precision-preserving pattern used by the flash-attn f16 kernels. 259 260static inline void hvx_fast_rms_norm_f16 (const uint8_t * restrictsrc , 261uint8_t * restrictdst , 262const int num_elems , 263float epsilon ) { 264 265const HVX_Vector * restrictv_src = (HVX_Vector * )src ; 266HVX_Vector * restrictv_dst = (HVX_Vector * )dst ; 267 268const int nvec = num_elems /VLEN_FP16 ;// number of full f16 vectors 269const int nloe = num_elems %VLEN_FP16 ;// leftover elements 270 271HVX_Vector sum_v = Q6_V_vsplat_R (0x00000000 ); 272HVX_Vector epsilon_v = hvx_vec_splat_f32 (epsilon ); 273 274#pragma unroll(4) 275for (int i = 0 ;i < nvec ;i ++ ) { 276HVX_VectorPair p = hvx_vec_f16_to_f32 (v_src [i ]); 277HVX_Vector p0 = Q6_V_lo_W (p ); 278HVX_Vector p1 = Q6_V_hi_W (p ); 279sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,Q6_Vqf32_vmpy_VsfVsf (p0 ,p0 )); 280sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,Q6_Vqf32_vmpy_VsfVsf (p1 ,p1 )); 281 } 282 283if (nloe > 0 ) { 284HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * SIZEOF_FP16 ); 285HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 286HVX_VectorPair p = hvx_vec_f16_to_f32 (v1 ); 287HVX_Vector p0 = Q6_V_lo_W (p ); 288HVX_Vector p1 = Q6_V_hi_W (p ); 289sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,Q6_Vqf32_vmpy_VsfVsf (p0 ,p0 )); 290sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,Q6_Vqf32_vmpy_VsfVsf (p1 ,p1 )); 291 } 292 293sum_v = hvx_vec_reduce_sum_f32 (Q6_Vsf_equals_Vqf32 (sum_v )); 294 295HVX_Vector t_v = hvx_vec_splat_f32 ((float )num_elems ); 296HVX_Vector denom_v = hvx_vec_inverse_f32 (t_v ); 297HVX_Vector mean_v = Q6_Vqf32_vmpy_VsfVsf (sum_v ,denom_v ); 298HVX_Vector mean_epsilon_v = Q6_Vqf32_vadd_Vqf32Vsf (mean_v ,epsilon_v ); 299 300HVX_Vector scale_v = hvx_vec_rsqrt_f32 (Q6_Vsf_equals_Vqf32 (mean_epsilon_v )); 301 302#pragma unroll(4) 303for (int i = 0 ;i < nvec ;i ++ ) { 304HVX_VectorPair p = hvx_vec_f16_to_f32 (v_src [i ]); 305HVX_Vector r0 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_V_lo_W (p ),scale_v )); 306HVX_Vector r1 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_V_hi_W (p ),scale_v )); 307v_dst [i ]= hvx_vec_f32_to_f16 (r0 ,r1 ); 308 } 309 310if (nloe > 0 ) { 311HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * SIZEOF_FP16 ); 312HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 313HVX_VectorPair p = hvx_vec_f16_to_f32 (v1 ); 314HVX_Vector r0 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_V_lo_W (p ),scale_v )); 315HVX_Vector r1 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_V_hi_W (p ),scale_v )); 316HVX_Vector result = hvx_vec_f32_to_f16 (r0 ,r1 ); 317hvx_vec_store_a (& v_dst [nvec ],nloe * SIZEOF_FP16 ,result ); 318 } 319} 320 321static inline void hvx_fast_norm_f16 (const uint8_t * restrictsrc , 322uint8_t * restrictdst , 323const int num_elems , 324float epsilon ) { 325 326const HVX_Vector * restrictv_src = (HVX_Vector * )src ; 327HVX_Vector * restrictv_dst = (HVX_Vector * )dst ; 328 329const int nvec = num_elems /VLEN_FP16 ; 330const int nloe = num_elems %VLEN_FP16 ; 331 332HVX_Vector sum_sq_v = Q6_V_vsplat_R (0x00000000 ); 333HVX_Vector sum_x_v = Q6_V_vsplat_R (0x00000000 ); 334HVX_Vector epsilon_v = hvx_vec_splat_f32 (epsilon ); 335 336#pragma unroll(4) 337for (int i = 0 ;i < nvec ;i ++ ) { 338HVX_VectorPair p = hvx_vec_f16_to_f32 (v_src [i ]); 339HVX_Vector p0 = Q6_V_lo_W (p ); 340HVX_Vector p1 = Q6_V_hi_W (p ); 341sum_sq_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_sq_v ,Q6_Vqf32_vmpy_VsfVsf (p0 ,p0 )); 342sum_sq_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_sq_v ,Q6_Vqf32_vmpy_VsfVsf (p1 ,p1 )); 343sum_x_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_x_v ,Q6_Vqf32_vadd_VsfVsf (p0 ,Q6_V_vzero ())); 344sum_x_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_x_v ,Q6_Vqf32_vadd_VsfVsf (p1 ,Q6_V_vzero ())); 345 } 346 347if (nloe > 0 ) { 348HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * SIZEOF_FP16 ); 349HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 350HVX_VectorPair p = hvx_vec_f16_to_f32 (v1 ); 351HVX_Vector p0 = Q6_V_lo_W (p ); 352HVX_Vector p1 = Q6_V_hi_W (p ); 353sum_sq_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_sq_v ,Q6_Vqf32_vmpy_VsfVsf (p0 ,p0 )); 354sum_sq_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_sq_v ,Q6_Vqf32_vmpy_VsfVsf (p1 ,p1 )); 355sum_x_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_x_v ,Q6_Vqf32_vadd_VsfVsf (p0 ,Q6_V_vzero ())); 356sum_x_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_x_v ,Q6_Vqf32_vadd_VsfVsf (p1 ,Q6_V_vzero ())); 357 } 358 359sum_sq_v = hvx_vec_reduce_sum_f32 (Q6_Vsf_equals_Vqf32 (sum_sq_v )); 360sum_x_v = hvx_vec_reduce_sum_f32 (Q6_Vsf_equals_Vqf32 (sum_x_v )); 361 362HVX_Vector t_v = hvx_vec_splat_f32 ((float )num_elems ); 363HVX_Vector denom_v = hvx_vec_inverse_f32 (t_v ); 364HVX_Vector mean_sq_v = Q6_Vqf32_vmpy_VsfVsf (sum_sq_v ,denom_v ); 365HVX_Vector mean_x_v = Q6_Vqf32_vmpy_VsfVsf (sum_x_v ,denom_v ); 366HVX_Vector mean_x_sq_v = Q6_Vqf32_vmpy_VsfVsf (Q6_Vsf_equals_Vqf32 (mean_x_v ),Q6_Vsf_equals_Vqf32 (mean_x_v )); 367HVX_Vector var_v = Q6_Vqf32_vsub_Vqf32Vqf32 (mean_sq_v ,mean_x_sq_v ); 368HVX_Vector var_epsilon_v = Q6_Vqf32_vadd_Vqf32Vsf (var_v ,epsilon_v ); 369 370HVX_Vector scale_v = hvx_vec_rsqrt_f32 (Q6_Vsf_equals_Vqf32 (var_epsilon_v )); 371HVX_Vector mean_x_b = hvx_vec_repl_f32 (Q6_Vsf_equals_Vqf32 (mean_x_v )); 372 373#pragma unroll(4) 374for (int i = 0 ;i < nvec ;i ++ ) { 375HVX_VectorPair p = hvx_vec_f16_to_f32 (v_src [i ]); 376HVX_Vector d0 = Q6_Vqf32_vsub_VsfVsf (Q6_V_lo_W (p ),mean_x_b ); 377HVX_Vector d1 = Q6_Vqf32_vsub_VsfVsf (Q6_V_hi_W (p ),mean_x_b ); 378HVX_Vector r0 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_Vsf_equals_Vqf32 (d0 ),scale_v )); 379HVX_Vector r1 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_Vsf_equals_Vqf32 (d1 ),scale_v )); 380v_dst [i ]= hvx_vec_f32_to_f16 (r0 ,r1 ); 381 } 382 383if (nloe > 0 ) { 384HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * SIZEOF_FP16 ); 385HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 386HVX_VectorPair p = hvx_vec_f16_to_f32 (v1 ); 387HVX_Vector d0 = Q6_Vqf32_vsub_VsfVsf (Q6_V_lo_W (p ),mean_x_b ); 388HVX_Vector d1 = Q6_Vqf32_vsub_VsfVsf (Q6_V_hi_W (p ),mean_x_b ); 389HVX_Vector r0 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_Vsf_equals_Vqf32 (d0 ),scale_v )); 390HVX_Vector r1 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_Vsf_equals_Vqf32 (d1 ),scale_v )); 391HVX_Vector result = hvx_vec_f32_to_f16 (r0 ,r1 ); 392hvx_vec_store_a (& v_dst [nvec ],nloe * SIZEOF_FP16 ,result ); 393 } 394} 395 396static inline void hvx_fast_l2_norm_f16 (const uint8_t * restrictsrc , 397uint8_t * restrictdst , 398const int num_elems , 399float epsilon ) { 400 401const HVX_Vector * restrictv_src = (HVX_Vector * )src ; 402HVX_Vector * restrictv_dst = (HVX_Vector * )dst ; 403 404const int nvec = num_elems /VLEN_FP16 ; 405const int nloe = num_elems %VLEN_FP16 ; 406 407HVX_Vector sum_v = hvx_vec_splat_f32 (0.0f ); 408 409#pragma unroll(4) 410for (int i = 0 ;i < nvec ;i ++ ) { 411HVX_VectorPair p = hvx_vec_f16_to_f32 (v_src [i ]); 412HVX_Vector p0 = Q6_V_lo_W (p ); 413HVX_Vector p1 = Q6_V_hi_W (p ); 414sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,Q6_Vqf32_vmpy_VsfVsf (p0 ,p0 )); 415sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,Q6_Vqf32_vmpy_VsfVsf (p1 ,p1 )); 416 } 417 418if (nloe > 0 ) { 419HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * SIZEOF_FP16 ); 420HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 421HVX_VectorPair p = hvx_vec_f16_to_f32 (v1 ); 422HVX_Vector p0 = Q6_V_lo_W (p ); 423HVX_Vector p1 = Q6_V_hi_W (p ); 424sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,Q6_Vqf32_vmpy_VsfVsf (p0 ,p0 )); 425sum_v = Q6_Vqf32_vadd_Vqf32Vqf32 (sum_v ,Q6_Vqf32_vmpy_VsfVsf (p1 ,p1 )); 426 } 427 428HVX_Vector sum_sf = hvx_vec_reduce_sum_f32 (Q6_Vsf_equals_Vqf32 (sum_v )); 429HVX_Vector rsqrt_v = hvx_vec_rsqrt_f32 (sum_sf ); 430HVX_Vector sqrt_v = hvx_vec_inverse_f32 (rsqrt_v ); 431HVX_Vector epsilon_v = hvx_vec_splat_f32 (epsilon ); 432HVX_Vector denom_v = Q6_Vsf_vmax_VsfVsf (sqrt_v ,epsilon_v ); 433HVX_Vector scale_v = hvx_vec_inverse_f32 (denom_v ); 434 435#pragma unroll(4) 436for (int i = 0 ;i < nvec ;i ++ ) { 437HVX_VectorPair p = hvx_vec_f16_to_f32 (v_src [i ]); 438HVX_Vector r0 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_V_lo_W (p ),scale_v )); 439HVX_Vector r1 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_V_hi_W (p ),scale_v )); 440v_dst [i ]= hvx_vec_f32_to_f16 (r0 ,r1 ); 441 } 442 443if (nloe > 0 ) { 444HVX_VectorPred bmask = Q6_Q_vsetq_R (nloe * SIZEOF_FP16 ); 445HVX_Vector v1 = Q6_V_vand_QV (bmask ,v_src [nvec ]); 446HVX_VectorPair p = hvx_vec_f16_to_f32 (v1 ); 447HVX_Vector r0 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_V_lo_W (p ),scale_v )); 448HVX_Vector r1 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vmpy_VsfVsf (Q6_V_hi_W (p ),scale_v )); 449HVX_Vector result = hvx_vec_f32_to_f16 (r0 ,r1 ); 450hvx_vec_store_a (& v_dst [nvec ],nloe * SIZEOF_FP16 ,result ); 451 } 452} 453 454#endif // HVX_NORM_H