char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
eafe15a5e
char/aliceai-t5-moe
1#pragma clang diagnostic ignored "-Wunused-variable" 2#pragma clang diagnostic ignored "-Wunused-function" 3#pragma clang diagnostic ignored "-Wunused-but-set-variable" 4 5#include <HAP_farf.h> 6#include <HAP_perf.h> 7 8#include <math.h> 9#include <string.h> 10#include <stdlib.h> 11 12#include "hex-dma.h" 13#include "hvx-utils.h" 14#include "hex-fastdiv.h" 15 16#define GGML_COMMON_DECL_C 17#include "ggml-common.h" 18#include "htp-ctx.h" 19#include "htp-ops.h" 20#include "htp-tensor.h" 21#include "rope-ops.h" 22 23// Redefined the rope type constants as we can't include ggml.h 24#define HTP_ROPE_TYPE_NORMAL 0 25#define HTP_ROPE_TYPE_NEOX 2 26#define HTP_ROPE_TYPE_MROPE 8 27#define HTP_ROPE_TYPE_VISION 24 28#define HTP_ROPE_TYPE_IMROPE 40 29 30#define htp_rope_preamble \ 31 const uint32_t ne00 = src0->ne[0]; \ 32 const uint32_t ne01 = src0->ne[1]; \ 33 const uint32_t ne02 = src0->ne[2]; \ 34 const uint32_t ne03 = src0->ne[3]; \ 35 \ 36 const uint32_t ne0 = dst->ne[0]; \ 37 const uint32_t ne1 = dst->ne[1]; \ 38 const uint32_t ne2 = dst->ne[2]; \ 39 const uint32_t ne3 = dst->ne[3]; \ 40 \ 41 const uint32_t nb00 = src0->nb[0]; \ 42 const uint32_t nb01 = src0->nb[1]; \ 43 const uint32_t nb02 = src0->nb[2]; \ 44 const uint32_t nb03 = src0->nb[3]; \ 45 \ 46 const uint32_t nb0 = dst->nb[0]; \ 47 const uint32_t nb1 = dst->nb[1]; \ 48 const uint32_t nb2 = dst->nb[2]; \ 49 const uint32_t nb3 = dst->nb[3]; 50 51struct htp_rope_context { 52int32_t n_dims ; 53int32_t n_offs ; 54int32_t mode ; 55int32_t n_ctx_orig ; 56int32_t sections [4 ]; 57 58float freq_base ; 59float freq_scale ; 60float ext_factor ; 61float attn_factor ; 62float beta_fast ; 63float beta_slow ; 64float theta_scale ; 65float theta_scale_32 ; 66float theta_powers [32 ]; 67float corr_dims [2 ]; 68 69uint32_t src0_nrows_per_thread ; 70 71struct htp_ops_context * octx ; 72 73uint8_t * vtcm_base ; 74size_t spad_per_thread ; 75size_t theta_cache_offset ; 76 77size_t src0_row_size ; 78size_t src0_row_stride ; 79size_t dst_row_size ; 80size_t dst_row_stride ; 81size_t src0_row_size_aligned ; 82uint32_t src0_nrows ; 83uint32_t row_start ; 84uint32_t nrows ; 85 86struct fastdiv_values div_ne2_ne1 ; 87struct fastdiv_values div_ne1 ; 88}; 89 90static float rope_yarn_ramp (const float low ,const float high ,const int i0 ) { 91const float y = (i0 /2 - low ) /MAX (0.001f ,high - low ); 92 93return (1 - MIN (1 ,MAX (0 ,y ))); 94} 95 96// Compute one (cos, sin) pair into cache[i0], cache[i0+1] applying YaRN scaling. 97static inline void rope_yarn_one (float theta ,float freq_scale ,float * corr_dims , 98uint32_t i0 ,float ext_factor ,float mscale , 99float * cache ) { 100float theta_extrap = theta ; 101 102// Get n-d rotational scaling corrected for extrapolation 103float theta_interp = freq_scale * theta_extrap ; 104float theta_final = theta_interp ; 105float mscale_final = mscale ; 106 107if (ext_factor != 0.0f ) { 108float ramp_mix = rope_yarn_ramp (corr_dims [0 ],corr_dims [1 ],i0 )* ext_factor ; 109theta_final = theta_interp * (1 - ramp_mix )+ theta_extrap * ramp_mix ; 110 111// Get n-d magnitude scaling corrected for interpolation 112mscale_final *=1.0f + 0.1f * logf (1.0f /freq_scale ); 113 } 114 115const uint32_t b = i0 /64 ; 116const uint32_t k = (i0 %64 ) /2 ; 117cache [b * 64 + k ]= cosf (theta_final )* mscale_final ; 118cache [b * 64 + 32 + k ]= sinf (theta_final )* mscale_final ; 119} 120 121// 32 thetas -> 32 deinterleaved pairs [cos[32] | sin[32]] at cache[i0]. 122static inline void rope_cache_hvx_32 (float * cache ,uint32_t i0 , 123HVX_Vector v_theta , 124const float * freq_factors , 125HVX_Vector v_freq_scale , 126HVX_Vector v_mscale ) { 127if (freq_factors ) { 128HVX_Vector v_ff = hvx_vmemu (freq_factors + i0 /2 ); 129v_theta = hvx_vec_mul_f32_f32 (v_theta ,hvx_vec_inverse_f32 (v_ff )); 130 } 131 132HVX_Vector v_theta_final = hvx_vec_mul_f32_f32 (v_theta ,v_freq_scale ); 133HVX_Vector vcos ; 134HVX_Vector vsin ; 135hvx_vec_sincos_f32 (v_theta_final ,& vcos ,& vsin ); 136vcos = hvx_vec_mul_f32_f32 (vcos ,v_mscale ); 137vsin = hvx_vec_mul_f32_f32 (vsin ,v_mscale ); 138 139if (((uintptr_t ) (cache + i0 )) %128 == 0 ) { 140hvx_vmem (cache + i0 + 0 )= vcos ; 141hvx_vmem (cache + i0 + 32 )= vsin ; 142 }else { 143hvx_vec_store_u (cache + i0 + 0 ,32 * sizeof (float ),vcos ); 144hvx_vec_store_u (cache + i0 + 32 ,32 * sizeof (float ),vsin ); 145 } 146} 147 148static __attribute__((noinline ))void rope_cache_init (const float theta_base , 149const float freq_scale , 150const float * freq_factors , 151float * corr_dims , 152const uint32_t n_cache , 153const float ext_factor , 154const float mscale , 155float * cache , 156const float theta_scale , 157const float * theta_powers , 158const float theta_scale_32 ) { 159// ref: https://github.com/jquesnelle/yarn/blob/master/scaled_rope/LlamaYaRNScaledRotaryEmbedding.py 160if (ext_factor == 0.0f ) { 161// Fast path: fully vectorized 162// We process 32 pairs (64 elements) per iteration. 163const uint32_t n_blocks = n_cache /64 ; 164 165HVX_Vector v_theta_powers = hvx_vmemu (theta_powers ); 166HVX_Vector v_freq_scale = hvx_vec_splat_f32 (freq_scale ); 167HVX_Vector v_mscale = hvx_vec_splat_f32 (mscale ); 168 169float theta_block = theta_base ; 170 171for (uint32_t b = 0 ;b < n_blocks ;b ++ ) { 172uint32_t i0 = b * 64 ; 173HVX_Vector v_theta_base = hvx_vec_splat_f32 (theta_block ); 174HVX_Vector v_theta = hvx_vec_mul_f32_f32 (v_theta_base ,v_theta_powers ); 175rope_cache_hvx_32 (cache ,i0 ,v_theta ,freq_factors ,v_freq_scale ,v_mscale ); 176theta_block *=theta_scale_32 ; 177 } 178 179// Leftovers 180float theta = theta_block ; 181for (uint32_t i0 = n_blocks * 64 ;i0 < n_cache ;i0 += 2 ) { 182const float ff = freq_factors ?freq_factors [i0 /2 ] :1.0f ; 183rope_yarn_one (theta /ff ,freq_scale ,corr_dims ,i0 ,ext_factor ,mscale ,cache ); 184theta *=theta_scale ; 185 } 186 }else { 187float theta = theta_base ; 188for (uint32_t i0 = 0 ;i0 < n_cache ;i0 += 2 ) { 189const float ff = freq_factors ?freq_factors [i0 /2 ] :1.0f ; 190rope_yarn_one (theta /ff ,freq_scale ,corr_dims ,i0 ,ext_factor ,mscale ,cache ); 191theta *=theta_scale ; 192 } 193 } 194} 195 196static inline float mrope_pick_theta (float theta_t ,float theta_h ,float theta_w ,float theta_e , 197int sector ,const int32_t sections [4 ],int sec_w ,int sec_e , 198bool is_imrope ) { 199if (is_imrope ) { 200if (sector %3 == 0 && sector < 3 * sections [0 ]) {return theta_t ; } 201else if (sector %3 == 1 && sector < 3 * sections [1 ]) {return theta_h ; } 202else if (sector %3 == 2 && sector < 3 * sections [2 ]) {return theta_w ; } 203else {return theta_e ; } 204 } 205if (sector < sections [0 ]) {return theta_t ; } 206else if (sector < sec_w ) {return theta_h ; } 207else if (sector < sec_e ) {return theta_w ; } 208else {return theta_e ; } 209} 210 211// lane j is 1 when (j % 3) == rem 212static const float __attribute__((aligned (128 )))mrope_mod3_eq0 [32 ]= { 2131 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 214}; 215static const float __attribute__((aligned (128 )))mrope_mod3_eq1 [32 ]= { 2160 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 217}; 218static const float __attribute__((aligned (128 )))mrope_mod3_eq2 [32 ]= { 2190 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 ,1 ,0 ,0 220}; 221 222static const float __attribute__((aligned (128 )))mrope_k_ramp [32 ]= { 2230 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 , 22416 ,17 ,18 ,19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 225}; 226 227static inline HVX_VectorPred mrope_mask_eq1 (const float * m ) { 228return Q6_Q_vcmp_gt_VsfVsf (hvx_vmemu (m ),Q6_V_vzero ()); 229} 230 231// IMROPE without wrap: theta[k] = pos[k % 3] * scale^k 232static inline HVX_Vector mrope_thetas_imrope_mod3 (float pos_t ,float pos_h ,float pos_w , 233uint32_t k0 ,HVX_Vector v_powers ,float scale_block ) { 234const int r = (int ) (k0 %3 ); 235const float * mt = (r == 0 ) ?mrope_mod3_eq0 : (r == 1 ) ?mrope_mod3_eq2 :mrope_mod3_eq1 ; 236const float * mh = (r == 0 ) ?mrope_mod3_eq1 : (r == 1 ) ?mrope_mod3_eq0 :mrope_mod3_eq2 ; 237 238HVX_Vector v = hvx_vec_splat_f32 (pos_w ); 239v = Q6_V_vmux_QVV (mrope_mask_eq1 (mh ),hvx_vec_splat_f32 (pos_h ),v ); 240v = Q6_V_vmux_QVV (mrope_mask_eq1 (mt ),hvx_vec_splat_f32 (pos_t ),v ); 241v = hvx_vec_mul_f32_f32 (v ,v_powers ); 242return hvx_vec_mul_f32_f32 (v ,hvx_vec_splat_f32 (scale_block )); 243} 244 245// Contiguous MROPE without wrap: theta[k] = pos[section(k)] * scale^k 246static inline HVX_Vector mrope_thetas_contig (float pos_t ,float pos_h ,float pos_w ,float pos_e , 247uint32_t k0 ,int s0 ,int sec_w ,int sec_e , 248HVX_Vector v_powers ,float scale_block ) { 249HVX_Vector v_k = hvx_vec_add_f32_f32 (hvx_vec_splat_f32 ((float )k0 ),hvx_vmemu (mrope_k_ramp )); 250HVX_VectorPred lt_s0 = Q6_Q_vcmp_gt_VsfVsf (hvx_vec_splat_f32 ((float )s0 ),v_k ); 251HVX_VectorPred lt_sw = Q6_Q_vcmp_gt_VsfVsf (hvx_vec_splat_f32 ((float )sec_w ),v_k ); 252HVX_VectorPred lt_se = Q6_Q_vcmp_gt_VsfVsf (hvx_vec_splat_f32 ((float )sec_e ),v_k ); 253 254HVX_Vector v = hvx_vec_splat_f32 (pos_e ); 255v = Q6_V_vmux_QVV (lt_se ,hvx_vec_splat_f32 (pos_w ),v ); 256v = Q6_V_vmux_QVV (lt_sw ,hvx_vec_splat_f32 (pos_h ),v ); 257v = Q6_V_vmux_QVV (lt_s0 ,hvx_vec_splat_f32 (pos_t ),v ); 258v = hvx_vec_mul_f32_f32 (v ,v_powers ); 259return hvx_vec_mul_f32_f32 (v ,hvx_vec_splat_f32 (scale_block )); 260} 261 262// pos_t/h/w/e: the four position ids for this sequence step (t=time, h=height, w=width, e=extra). 263// sections[4]: number of head dims assigned to each position component. 264static __attribute__((noinline ))void mrope_cache_init (const float pos_t , 265const float pos_h , 266const float pos_w , 267const float pos_e , 268const int32_t sections [4 ], 269const bool is_imrope , 270const bool indep_sects , 271const float freq_scale , 272const float * freq_factors , 273float * corr_dims , 274const uint32_t n_cache , 275const float ext_factor , 276const float mscale , 277float * cache , 278const float theta_scale , 279const float * theta_powers , 280const float theta_scale_32 ) { 281const int sect_dims = sections [0 ]+ sections [1 ]+ sections [2 ]+ sections [3 ]; 282const int sec_w = sections [0 ]+ sections [1 ]; 283const int sec_e = sec_w + sections [2 ]; 284const uint32_t n_pairs = n_cache /2 ; 285 286const bool no_wrap = (sect_dims > 0 )&& (n_pairs <= (uint32_t )sect_dims ); 287const bool imrope_mod3 = is_imrope && !indep_sects && no_wrap 288&& sections [0 ]> 0 && sections [1 ]> 0 && sections [2 ]> 0 289&& n_pairs <= (uint32_t ) (3 * sections [0 ]) 290&& n_pairs <= (uint32_t ) (3 * sections [1 ]) 291&& n_pairs <= (uint32_t ) (3 * sections [2 ]); 292const bool contig = !is_imrope && !indep_sects && no_wrap ; 293 294if (ext_factor == 0.0f && (imrope_mod3 || contig )) { 295HVX_Vector v_powers = hvx_vmemu (theta_powers ); 296HVX_Vector v_freq_scale = hvx_vec_splat_f32 (freq_scale ); 297HVX_Vector v_mscale = hvx_vec_splat_f32 (mscale ); 298float scale_block = 1.0f ; 299const uint32_t n_blocks = n_cache /64 ; 300 301for (uint32_t b = 0 ;b < n_blocks ;b ++ ) { 302const uint32_t i0 = b * 64 ; 303const uint32_t k0 = b * 32 ; 304HVX_Vector v_theta = imrope_mod3 305 ?mrope_thetas_imrope_mod3 (pos_t ,pos_h ,pos_w ,k0 ,v_powers ,scale_block ) 306 :mrope_thetas_contig (pos_t ,pos_h ,pos_w ,pos_e ,k0 ,sections [0 ],sec_w ,sec_e , 307v_powers ,scale_block ); 308rope_cache_hvx_32 (cache ,i0 ,v_theta ,freq_factors ,v_freq_scale ,v_mscale ); 309scale_block *=theta_scale_32 ; 310 } 311 312float theta_k = scale_block ; 313for (uint32_t k = n_blocks * 32 ;k < n_pairs ;k ++ ) { 314const uint32_t i0 = 2 * k ; 315const float pos = mrope_pick_theta (pos_t ,pos_h ,pos_w ,pos_e , 316 (int )k ,sections ,sec_w ,sec_e ,is_imrope ); 317const float ff = freq_factors ?freq_factors [k ] :1.0f ; 318rope_yarn_one (pos * theta_k /ff ,freq_scale ,corr_dims ,i0 ,ext_factor ,mscale ,cache ); 319theta_k *=theta_scale ; 320 } 321return ; 322 } 323 324float theta_t = pos_t ; 325float theta_h = pos_h ; 326float theta_w = pos_w ; 327float theta_e = pos_e ; 328 329const bool use_hvx = (ext_factor == 0.0f ); 330float __attribute__((aligned (128 )))thetas [32 ]; 331uint32_t n_thetas = 0 ; 332uint32_t block_i0 = 0 ; 333 334HVX_Vector v_freq_scale = hvx_vec_splat_f32 (freq_scale ); 335HVX_Vector v_mscale = hvx_vec_splat_f32 (mscale ); 336 337for (uint32_t i0 = 0 ;i0 < n_cache ;i0 += 2 ) { 338const int sector = (i0 /2 ) %sect_dims ; 339 340if (indep_sects ) { 341// Reset theta when crossing into a new section. 342if (sector == 0 ) {theta_t = pos_t ; } 343else if (sector == sections [0 ]) {theta_h = pos_h ; } 344else if (sector == sec_w ) {theta_w = pos_w ; } 345else if (sector == sec_e ) {theta_e = pos_e ; } 346 } 347 348const float theta = mrope_pick_theta (theta_t ,theta_h ,theta_w ,theta_e , 349sector ,sections ,sec_w ,sec_e ,is_imrope ); 350 351if (use_hvx ) { 352if (n_thetas == 0 ) { 353block_i0 = i0 ; 354 } 355thetas [n_thetas ++ ]= theta ; 356if (n_thetas == 32 ) { 357rope_cache_hvx_32 (cache ,block_i0 ,hvx_vmemu (thetas ),freq_factors ,v_freq_scale ,v_mscale ); 358n_thetas = 0 ; 359 } 360 }else { 361const float ff = freq_factors ?freq_factors [i0 /2 ] :1.0f ; 362rope_yarn_one (theta /ff ,freq_scale ,corr_dims ,i0 ,ext_factor ,mscale ,cache ); 363 } 364 365theta_t *=theta_scale ; 366theta_h *=theta_scale ; 367theta_w *=theta_scale ; 368theta_e *=theta_scale ; 369 } 370 371for (uint32_t k = 0 ;k < n_thetas ;k ++ ) { 372const uint32_t i0 = block_i0 + 2 * k ; 373const float ff = freq_factors ?freq_factors [i0 /2 ] :1.0f ; 374rope_yarn_one (thetas [k ] /ff ,freq_scale ,corr_dims ,i0 ,ext_factor ,mscale ,cache ); 375 } 376} 377 378#define M_PI 3.1415926535897932384626433 379 380static void rope_corr_dims (int n_dims , 381int n_ctx_orig , 382float freq_base , 383float beta_fast , 384float beta_slow , 385float * dims ) { 386float start = floorf (n_dims * logf (n_ctx_orig / (beta_fast * 2 * (float )M_PI )) / (2 * logf (freq_base ))); 387float end = ceilf (n_dims * logf (n_ctx_orig / (beta_slow * 2 * (float )M_PI )) / (2 * logf (freq_base ))); 388dims [0 ]= MAX (0 ,start ); 389dims [1 ]= MIN (n_dims - 1 ,end ); 390} 391 392static inline void hvx_rope_neox_mul (HVX_Vector v0 ,HVX_Vector v1 ,HVX_Vector vcos ,HVX_Vector vsin , 393HVX_Vector * o0 ,HVX_Vector * o1 ) { 394HVX_Vector vx0_c = Q6_Vqf32_vmpy_VsfVsf (v0 ,vcos ); 395HVX_Vector vx0_s = Q6_Vqf32_vmpy_VsfVsf (v0 ,vsin ); 396HVX_Vector vx1_c = Q6_Vqf32_vmpy_VsfVsf (v1 ,vcos ); 397HVX_Vector vx1_s = Q6_Vqf32_vmpy_VsfVsf (v1 ,vsin ); 398* o0 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vsub_Vqf32Vqf32 (vx0_c ,vx1_s )); 399* o1 = Q6_Vsf_equals_Vqf32 (Q6_Vqf32_vadd_Vqf32Vqf32 (vx0_s ,vx1_c )); 400} 401 402// theta_cache full 32-pair blocks are deinterleaved [cos | sin]. 403static inline void hvx_rope_neox_f32_aa (float * restrictdst ,const float * restrictsrc0 ,uint32_t ne ,const float * restricttheta_cache ) { 404const uint32_t he = ne /2 ; 405const uint32_t nvec = he /32 ; 406const uint32_t nloe = he %32 ; 407 408if (nloe == 0 ) { 409const HVX_Vector * vs = (const HVX_Vector * )src0 ; 410const HVX_Vector * vt = (const HVX_Vector * )theta_cache ; 411HVX_Vector * vd = (HVX_Vector * )dst ; 412for (uint32_t i = 0 ;i < nvec ;i ++ ) { 413HVX_Vector o0 ,o1 ; 414hvx_rope_neox_mul (vs [i ],vs [nvec + i ],vt [i * 2 + 0 ],vt [i * 2 + 1 ],& o0 ,& o1 ); 415vd [i ]= o0 ; 416vd [nvec + i ]= o1 ; 417 } 418return ; 419 } 420 421for (uint32_t i = 0 ;i < nvec ;i ++ ) { 422HVX_Vector o0 ,o1 ; 423hvx_rope_neox_mul (((const HVX_Vector * )src0 )[i ], 424hvx_vmemu (src0 + he + i * 32 ), 425 ((const HVX_Vector * )theta_cache )[i * 2 + 0 ], 426 ((const HVX_Vector * )theta_cache )[i * 2 + 1 ], 427& o0 ,& o1 ); 428 ((HVX_Vector * )dst )[i ]= o0 ; 429hvx_vmemu (dst + he + i * 32 )= o1 ; 430 } 431 432HVX_Vector v0 = hvx_vmemu (src0 + nvec * 32 ); 433HVX_Vector v1 = hvx_vmemu (src0 + he + nvec * 32 ); 434HVX_Vector vcos = hvx_vmemu (theta_cache + nvec * 64 ); 435HVX_Vector vsin = hvx_vmemu (theta_cache + nvec * 64 + 32 ); 436HVX_Vector o0 ,o1 ; 437hvx_rope_neox_mul (v0 ,v1 ,vcos ,vsin ,& o0 ,& o1 ); 438hvx_vec_store_u (dst + nvec * 32 ,nloe * sizeof (float ),o0 ); 439hvx_vec_store_u (dst + he + nvec * 32 ,nloe * sizeof (float ),o1 ); 440} 441 442static inline void hvx_rope_f32_aa (float * restrictdst ,const float * restrictsrc0 ,uint32_t ne ,const float * restricttheta_cache ) { 443const uint32_t nvec = ne /64 ; 444const uint32_t nloe = ne %64 ; 445 446for (uint32_t i = 0 ;i < nvec ;i ++ ) { 447HVX_Vector v0 = ((const HVX_Vector * )src0 )[i * 2 + 0 ]; 448HVX_Vector v1 = ((const HVX_Vector * )src0 )[i * 2 + 1 ]; 449 450HVX_Vector vcos = ((const HVX_Vector * )theta_cache )[i * 2 + 0 ]; 451HVX_Vector vsin = ((const HVX_Vector * )theta_cache )[i * 2 + 1 ]; 452 453HVX_VectorPair vx0_x1 = Q6_W_vdeal_VVR (v1 ,v0 ,-4 ); 454 455HVX_Vector vx0_c = Q6_Vqf32_vmpy_VsfVsf (Q6_V_lo_W (vx0_x1 ),vcos ); 456HVX_Vector vx0_s = Q6_Vqf32_vmpy_VsfVsf (Q6_V_lo_W (vx0_x1 ),vsin ); 457HVX_Vector vx1_c = Q6_Vqf32_vmpy_VsfVsf (Q6_V_hi_W (vx0_x1 ),vcos ); 458HVX_Vector vx1_s = Q6_Vqf32_vmpy_VsfVsf (Q6_V_hi_W (vx0_x1 ),vsin ); 459 460HVX_Vector v4 = Q6_Vqf32_vsub_Vqf32Vqf32 (vx0_c ,vx1_s ); 461HVX_Vector v5 = Q6_Vqf32_vadd_Vqf32Vqf32 (vx0_s ,vx1_c ); 462 463HVX_VectorPair vstore = Q6_W_vshuff_VVR (Q6_Vsf_equals_Vqf32 (v5 ),Q6_Vsf_equals_Vqf32 (v4 ),-4 ); 464 465 ((HVX_Vector * )dst )[i * 2 + 0 ]= Q6_V_lo_W (vstore ); 466 ((HVX_Vector * )dst )[i * 2 + 1 ]= Q6_V_hi_W (vstore ); 467 } 468 469if (nloe > 0 ) { 470if (nloe <=32 ) { 471HVX_Vector v0 = hvx_vmemu (src0 + nvec * 64 ); 472HVX_Vector vcos = hvx_vmemu (theta_cache + nvec * 64 ); 473HVX_Vector vsin = hvx_vmemu (theta_cache + nvec * 64 + 32 ); 474 475HVX_VectorPair vx0_x1 = Q6_W_vdeal_VVR (Q6_V_vzero (),v0 ,-4 ); 476 477HVX_Vector vx0_c = Q6_Vqf32_vmpy_VsfVsf (Q6_V_lo_W (vx0_x1 ),vcos ); 478HVX_Vector vx0_s = Q6_Vqf32_vmpy_VsfVsf (Q6_V_lo_W (vx0_x1 ),vsin ); 479HVX_Vector vx1_c = Q6_Vqf32_vmpy_VsfVsf (Q6_V_hi_W (vx0_x1 ),vcos ); 480HVX_Vector vx1_s = Q6_Vqf32_vmpy_VsfVsf (Q6_V_hi_W (vx0_x1 ),vsin ); 481 482HVX_Vector v4 = Q6_Vqf32_vsub_Vqf32Vqf32 (vx0_c ,vx1_s ); 483HVX_Vector v5 = Q6_Vqf32_vadd_Vqf32Vqf32 (vx0_s ,vx1_c ); 484 485HVX_VectorPair vstore = Q6_W_vshuff_VVR (Q6_Vsf_equals_Vqf32 (v5 ),Q6_Vsf_equals_Vqf32 (v4 ),-4 ); 486 487hvx_vec_store_u (dst + nvec * 64 ,nloe * sizeof (float ),Q6_V_lo_W (vstore )); 488 }else { 489HVX_Vector v0 = hvx_vmemu (src0 + nvec * 64 ); 490HVX_Vector v1 = hvx_vmemu (src0 + nvec * 64 + 32 ); 491 492HVX_Vector vcos = hvx_vmemu (theta_cache + nvec * 64 ); 493HVX_Vector vsin = hvx_vmemu (theta_cache + nvec * 64 + 32 ); 494 495HVX_VectorPair vx0_x1 = Q6_W_vdeal_VVR (v1 ,v0 ,-4 ); 496 497HVX_Vector vx0_c = Q6_Vqf32_vmpy_VsfVsf (Q6_V_lo_W (vx0_x1 ),vcos ); 498HVX_Vector vx0_s = Q6_Vqf32_vmpy_VsfVsf (Q6_V_lo_W (vx0_x1 ),vsin ); 499HVX_Vector vx1_c = Q6_Vqf32_vmpy_VsfVsf (Q6_V_hi_W (vx0_x1 ),vcos ); 500HVX_Vector vx1_s = Q6_Vqf32_vmpy_VsfVsf (Q6_V_hi_W (vx0_x1 ),vsin ); 501 502HVX_Vector v4 = Q6_Vqf32_vsub_Vqf32Vqf32 (vx0_c ,vx1_s ); 503HVX_Vector v5 = Q6_Vqf32_vadd_Vqf32Vqf32 (vx0_s ,vx1_c ); 504 505HVX_VectorPair vstore = Q6_W_vshuff_VVR (Q6_Vsf_equals_Vqf32 (v5 ),Q6_Vsf_equals_Vqf32 (v4 ),-4 ); 506 507 ((HVX_Vector * )dst )[nvec * 2 + 0 ]= Q6_V_lo_W (vstore ); 508hvx_vec_store_u (dst + nvec * 64 + 32 , (nloe - 32 )* sizeof (float ),Q6_V_hi_W (vstore )); 509 } 510 } 511} 512 513static void inline rope_basic_f32_inplace (struct htp_rope_context * rctx ,uint8_t * src , 514uint32_t nr ,const float * restricttheta_cache ) { 515const uint32_t n_offs = rctx -> n_offs ; 516#pragma unroll(4) 517for (uint32_t i = 0 ;i < nr ;i ++ ) { 518float * s = (float * ) (src + i * rctx -> src0_row_size_aligned ); 519hvx_rope_f32_aa (s + n_offs ,s + n_offs ,rctx -> n_dims ,theta_cache ); 520 } 521} 522 523static void inline rope_neox_f32_inplace (struct htp_rope_context * rctx ,uint8_t * src , 524uint32_t nr ,uint32_t ne ,const float * restricttheta_cache ) { 525const uint32_t n_offs = rctx -> n_offs ; 526#pragma unroll(4) 527for (uint32_t i = 0 ;i < nr ;i ++ ) { 528float * s = (float * ) (src + i * rctx -> src0_row_size_aligned ); 529hvx_rope_neox_f32_aa (s + n_offs ,s + n_offs ,ne ,theta_cache ); 530 } 531} 532 533static void rope_job_f32 (unsigned int nth ,unsigned int ith ,void * data ) { 534struct htp_rope_context * rctx = (struct htp_rope_context * )data ; 535struct htp_ops_context * octx = rctx -> octx ; 536 537const struct htp_tensor * src0 = octx -> src [0 ]; 538const struct htp_tensor * src1 = octx -> src [1 ]; 539const struct htp_tensor * src2 = octx -> src [2 ]; 540const struct htp_tensor * dst = octx -> dst ; 541 542htp_rope_preamble ; 543 544const uint32_t src0_nrows = rctx -> nrows ; 545const uint32_t src0_nrows_per_thread = rctx -> src0_nrows_per_thread ; 546 547const uint32_t src0_start_row = rctx -> row_start + src0_nrows_per_thread * ith ; 548const uint32_t src0_end_row = MIN (src0_start_row + src0_nrows_per_thread ,rctx -> row_start + src0_nrows ); 549 550// no work for this thread 551if (src0_start_row >=src0_end_row ) { 552return ; 553 } 554 555const int32_t mode = rctx -> mode ; 556// MROPE, IMROPE and VISION use NEOX-style pairing for the rotation 557const bool is_neox = (mode & HTP_ROPE_TYPE_NEOX )|| (mode & HTP_ROPE_TYPE_MROPE ); 558const bool is_vision = (mode == HTP_ROPE_TYPE_VISION ); 559 560// VTCM setup 561uint8_t * src0_spad_base = rctx -> vtcm_base + (ith * rctx -> spad_per_thread ); 562float * theta_cache = (float * ) (src0_spad_base ); 563src0_spad_base = src0_spad_base + rctx -> theta_cache_offset ; 564 565dma_queue * dma_queue = octx -> ctx -> dma [ith ]; 566struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 567const int32_t * pos = (const int32_t * )src1 -> data ; 568const float * freq_factors = src2 ? (const float * )src2 -> data :NULL ; 569 570const uint32_t i3_start = fastdiv (src0_start_row ,& rctx -> div_ne2_ne1 ); 571const uint32_t rem = fastmodulo (src0_start_row ,ne2 * ne1 ,& rctx -> div_ne2_ne1 ); 572const uint32_t i2_start = fastdiv (rem ,& rctx -> div_ne1 ); 573const uint32_t i1_start = fastmodulo (rem ,ne1 ,& rctx -> div_ne1 ); 574 575uint32_t ir = src0_start_row ; 576uint32_t prev_i2 = (uint32_t )-1 ; 577uint32_t cur_slot = 0 ; 578 579for (uint32_t i3 = i3_start ;i3 < ne3 ;i3 ++ ) {// batch 580const uint32_t i2_init = (i3 == i3_start ) ?i2_start :0 ; 581for (uint32_t i2 = i2_init ;i2 < ne2 ;i2 ++ ) {// seq-len 582const uint32_t i1_init = (i3 == i3_start && i2 == i2_start ) ?i1_start :0 ; 583for (uint32_t i1 = i1_init ;i1 < ne1 ; ) {// attn-heads 584if (ir >=src0_end_row ) gotodone ; 585 586// Rows in this block 587const uint32_t nrows = MIN (src0_end_row - ir ,ne1 - i1 ); 588 589// Depth before prefetch 590const uint32_t dma_depth = dma_queue_depth (dma_queue ); 591 592// Prefetch up to 2 blocks 593const uint32_t p_nrows = MIN (nrows ,2 * HTP_ROPE_SPAD_BLOCK ); 594for (uint32_t pr = 0 ;pr < p_nrows ;pr += HTP_ROPE_SPAD_BLOCK ) { 595const uint32_t pnr = MIN (nrows - pr ,HTP_ROPE_SPAD_BLOCK ); 596const uint32_t slot = (cur_slot + pr /HTP_ROPE_SPAD_BLOCK ) %HTP_ROPE_SPAD_NSLOTS ; 597uint8_t * spad_slot = rope_spad_slot (src0_spad_base ,slot ,rctx -> src0_row_size_aligned ); 598const uint8_t * src_addr = (const uint8_t * )src0 -> data + i3 * nb03 + i2 * nb02 + (i1 + pr )* nb01 ; 599 600// Dummy DMA transaction for sequencing (interleaving wr, rd, wr, rd, ...) 601dma_queue_push (dma_queue ,dma_make_ptr ((void * )dst -> data ,spad_slot ),0 ,0 ,0 ,0 ); 602 603dma_queue_push (dma_queue ,dma_make_ptr (spad_slot ,src_addr ), 604rctx -> src0_row_size_aligned ,rctx -> src0_row_stride ,rctx -> src0_row_size ,pnr ); 605 } 606 607// Update theta cache 608if (i2 != prev_i2 ) { 609prev_i2 = i2 ; 610 611htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_A_PREP ,i2 ); 612// VISION rotates the full row; other modes only rotate n_dims. 613const uint32_t n_cache = is_vision ?ne0 : (uint32_t )rctx -> n_dims ; 614const bool is_mrope = (rctx -> mode & HTP_ROPE_TYPE_MROPE )!= 0 ; 615if (is_mrope ) { 616// src1 holds four position arrays stacked along ne0: 617// pos[i2], pos[i2+ne2], pos[i2+ne2*2], pos[i2+ne2*3] 618const bool is_imrope = (rctx -> mode == HTP_ROPE_TYPE_IMROPE ); 619mrope_cache_init ( 620 (float )pos [i2 ], 621 (float )pos [i2 + ne2 ], 622 (float )pos [i2 + ne2 * 2 ], 623 (float )pos [i2 + ne2 * 3 ], 624rctx -> sections ,is_imrope ,is_vision , 625rctx -> freq_scale ,freq_factors ,rctx -> corr_dims , 626n_cache ,rctx -> ext_factor ,rctx -> attn_factor , 627theta_cache ,rctx -> theta_scale ,rctx -> theta_powers ,rctx -> theta_scale_32 ); 628 }else { 629rope_cache_init (pos [i2 ],rctx -> freq_scale ,freq_factors ,rctx -> corr_dims , 630n_cache ,rctx -> ext_factor ,rctx -> attn_factor , 631theta_cache ,rctx -> theta_scale ,rctx -> theta_powers ,rctx -> theta_scale_32 ); 632 } 633htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_A_PREP ,i2 ); 634 } 635 636// Skip output DMA transactions from prev block (if any) 637for (uint32_t d = 0 ;d < dma_depth ;d ++ ) {dma_queue_pop_nowait (dma_queue ); } 638 639// Compute loop 640const uint32_t ne = is_vision ?ne0 :rctx -> n_dims ; 641const uint32_t base_i1 = i1 ; 642const uint32_t base_ir = ir ; 643 644for (uint32_t cnr = 0 ,cr = 0 ;cr < nrows ;cr += cnr ) { 645cnr = MIN (nrows - cr ,HTP_ROPE_SPAD_BLOCK ); 646const uint32_t slot = (cur_slot + cr /HTP_ROPE_SPAD_BLOCK ) %HTP_ROPE_SPAD_NSLOTS ; 647const uint32_t cur_ir = base_ir + cr ; 648const uint32_t cur_i1 = base_i1 + cr ; 649 650dma_queue_pop (dma_queue ); 651uint8_t * cur_spad = (uint8_t * )dma_queue_pop (dma_queue ).dst ; 652 653htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP ,cur_ir ); 654if (is_neox || is_vision ) { 655rope_neox_f32_inplace (rctx ,cur_spad ,cnr ,ne ,theta_cache ); 656 }else { 657rope_basic_f32_inplace (rctx ,cur_spad ,cnr ,theta_cache ); 658 } 659htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP ,cur_ir ); 660 661uint8_t * dst_addr = (uint8_t * )dst -> data + i3 * nb3 + i2 * nb2 + cur_i1 * nb1 ; 662dma_queue_push (dma_queue ,dma_make_ptr (dst_addr ,cur_spad ), 663rctx -> dst_row_stride ,rctx -> src0_row_size_aligned ,rctx -> dst_row_size ,cnr ); 664 665// Prefetch 2 blocks ahead into the slot just freed 666if ((cr + 2 * HTP_ROPE_SPAD_BLOCK )< nrows ) { 667const uint32_t p_cr = cr + 2 * HTP_ROPE_SPAD_BLOCK ; 668const uint32_t pnr = MIN (nrows - p_cr ,HTP_ROPE_SPAD_BLOCK ); 669const uint32_t p_slot = (cur_slot + p_cr /HTP_ROPE_SPAD_BLOCK ) %HTP_ROPE_SPAD_NSLOTS ; 670uint8_t * p_spad = rope_spad_slot (src0_spad_base ,p_slot ,rctx -> src0_row_size_aligned ); 671const uint8_t * src_addr = (const uint8_t * )src0 -> data + i3 * nb03 + i2 * nb02 + (base_i1 + p_cr )* nb01 ; 672 673dma_queue_push (dma_queue ,dma_make_ptr (p_spad ,src_addr ), 674rctx -> src0_row_size_aligned ,rctx -> src0_row_stride ,rctx -> src0_row_size ,pnr ); 675 } 676 } 677 678const uint32_t n_chunks = (nrows + HTP_ROPE_SPAD_BLOCK - 1 ) /HTP_ROPE_SPAD_BLOCK ; 679cur_slot = (cur_slot + n_chunks ) %HTP_ROPE_SPAD_NSLOTS ; 680 681ir += nrows ; 682i1 += nrows ; 683 } 684 } 685 } 686 687done : 688dma_queue_flush (dma_queue ); 689 690FARF (HIGH ,"rope-f32: %d/%d: (%u:%u)\n" ,ith ,nth ,src0_start_row ,src0_end_row ); 691} 692 693static int execute_op_rope_f32 (struct htp_ops_context * octx ) { 694int err = HTP_STATUS_OK ; 695 696const struct htp_tensor * src0 = octx -> src [0 ]; 697const struct htp_tensor * src1 = octx -> src [1 ]; 698const struct htp_tensor * src2 = octx -> src [2 ]; 699const struct htp_tensor * dst = octx -> dst ; 700 701switch (octx -> op ) { 702case HTP_OP_ROPE : 703break ; 704 705default : 706FARF (ERROR ,"Unsupported Op %u\n" ,octx -> op ); 707return HTP_STATUS_NO_SUPPORT ; 708 } 709 710const struct htp_rope_kernel_params * kparams = (const struct htp_rope_kernel_params * )octx -> kernel_params ; 711if (!htp_ops_context_set_n_threads (octx ,kparams -> n_threads )) { 712return HTP_STATUS_INVAL_PARAMS ; 713 } 714assert (octx -> ctx -> vtcm_size >=kparams -> vtcm_size ); 715 716const uint32_t total_rows = src0 -> ne [1 ]* src0 -> ne [2 ]* src0 -> ne [3 ]; 717const size_t dst_data_row_size = dst -> ne [0 ]* sizeof (float ); 718 719uint32_t row_start = 0 ; 720uint32_t nrows = total_rows ; 721 722if (octx -> ctx -> mdev .count > 1 ) { 723uint32_t rows_per_chunk = 0 ; 724htp_tensor_mdev_rows_per_chunk (dst ,sizeof (float ), (uint32_t )dst_data_row_size ,& rows_per_chunk ); 725const struct htp_tensor_mdev_range range = htp_tensor_mdev_partition ( 726total_rows ,rows_per_chunk ,octx -> ctx -> mdev .idx ,octx -> ctx -> mdev .count ,& octx -> ctx -> mdev .count_div ); 727row_start = range .start ; 728nrows = range .count ; 729 } 730 731if (nrows == 0 ) { 732return HTP_STATUS_OK ; 733 } 734 735const uint32_t n_threads = octx -> n_threads ; 736 737const uint32_t ne0 = dst -> ne [0 ]; 738const size_t src0_row_size = src0 -> ne [0 ]* sizeof (float ); 739const size_t src0_row_stride = src0 -> nb [1 ]; 740const size_t dst_row_size = dst -> ne [0 ]* sizeof (float ); 741const size_t dst_row_stride = dst -> nb [1 ]; 742 743struct htp_rope_context rctx ; 744memset (& rctx ,0 ,sizeof (struct htp_rope_context )); 745 746rctx .octx = octx ; 747rctx .vtcm_base = (uint8_t * )octx -> ctx -> vtcm_base ; 748rctx .spad_per_thread = kparams -> spad_per_thread ; 749rctx .theta_cache_offset = kparams -> theta_cache_offset ; 750 751const int32_t * op_params = & octx -> op_params [0 ]; 752rctx .n_dims = ((const int32_t * )op_params )[1 ]; 753rctx .mode = ((const int32_t * )op_params )[2 ]; 754rctx .n_ctx_orig = ((const int32_t * )op_params )[4 ]; 755rctx .n_offs = ((const int32_t * )op_params )[15 ]; 756 757memcpy (& rctx .freq_base , (int32_t * )op_params + 5 ,sizeof (float )); 758memcpy (& rctx .freq_scale , (int32_t * )op_params + 6 ,sizeof (float )); 759memcpy (& rctx .ext_factor , (int32_t * )op_params + 7 ,sizeof (float )); 760memcpy (& rctx .attn_factor , (int32_t * )op_params + 8 ,sizeof (float )); 761memcpy (& rctx .beta_fast , (int32_t * )op_params + 9 ,sizeof (float )); 762memcpy (& rctx .beta_slow , (int32_t * )op_params + 10 ,sizeof (float )); 763memcpy (& rctx .sections , (int32_t * )op_params + 11 ,sizeof (int )* 4 ); 764 765rctx .theta_scale = powf (rctx .freq_base ,-2.0f /rctx .n_dims ); 766rctx .theta_powers [0 ]= 1.0f ; 767for (int j = 1 ;j < 32 ;j ++ ) { 768rctx .theta_powers [j ]= rctx .theta_powers [j - 1 ]* rctx .theta_scale ; 769 } 770rctx .theta_scale_32 = rctx .theta_powers [31 ]* rctx .theta_scale ; 771 772rope_corr_dims (rctx .n_dims ,rctx .n_ctx_orig ,rctx .freq_base ,rctx .beta_fast ,rctx .beta_slow ,rctx .corr_dims ); 773 774rctx .src0_row_size = src0_row_size ; 775rctx .src0_row_stride = src0_row_stride ; 776rctx .dst_row_size = dst_row_size ; 777rctx .dst_row_stride = dst_row_stride ; 778rctx .src0_row_size_aligned = kparams -> src0_row_size_aligned ; 779 780rctx .src0_nrows = nrows ; 781rctx .nrows = nrows ; 782rctx .row_start = row_start ; 783rctx .src0_nrows_per_thread = fastdiv (nrows + n_threads - 1 ,& octx -> n_threads_div ); 784rctx .div_ne2_ne1 = kparams -> div_ne2_ne1 ; 785rctx .div_ne1 = kparams -> div_ne1 ; 786 787FARF (HIGH ,"rope-f32 n-rows %u n-dims %d ne0 %u ext-factor %.6f theta-scale %.6f attn-factor %.6f\n" ,rctx .src0_nrows ,rctx .n_dims ,ne0 , 788rctx .ext_factor ,rctx .theta_scale ,rctx .attn_factor ); 789 790work_queue_run (octx -> ctx -> work_queue ,rope_job_f32 ,& rctx ,n_threads ); 791 792return err ; 793} 794 795int op_rope (struct htp_ops_context * octx ) { 796switch (octx -> src [0 ]-> type ) { 797case HTP_TYPE_F32 : 798return execute_op_rope_f32 (octx ); 799 800default : 801return HTP_STATUS_NO_SUPPORT ; 802 } 803}