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 11#include "hex-dma.h" 12#include "hvx-utils.h" 13#include "hex-fastdiv.h" 14 15#define GGML_COMMON_DECL_C 16#include "ggml-common.h" 17#include "hex-common.h" 18#include "hex-profile.h" 19#include "htp-ctx.h" 20#include "htp-ops.h" 21#include "htp-tensor.h" 22 23#define htp_softmax_preamble3 \ 24 const uint32_t ne00 = src0->ne[0]; \ 25 const uint32_t ne01 = src0->ne[1]; \ 26 const uint32_t ne02 = src0->ne[2]; \ 27 const uint32_t ne03 = src0->ne[3]; \ 28 \ 29 const uint32_t nb00 = src0->nb[0]; \ 30 const uint32_t nb01 = src0->nb[1]; \ 31 const uint32_t nb02 = src0->nb[2]; \ 32 const uint32_t nb03 = src0->nb[3]; \ 33 \ 34 const uint32_t ne10 = src1 ? src1->ne[0] : 1; \ 35 const uint32_t ne11 = src1 ? src1->ne[1] : 1; \ 36 const uint32_t ne12 = src1 ? src1->ne[2] : 1; \ 37 const uint32_t ne13 = src1 ? src1->ne[3] : 1; \ 38 \ 39 const uint32_t nb10 = src1 ? src1->nb[0] : 1; \ 40 const uint32_t nb11 = src1 ? src1->nb[1] : 1; \ 41 const uint32_t nb12 = src1 ? src1->nb[2] : 1; \ 42 const uint32_t nb13 = src1 ? src1->nb[3] : 1; \ 43 \ 44 const uint32_t ne0 = dst->ne[0]; \ 45 const uint32_t ne1 = dst->ne[1]; \ 46 const uint32_t ne2 = dst->ne[2]; \ 47 const uint32_t ne3 = dst->ne[3]; \ 48 \ 49 const uint32_t nb0 = dst->nb[0]; \ 50 const uint32_t nb1 = dst->nb[1]; \ 51 const uint32_t nb2 = dst->nb[2]; \ 52 const uint32_t nb3 = dst->nb[3]; 53 54struct htp_softmax_context { 55struct htp_ops_context * octx ; 56 57bool use_f16 ; 58bool use_src1 ; 59 60uint32_t n_head ; 61uint32_t n_head_log2 ; 62 63float scale ; 64float max_bias ; 65float m0 ; 66float m1 ; 67 68struct fastdiv_values fastdiv_ne01 ; 69struct fastdiv_values fastdiv_ne02 ; 70struct fastdiv_values fastdiv_ne12 ;// For mask broadcasting 71struct fastdiv_values fastdiv_ne13 ;// For mask broadcasting 72 73uint32_t src0_nrows_per_thread ; 74uint32_t row_start ; 75uint32_t nrows ; 76}; 77 78static void apply_mask (float * restrictwp0 , 79const float * restrictmp_f32 , 80const __fp16 * restrictmp_f16 , 81uint32_t ne00 , 82float slope , 83bool use_f16 ) { 84if (!mp_f32 ) { 85return ; 86 } 87if (use_f16 ) { 88for (uint32_t i = 0 ;i < ne00 ;++ i ) { 89wp0 [i ]+= slope * (float )mp_f16 [i ]; 90 } 91 }else { 92for (uint32_t i = 0 ;i < ne00 ;++ i ) { 93wp0 [i ]+= slope * mp_f32 [i ]; 94 } 95 } 96} 97 98static void init_softmax_ctx (struct htp_softmax_context * smctx ,struct htp_ops_context * octx ) { 99const struct htp_tensor * src0 = octx -> src [0 ]; 100const struct htp_tensor * src1 = octx -> src [1 ]; 101 102memset (smctx ,0 ,sizeof (struct htp_softmax_context )); 103 104memcpy (& smctx -> scale , (float * )octx -> op_params ,sizeof (float )); 105memcpy (& smctx -> max_bias , (float * )octx -> op_params + 1 ,sizeof (float )); 106 107smctx -> n_head = src0 -> ne [2 ]; 108smctx -> n_head_log2 = 1u << (uint32_t )floor (log2 (smctx -> n_head )); 109 110smctx -> m0 = powf (2.0f ,- (smctx -> max_bias ) /smctx -> n_head_log2 ); 111smctx -> m1 = powf (2.0f ,- (smctx -> max_bias /2.0f ) /smctx -> n_head_log2 ); 112 113smctx -> use_src1 = (src1 != 0 ); 114smctx -> use_f16 = (src1 != 0 )&& (src1 -> type == HTP_TYPE_F16 ); 115 116smctx -> octx = octx ; 117 118// Initialize fastdiv values 119const uint32_t ne01 = src0 -> ne [1 ]; 120const uint32_t ne02 = src0 -> ne [2 ]; 121 122if (ne01 > 0 )smctx -> fastdiv_ne01 = init_fastdiv_values (ne01 ); 123if (ne02 > 0 )smctx -> fastdiv_ne02 = init_fastdiv_values (ne02 ); 124 125const uint32_t ne12 = src1 ?src1 -> ne [2 ] :1 ; 126const uint32_t ne13 = src1 ?src1 -> ne [3 ] :1 ; 127 128if (ne12 > 0 )smctx -> fastdiv_ne12 = init_fastdiv_values (ne12 ); 129if (ne13 > 0 )smctx -> fastdiv_ne13 = init_fastdiv_values (ne13 ); 130} 131 132static void hvx_fast_softmax_prep_f32 (const uint8_t * restrictsrc , 133uint8_t * restrictdst , 134const int num_elems , 135float scale , 136const uint8_t * restrictmask , 137float slope ) { 138const uint8_t * restrictsrc_curr = src ; 139uint8_t * restrictdst_curr = dst ; 140const uint8_t * restrictmask_curr = mask ; 141 142HVX_Vector scale_vec = hvx_vec_splat_f32 (scale ); 143HVX_Vector slope_vec = hvx_vec_splat_f32 (slope ); 144 145int step_of_1 = num_elems >>5 ; 146 147#pragma unroll(4) 148for (int i = 0 ;i < step_of_1 ;i ++ ) { 149HVX_Vector v1 = * (HVX_Vector * )src_curr ; 150 151HVX_Vector v3 = * (HVX_Vector * )mask_curr ; 152 153HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,scale_vec ); 154 155HVX_Vector v4 = Q6_Vqf32_vmpy_VsfVsf (v3 ,slope_vec ); 156 157HVX_Vector v5 = Q6_Vqf32_vadd_Vqf32Vqf32 (v2 ,v4 ); 158 159* (HVX_Vector * )dst_curr = Q6_Vsf_equals_Vqf32 (v5 ); 160 161src_curr += VLEN ; 162dst_curr += VLEN ; 163mask_curr += VLEN ; 164 } 165} 166 167static void hvx_fast_softmax_f32 (const uint8_t * restrictsrc ,uint8_t * restrictdst ,uint8_t * restrictpad ,const int num_elems ) { 168const HVX_Vector * restrictv_src = (HVX_Vector * )src ; 169HVX_Vector * restrictv_pad = (HVX_Vector * )pad ; 170HVX_Vector * restrictv_dst = (HVX_Vector * )dst ; 171 172HVX_Vector sum_vec = Q6_V_vsplat_R (0x00000000 ); 173HVX_Vector max_vec = hvx_vec_splat_f32 (((const float * )src )[0 ]); 174HVX_Vector zero_v = Q6_V_vzero (); 175HVX_Vector one_v = hvx_vec_splat_f32 (1.0 ); 176 177int step_of_1 = num_elems >>5 ; 178 179#pragma unroll(4) 180for (int i = 0 ;i < step_of_1 ;i ++ ) { 181HVX_Vector v1 = v_src [i ]; 182max_vec = Q6_Vsf_vmax_VsfVsf (max_vec ,v1 ); 183 } 184 185max_vec = hvx_vec_reduce_max_f32 (max_vec );// replicated over all lanes 186 187#pragma unroll(4) 188for (int i = 0 ;i < step_of_1 ;i ++ ) { 189HVX_Vector v1 = v_src [i ]; 190HVX_Vector v2 = Q6_Vqf32_vsub_VsfVsf (v1 ,max_vec ); 191 192HVX_Vector v3 = hvx_vec_exp_f32 (Q6_Vsf_equals_Vqf32 (v2 )); 193 194sum_vec = Q6_Vqf32_vadd_VsfVsf (Q6_Vsf_equals_Vqf32 (sum_vec ),v3 ); 195 196v_pad [i ]= v3 ; 197 } 198 199sum_vec = hvx_vec_reduce_sum_f32 (Q6_Vsf_equals_Vqf32 (sum_vec ));// replicated over all lanes 200 201HVX_VectorPred pos_sum = Q6_Q_vcmp_gt_VwVw (sum_vec ,zero_v ); 202HVX_Vector v4 = hvx_vec_inverse_f32 (sum_vec ); 203HVX_Vector scale_vec = Q6_V_vmux_QVV (pos_sum ,v4 ,one_v ); 204 205#pragma unroll(4) 206for (int i = 0 ;i < step_of_1 ;i ++ ) { 207HVX_Vector v1 = v_pad [i ]; 208HVX_Vector v2 = Q6_Vqf32_vmpy_VsfVsf (v1 ,scale_vec ); 209v_dst [i ]= Q6_Vsf_equals_Vqf32 (v2 ); 210 } 211} 212 213static float hvx_softmax_f32 (const uint8_t * restrictsrc ,uint8_t * restrictdst ,uint8_t * restrictspad ,const int num_elems ,const float max ) { 214hvx_sub_scalar_f32 (spad ,src ,max ,num_elems ); 215 216hvx_exp_f32 (dst ,spad ,num_elems , false); 217return hvx_reduce_sum_f32 (dst ,num_elems ); 218} 219 220static void softmax_job_f32 (unsigned int nth ,unsigned int ith ,void * data ) { 221struct htp_softmax_context * smctx = (struct htp_softmax_context * )data ; 222struct htp_ops_context * octx = smctx -> octx ; 223 224const struct htp_tensor * src0 = octx -> src [0 ]; 225const struct htp_tensor * src1 = octx -> src [1 ]; 226const struct htp_tensor * dst = octx -> dst ; 227 228htp_softmax_preamble3 ; 229 230const uint32_t src0_nrows = smctx -> nrows ; 231const uint32_t src0_nrows_per_thread = smctx -> src0_nrows_per_thread ; 232 233const uint32_t src0_start_row = smctx -> row_start + src0_nrows_per_thread * ith ; 234const uint32_t src0_end_row = MIN (src0_start_row + src0_nrows_per_thread ,smctx -> row_start + src0_nrows ); 235 236// no work for this thread 237if (src0_start_row >=src0_end_row ) { 238return ; 239 } 240 241int is_aligned = 1 ; 242int opt_path = 0 ; 243 244if (!hex_is_aligned ((void * )src0 -> data ,VLEN )|| !hex_is_aligned ((void * )dst -> data ,VLEN )) { 245is_aligned = 0 ; 246FARF (HIGH ,"softmax-f32: unaligned addresses in elementwise op, possibly slower execution\n" ); 247 } 248 249// Only use the fast path when aligned AND row size is multiple of VLEN (128 bytes) 250// The fast path (hvx_fast_softmax_f32) doesn't handle tail elements 251// The non-opt path uses hvx_softmax_f32 which properly handles all sizes via its helper functions 252if ((1 == is_aligned )&& !(nb01 & (VLEN - 1 ))) { 253opt_path = 1 ; 254 } 255 256uint8_t * src0_spad_data = octx -> src0_spad .data + (ith * octx -> src0_spad .size_per_thread ); 257uint8_t * src1_spad_data = octx -> src1_spad .data + (ith * octx -> src1_spad .size_per_thread ); 258uint8_t * dst_spad_data = octx -> dst_spad .data + (ith * octx -> dst_spad .size_per_thread ); 259 260float * wp0 = (float * )src0_spad_data ; 261float * wp1 = (float * )src1_spad_data ; 262float * wp2 = (float * )dst_spad_data ; 263 264uint32_t prev_i2 = (uint32_t )-1 ; 265float slope = 1.0f ; 266 267struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 268htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP ,src0_start_row ); 269 270for (uint32_t r = src0_start_row ;r < src0_end_row ;++ r ) { 271uint32_t i1 = fastmodulo (r ,ne01 ,& smctx -> fastdiv_ne01 ); 272uint32_t r_div_ne01 = fastdiv (r ,& smctx -> fastdiv_ne01 ); 273uint32_t i2 = fastmodulo (r_div_ne01 ,ne02 ,& smctx -> fastdiv_ne02 ); 274uint32_t i3 = fastdiv (r_div_ne01 ,& smctx -> fastdiv_ne02 ); 275 276// Map to original logic indices 277// i01 = i1 278// i02 = i2 279// i03 = i3 280 281const uint32_t i11 = i1 ; 282// const uint32_t i12 = i2 % ne12; 283// const uint32_t i13 = i3 % ne13; 284 285uint32_t i12 ,i13 ; 286if (ne12 == ne02 ) { 287i12 = i2 ; 288 }else { 289i12 = fastmodulo (i2 ,ne12 ,& smctx -> fastdiv_ne12 ); 290 } 291 292if (ne13 == ne03 ) { 293i13 = i3 ; 294 }else { 295i13 = fastmodulo (i3 ,ne13 ,& smctx -> fastdiv_ne13 ); 296 } 297 298// ALiBi 299if (i2 != prev_i2 ) { 300const uint32_t h = i2 ;// head 301slope = (smctx -> max_bias > 0.0f ) ?h < smctx -> n_head_log2 ?powf (smctx -> m0 ,h + 1 ) :powf (smctx -> m1 ,2 * (h - smctx -> n_head_log2 )+ 1 ) :1.0f ; 302prev_i2 = i2 ; 303 } 304 305float * sp = (float * ) ((char * )src0 -> data + i1 * nb01 + i2 * nb02 + i3 * nb03 ); 306float * dp = (float * ) ((char * )dst -> data + i1 * nb1 + i2 * nb2 + i3 * nb3 ); 307 308// broadcast the mask across rows 309__fp16 * mp_f16 = (smctx -> use_src1 ) ? (__fp16 * ) ((char * )src1 -> data + i11 * nb11 + i12 * nb12 + i13 * nb13 ) :NULL ; 310float * mp_f32 = (smctx -> use_src1 ) ? (float * ) ((char * )src1 -> data + i11 * nb11 + i12 * nb12 + i13 * nb13 ) :NULL ; 311 312if ((1 == opt_path )&& (mp_f32 )&& !(smctx -> use_f16 )) { 313hvx_fast_softmax_prep_f32 ((const uint8_t * )sp , (uint8_t * )wp0 ,ne00 ,smctx -> scale , (const uint8_t * )mp_f32 ,slope ); 314hvx_fast_softmax_f32 ((const uint8_t * )wp0 , (uint8_t * )dp , (uint8_t * )wp1 ,ne00 ); 315 }else if (1 == opt_path ) { 316hvx_scale_f32 ((uint8_t * )wp0 , (const uint8_t * )sp ,ne00 ,smctx -> scale ); 317apply_mask (wp0 ,mp_f32 ,mp_f16 ,ne00 ,slope ,smctx -> use_f16 ); 318hvx_fast_softmax_f32 ((const uint8_t * )wp0 , (uint8_t * )dp , (uint8_t * )wp1 ,ne00 ); 319 }else { 320// Non-optimized path: uses HVX helper functions that properly handle all tensor sizes 321// including non-multiples of 32 (the HVX vector lane count for f32) 322hvx_scale_f32 ((uint8_t * )wp0 , (const uint8_t * )sp ,ne00 ,smctx -> scale ); 323apply_mask (wp0 ,mp_f32 ,mp_f16 ,ne00 ,slope ,smctx -> use_f16 ); 324float max = hvx_reduce_max_f32 ((const uint8_t * )wp0 ,ne00 ); 325float sum = hvx_softmax_f32 ((const uint8_t * )wp0 , (uint8_t * )wp2 , (uint8_t * )wp1 ,ne00 ,max ); 326sum = sum > 0.0 ? (1.0 /sum ) :1 ; 327hvx_scale_f32 ((uint8_t * )dp , (const uint8_t * )wp2 ,ne00 ,sum ); 328 } 329 } 330 331htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP ,src0_start_row ); 332 333FARF (HIGH ,"softmax-f32 %d/%d: %ux%ux%ux%u (%u:%u) x %ux%ux%ux%u -> %ux%ux%ux%u : opt %u f16 %u\n" ,ith ,nth , 334ne00 ,ne01 ,ne02 ,ne03 ,src0_start_row ,src0_end_row ,ne10 ,ne11 ,ne12 ,ne13 , 335ne0 ,ne1 ,ne2 ,ne3 ,opt_path ,smctx -> use_f16 ); 336} 337 338static int execute_op_softmax_f32 (struct htp_ops_context * octx ) { 339int err = HTP_STATUS_OK ; 340 341const struct htp_tensor * src0 = octx -> src [0 ]; 342const struct htp_tensor * src1 = octx -> src [1 ]; 343const struct htp_tensor * dst = octx -> dst ; 344 345struct htp_softmax_context smctx ; 346const char * op_type = "softmax-f32" ; 347 348init_softmax_ctx (& smctx ,octx ); 349 350const uint32_t src0_nrows = src0 -> ne [1 ]* src0 -> ne [2 ]* src0 -> ne [3 ]; 351const size_t elem_size = sizeof (float ); 352const size_t dst_row_size = dst -> nb [1 ]; 353 354uint32_t row_start = 0 ; 355uint32_t nrows = src0_nrows ; 356 357if (octx -> ctx -> mdev .count > 1 ) { 358uint32_t rows_per_chunk = 0 ; 359htp_tensor_mdev_rows_per_chunk (dst , (uint32_t )elem_size , (uint32_t )dst_row_size ,& rows_per_chunk ); 360const struct htp_tensor_mdev_range range = htp_tensor_mdev_partition (src0_nrows ,rows_per_chunk ,octx -> ctx -> mdev .idx ,octx -> ctx -> mdev .count ,& octx -> ctx -> mdev .count_div ); 361row_start = range .start ; 362nrows = range .count ; 363 } 364 365if (nrows == 0 ) { 366return HTP_STATUS_OK ; 367 } 368 369const uint32_t n_threads = octx -> n_threads ; 370 371smctx .src0_nrows_per_thread = fastdiv (nrows + n_threads - 1 ,& octx -> n_threads_div ); 372smctx .row_start = row_start ; 373smctx .nrows = nrows ; 374 375const size_t src0_row_size = src0 -> nb [1 ]; 376const size_t src1_row_size = src0_row_size ; 377 378// VTCM scratchpads for all tensors 379// 4 rows per thread, padded to HVX vector size 380octx -> src0_spad .size_per_thread = hex_round_up (4 * src0_row_size ,128 ); 381octx -> src1_spad .size_per_thread = hex_round_up (4 * src1_row_size ,128 ); 382octx -> dst_spad .size_per_thread = hex_round_up (4 * dst_row_size ,128 ); 383 384octx -> src0_spad .size = octx -> src0_spad .size_per_thread * n_threads ; 385octx -> src1_spad .size = octx -> src1_spad .size_per_thread * n_threads ; 386octx -> dst_spad .size = octx -> dst_spad .size_per_thread * n_threads ; 387 388size_t spad_size = octx -> src0_spad .size + octx -> src1_spad .size + octx -> dst_spad .size ; 389 390if (src1 ) { 391FARF (HIGH ,"%s: %ux%ux%ux%u x %ux%ux%ux%u -> %ux%ux%ux%u : src0-spad-size %u src1-spad-size %u dst-spad-size %u\n" , 392op_type ,src0 -> ne [0 ],src0 -> ne [1 ],src0 -> ne [2 ],src0 -> ne [3 ],src1 -> ne [0 ],src1 -> ne [1 ],src1 -> ne [2 ], 393src1 -> ne [3 ],dst -> ne [0 ],dst -> ne [1 ],dst -> ne [2 ],dst -> ne [3 ],octx -> src0_spad .size ,octx -> src1_spad .size , 394octx -> dst_spad .size ); 395 }else { 396FARF (HIGH ,"%s: %ux%ux%ux%u -> %ux%ux%ux%u : src0-spad-size %u src1-spad-size %u dst-spad-size %u\n" ,op_type , 397src0 -> ne [0 ],src0 -> ne [1 ],src0 -> ne [2 ],src0 -> ne [3 ],dst -> ne [0 ],dst -> ne [1 ],dst -> ne [2 ],dst -> ne [3 ], 398octx -> src0_spad .size ,octx -> src1_spad .size ,octx -> dst_spad .size ); 399 } 400 401// Make sure the reserved vtcm size is sufficient 402if (octx -> ctx -> vtcm_size < spad_size ) { 403FARF (ERROR ,"%s : current VTCM reservation %zu is too small, needed %zu\n" ,op_type ,octx -> ctx -> vtcm_size ,spad_size ); 404return HTP_STATUS_VTCM_TOO_SMALL ; 405 } 406 407octx -> src0_spad .data = octx -> ctx -> vtcm_base ;octx -> src0_spad .src = NULL ; 408octx -> src1_spad .data = octx -> src0_spad .data + octx -> src0_spad .size ;octx -> src1_spad .src = NULL ; 409octx -> dst_spad .data = octx -> src1_spad .data + octx -> src1_spad .size ;octx -> dst_spad .src = NULL ; 410 411work_queue_run (octx -> ctx -> work_queue ,softmax_job_f32 ,& smctx ,n_threads ); 412 413return err ; 414} 415 416int op_softmax (struct htp_ops_context * octx ) { 417int err = HTP_STATUS_OK ; 418 419switch (octx -> src [0 ]-> type ) { 420case HTP_TYPE_F32 : 421err = execute_op_softmax_f32 (octx ); 422break ; 423 424default : 425err = HTP_STATUS_NO_SUPPORT ; 426break ; 427 } 428 429return err ; 430}