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_mem.h> 7#include <HAP_ps.h> 8#include <hexagon_protos.h> 9#include <hexagon_types.h> 10#include <math.h> 11#include <qurt_thread.h> 12#include <string.h> 13 14#define GGML_COMMON_DECL_C 15#include "ggml-common.h" 16#include "htp-ctx.h" 17#include "hex-dma.h" 18#include "hex-profile.h" 19#include "htp-ops.h" 20#include "htp-tensor.h" 21#include "hvx-utils.h" 22 23#define htp_ssm_conv_tensors_preamble \ 24 const struct htp_tensor * restrict src0 = octx->src[0]; \ 25 const struct htp_tensor * restrict src1 = octx->src[1]; \ 26 const struct htp_tensor * restrict dst = octx->dst; \ 27 struct htp_spad * restrict src0_spad = &octx->src0_spad; \ 28 struct htp_spad * restrict src1_spad = &octx->src1_spad; \ 29 struct htp_spad * restrict dst_spad = &octx->dst_spad; \ 30 \ 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 ne10 = src1->ne[0]; \ 37 const uint32_t ne11 = src1->ne[1]; \ 38 const uint32_t ne12 = src1->ne[2]; \ 39 const uint32_t ne13 = src1->ne[3]; \ 40 \ 41 const uint32_t ne0 = dst->ne[0]; \ 42 const uint32_t ne1 = dst->ne[1]; \ 43 const uint32_t ne2 = dst->ne[2]; \ 44 const uint32_t ne3 = dst->ne[3]; \ 45 \ 46 const uint32_t nb00 = src0->nb[0]; \ 47 const uint32_t nb01 = src0->nb[1]; \ 48 const uint32_t nb02 = src0->nb[2]; \ 49 const uint32_t nb03 = src0->nb[3]; \ 50 \ 51 const uint32_t nb10 = src1->nb[0]; \ 52 const uint32_t nb11 = src1->nb[1]; \ 53 const uint32_t nb12 = src1->nb[2]; \ 54 const uint32_t nb13 = src1->nb[3]; \ 55 \ 56 const uint32_t nb0 = dst->nb[0]; \ 57 const uint32_t nb1 = dst->nb[1]; \ 58 const uint32_t nb2 = dst->nb[2]; \ 59 const uint32_t nb3 = dst->nb[3]; 60 61struct htp_ssm_conv_context { 62struct htp_ops_context * octx ; 63uint32_t nrows_per_thread ; 64uint32_t d_inner_tile ; 65uint64_t t_start ; 66uint32_t row_start ; 67uint32_t nrows ; 68}; 69 70#define htp_ssm_conv_preamble \ 71 struct htp_ssm_conv_context * scctx = (struct htp_ssm_conv_context *) data; \ 72 struct htp_ops_context * octx = scctx->octx; \ 73 htp_ssm_conv_tensors_preamble; \ 74 dma_queue * dma_queue = octx->ctx->dma[ith]; 75 76// Scalar FP32 SSM_CONV implementation 77static void ssm_conv_thread_f32_f32 (unsigned int nth ,unsigned int ith ,void * data ) { 78htp_ssm_conv_preamble ; 79 80const uint32_t d_conv = src1 -> ne [0 ]; 81const uint32_t d_inner = src0 -> ne [1 ]; 82const uint32_t n_t = dst -> ne [1 ]; 83const uint32_t n_s = dst -> ne [2 ]; 84 85const uint32_t src0_stride_inner = src0 -> nb [1 ] /sizeof (float );// stride for inner dimension 86const uint32_t src0_stride_seq = src0 -> nb [2 ] /sizeof (float );// stride for sequence dimension 87const uint32_t src1_stride_inner = src1 -> nb [1 ] /sizeof (float );// stride for inner dimension 88const uint32_t dst_stride_token = dst -> nb [1 ] /sizeof (float );// stride for token dimension 89const uint32_t dst_stride_seq = dst -> nb [2 ] /sizeof (float );// stride for sequence dimension 90 91const float * src0_data = (const float * )src0 -> data ; 92const float * src1_data = (const float * )src1 -> data ; 93float * dst_data = (float * )dst -> data ; 94 95// Calculate row range for this thread 96const uint32_t d_inner_per_thread = scctx -> nrows_per_thread ; 97const uint32_t d_inner_start = scctx -> row_start + d_inner_per_thread * ith ; 98const uint32_t d_inner_end = MIN (d_inner_start + d_inner_per_thread ,scctx -> row_start + scctx -> nrows ); 99 100// No work for this thread 101if (d_inner_start >=d_inner_end ) { 102return ; 103 } 104 105struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 106htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )d_inner_start ); 107 108for (uint32_t i3 = 0 ;i3 < n_s ;++ i3 ) { 109for (uint32_t i2 = 0 ;i2 < n_t ;++ i2 ) { 110for (uint32_t i1 = d_inner_start ;i1 < d_inner_end ;++ i1 ) { 111float sumf = 0.0f ; 112 113for (uint32_t i0 = 0 ;i0 < d_conv ;++ i0 ) { 114const uint32_t src0_idx = (i2 + i0 )+ i1 * src0_stride_inner + i3 * src0_stride_seq ; 115const uint32_t src1_idx = i0 + i1 * src1_stride_inner ; 116 117sumf += src0_data [src0_idx ]* src1_data [src1_idx ]; 118 } 119 120const uint32_t dst_idx = i1 + i2 * dst_stride_token + i3 * dst_stride_seq ; 121dst_data [dst_idx ]= sumf ; 122 } 123 } 124 } 125 126htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )d_inner_end ); 127 128FARF (HIGH ,"ssm-conv-f32 %d/%d: %ux%ux%ux%u (%u:%u) * %ux%ux%ux%u -> %ux%ux%ux%u\n" , 129ith ,nth ,src0 -> ne [0 ],src0 -> ne [1 ],src0 -> ne [2 ],src0 -> ne [3 ],d_inner_start ,d_inner_end , 130src1 -> ne [0 ],src1 -> ne [1 ],src1 -> ne [2 ],src1 -> ne [3 ],dst -> ne [0 ],dst -> ne [1 ], 131dst -> ne [2 ],dst -> ne [3 ]); 132} 133 134 135// In-register 32x32 fp32 transpose using std 5-stage HVX vshuff butterfly. 136static inline void hvx_transpose_32x32_f32 (HVX_Vector m [32 ]) { 137HVX_Vector tmp [32 ]; 138 139// Stage 0 (R = -4): pair (2i, 2i+1) for i = 0..15. m -> tmp. 140for (int i = 0 ;i < 16 ;++ i ) { 141HVX_VectorPair p = Q6_W_vshuff_VVR (m [2 * i + 1 ],m [2 * i ],-4 ); 142tmp [2 * i + 0 ]= Q6_V_lo_W (p ); 143tmp [2 * i + 1 ]= Q6_V_hi_W (p ); 144 } 145 146// Stage 1 (R = -8): per block of 4, pair (b+0, b+2) and (b+1, b+3). tmp -> m. 147for (int b = 0 ;b < 32 ;b += 4 ) { 148HVX_VectorPair p0 = Q6_W_vshuff_VVR (tmp [b + 2 ],tmp [b + 0 ],-8 ); 149HVX_VectorPair p1 = Q6_W_vshuff_VVR (tmp [b + 3 ],tmp [b + 1 ],-8 ); 150m [b + 0 ]= Q6_V_lo_W (p0 );m [b + 1 ]= Q6_V_hi_W (p0 ); 151m [b + 2 ]= Q6_V_lo_W (p1 );m [b + 3 ]= Q6_V_hi_W (p1 ); 152 } 153 154// Stage 2 (R = -16): per block of 8, pair (b+i, b+i+4) for i = 0..3. m -> tmp. 155for (int b = 0 ;b < 32 ;b += 8 ) { 156for (int i = 0 ;i < 4 ;++ i ) { 157HVX_VectorPair p = Q6_W_vshuff_VVR (m [b + i + 4 ],m [b + i ],-16 ); 158tmp [b + 2 * i + 0 ]= Q6_V_lo_W (p ); 159tmp [b + 2 * i + 1 ]= Q6_V_hi_W (p ); 160 } 161 } 162 163// Stage 3 (R = -32): per block of 16, pair (b+i, b+i+8) for i = 0..7. tmp -> m. 164for (int b = 0 ;b < 32 ;b += 16 ) { 165for (int i = 0 ;i < 8 ;++ i ) { 166HVX_VectorPair p = Q6_W_vshuff_VVR (tmp [b + i + 8 ],tmp [b + i ],-32 ); 167m [b + 2 * i + 0 ]= Q6_V_lo_W (p ); 168m [b + 2 * i + 1 ]= Q6_V_hi_W (p ); 169 } 170 } 171 172// Stage 4 (R = -64): pair (i, i+16) for i = 0..15. m -> tmp -> m. 173for (int i = 0 ;i < 16 ;++ i ) { 174HVX_VectorPair p = Q6_W_vshuff_VVR (m [i + 16 ],m [i ],-64 ); 175tmp [2 * i + 0 ]= Q6_V_lo_W (p ); 176tmp [2 * i + 1 ]= Q6_V_hi_W (p ); 177 } 178 179for (int i = 0 ;i < 32 ;++ i ) { 180m [i ]= tmp [i ]; 181 } 182} 183 184// HVX FP32 SSM_CONV implementation - channel-vectorized HVX kernel with src0/src1 185// transposed into VTCM. 186// 187// VTCM layouts (per thread): 188// src1_T : {d_inner_stride, d_conv} - staged once per launch (small). 189// src0_T : {d_inner_tile, ncs} - staged per d_inner-tile. 190// 191// d_inner_tile is chosen so that per-thread VTCM stays under the budget. 192// Each thread iterates ceil(d_inner_per_thread d_inner_tile) tiles serially. 193#define HTP_SSM_CONV_VTCM_BUDGET (1u << 20) // 1 MiB per thread 194 195// Scalar transpose: src1 {d_conv, d_inner} (DDR) -> {d_inner_stride, d_conv} (VTCM) 196static inline void transpose_src1 (const float * src1_data , 197uint32_t src1_stride_inner , 198uint32_t i1_off , 199uint32_t d_inner_per_thread , 200uint32_t d_inner_stride , 201uint32_t d_conv , 202float * src1_T ) { 203for (uint32_t i = 0 ;i < d_inner_per_thread ;++ i ) { 204const float * src_row = src1_data + (i1_off + i )* src1_stride_inner ; 205for (uint32_t j = 0 ;j < d_conv ;++ j ) { 206src1_T [j * d_inner_stride + i ]= src_row [j ]; 207 } 208 } 209} 210 211// HVX 32x32 src0 transpose: src0 {ncs, d_inner} (DDR) -> src0_T {d_inner_tile, ncs} (VTCM) 212static inline void transpose_src0_block (const float * src0_block , 213uint32_t ncs , 214uint32_t cb_n , 215uint32_t d_inner_tile , 216float * src0_T_block_dst , 217uint32_t cb /* dst column offset */ ) { 218const uint32_t T_TILE = VLEN_FP32 ; 219 220HVX_Vector __attribute__((aligned (VLEN )))sub [32 ]; 221 222for (uint32_t t0 = 0 ;t0 < ncs ;t0 += T_TILE ) { 223const uint32_t t_n = MIN (T_TILE ,ncs - t0 ); 224 225// Load 32 rows (channels) of T_TILE samples; pad missing channels with zeros. 226for (uint32_t r = 0 ;r < cb_n ;++ r ) { 227const float * src_row = src0_block + r * ncs + t0 ; 228if (t_n == T_TILE ) { 229sub [r ]= * (const HVX_UVector * )src_row ; 230 }else { 231HVX_Vector v = hvx_vec_splat_f32 (0.0f ); 232hvx_vec_store_u (& v ,t_n * sizeof (float ),hvx_vec_splat_f32 (0.0f )); 233 234float __attribute__((aligned (VLEN )))tmp [VLEN_FP32 ]= {0 }; 235for (uint32_t k = 0 ;k < t_n ;++ k )tmp [k ]= src_row [k ]; 236v = * (const HVX_Vector * )tmp ; 237sub [r ]= v ; 238 } 239 } 240for (uint32_t r = cb_n ;r < T_TILE ;++ r ) { 241sub [r ]= hvx_vec_splat_f32 (0.0f ); 242 } 243 244hvx_transpose_32x32_f32 (sub ); 245 246// Store transposed sub-tile to src0_T at offsets (t0 + j) * d_inner_tile + cb. 247// Only write the valid t_n rows of the transposed result. 248for (uint32_t r = 0 ;r < t_n ;++ r ) { 249float * dst = src0_T_block_dst + (t0 + r )* d_inner_tile + cb ; 250if (cb_n == T_TILE ) { 251* (HVX_UVector * )dst = sub [r ]; 252 }else { 253hvx_vec_store_u (dst ,cb_n * sizeof (float ),sub [r ]); 254 } 255 } 256 } 257} 258 259static void ssm_conv_thread_f32_f32_hvx (unsigned int nth ,unsigned int ith ,void * data ) { 260htp_ssm_conv_preamble ; 261 262const uint32_t d_conv = src1 -> ne [0 ]; 263const uint32_t d_inner = src0 -> ne [1 ]; 264const uint32_t n_t = dst -> ne [1 ]; 265const uint32_t n_s = dst -> ne [2 ]; 266const uint32_t ncs = src0 -> ne [0 ]; 267 268const uint32_t src0_stride_inner = src0 -> nb [1 ] /sizeof (float ); 269const uint32_t src0_stride_seq = src0 -> nb [2 ] /sizeof (float ); 270const uint32_t src1_stride_inner = src1 -> nb [1 ] /sizeof (float ); 271const uint32_t dst_stride_token = dst -> nb [1 ] /sizeof (float ); 272const uint32_t dst_stride_seq = dst -> nb [2 ] /sizeof (float ); 273 274const uint32_t dr = scctx -> nrows_per_thread ; 275const uint32_t ir0 = scctx -> row_start + dr * ith ; 276const uint32_t ir1 = MIN (ir0 + dr ,scctx -> row_start + scctx -> nrows ); 277 278if (ir0 >=ir1 ) { 279return ; 280 } 281 282struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 283htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir0 ); 284 285const uint32_t d_inner_per_thread = ir1 - ir0 ; 286const uint32_t d_inner_stride = scctx -> nrows_per_thread ; 287const uint32_t d_inner_tile = scctx -> d_inner_tile ; 288 289const float * src0_data = (const float * )src0 -> data ; 290const float * src1_data = (const float * )src1 -> data ; 291float * dst_data = (float * )dst -> data ; 292 293// Per-thread VTCM regions. 294float * src0_T = (float * )(octx -> src0_spad .data + ith * octx -> src0_spad .size_per_thread ); 295float * src1_T = (float * )(octx -> src1_spad .data + ith * octx -> src1_spad .size_per_thread ); 296 297// Stage src1 weights once into VTCM in {d_inner_stride, d_conv} layout. 298transpose_src1 (src1_data ,src1_stride_inner ,ir0 ,d_inner_per_thread ,d_inner_stride ,d_conv ,src1_T ); 299 300const uint32_t C_TILE = VLEN_FP32 ; 301 302for (uint32_t i3 = 0 ;i3 < n_s ;++ i3 ) { 303for (uint32_t tile_off = 0 ;tile_off < d_inner_per_thread ;tile_off += d_inner_tile ) { 304const uint32_t tile_n = MIN (d_inner_tile ,d_inner_per_thread - tile_off ); 305 306// Place src0 chunk into VTCM in {d_inner_tile, ncs} layout. 307const float * src0_block = src0_data + i3 * src0_stride_seq + (ir0 + tile_off )* src0_stride_inner ; 308 309for (uint32_t cb = 0 ;cb < tile_n ;cb += C_TILE ) { 310const uint32_t cb_n = MIN (C_TILE ,tile_n - cb ); 311transpose_src0_block (src0_block + cb * src0_stride_inner ,ncs ,cb_n ,d_inner_tile ,src0_T ,cb ); 312 } 313 314for (uint32_t t = 0 ;t < n_t ;++ t ) { 315for (uint32_t cb = 0 ;cb < tile_n ;cb += C_TILE ) { 316const uint32_t cb_n = MIN (C_TILE ,tile_n - cb ); 317 318HVX_Vector acc = hvx_vec_splat_f32 (0.0f ); 319for (uint32_t j = 0 ;j < d_conv ;++ j ) { 320HVX_Vector x = * (const HVX_Vector * ) (src0_T + (t + j )* d_inner_tile + cb ); 321HVX_Vector w = * (const HVX_Vector * ) (src1_T + j * d_inner_stride + tile_off + cb ); 322acc = Q6_Vqf32_vadd_Vqf32Vqf32 (acc ,Q6_Vqf32_vmpy_VsfVsf (x ,w )); 323 } 324 325HVX_Vector y = Q6_Vsf_equals_Vqf32 (acc ); 326 327float * dst_ptr = dst_data + (ir0 + tile_off + cb )+ t * dst_stride_token + i3 * dst_stride_seq ; 328if (cb_n == C_TILE ) { 329* (HVX_UVector * )dst_ptr = y ; 330 }else { 331hvx_vec_store_u (dst_ptr ,cb_n * sizeof (float ),y ); 332 } 333 } 334 } 335 } 336 } 337 338htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )ir1 ); 339 340FARF (HIGH ,"ssm-conv-f32-hvx %d/%d: %ux%ux%ux%u (%u:%u) * %ux%ux%ux%u -> %ux%ux%ux%u\n" , 341ith ,nth ,src0 -> ne [0 ],src0 -> ne [1 ],src0 -> ne [2 ],src0 -> ne [3 ],ir0 ,ir1 , 342src1 -> ne [0 ],src1 -> ne [1 ],src1 -> ne [2 ],src1 -> ne [3 ],dst -> ne [0 ],dst -> ne [1 ], 343dst -> ne [2 ],dst -> ne [3 ]); 344} 345 346int op_ssm_conv_f32 (struct htp_ops_context * octx ) { 347const struct htp_tensor * src0 = octx -> src [0 ]; 348const struct htp_tensor * src1 = octx -> src [1 ]; 349const struct htp_tensor * dst = octx -> dst ; 350 351if (src0 -> type != HTP_TYPE_F32 || src1 -> type != HTP_TYPE_F32 || dst -> type != HTP_TYPE_F32 ) { 352return HTP_STATUS_NO_SUPPORT ; 353 } 354 355const uint32_t d_conv = src1 -> ne [0 ]; 356const uint32_t d_inner = src0 -> ne [1 ]; 357const uint32_t n_t = dst -> ne [1 ];// tokens per sequence 358const uint32_t n_s = dst -> ne [2 ];// number of sequences in the batch 359 360if (octx -> flags & HTP_OPFLAGS_SKIP_COMPUTE ) { 361return HTP_STATUS_OK ; 362 } 363 364uint32_t row_start = 0 ; 365uint32_t nrows = d_inner ; 366 367if (octx -> ctx -> mdev .count > 1 ) { 368const uint32_t elems_per_chunk = VLEN_FP32 ; 369const struct htp_tensor_mdev_range range = htp_tensor_mdev_partition (d_inner ,htp_tensor_mdev_data_aligned (dst ) ?elems_per_chunk :0 ,octx -> ctx -> mdev .idx ,octx -> ctx -> mdev .count ,& octx -> ctx -> mdev .count_div ); 370row_start = range .start ; 371nrows = range .count ; 372 } 373 374if (nrows == 0 ) { 375return HTP_STATUS_OK ; 376 } 377 378const uint32_t n_threads = octx -> n_threads ; 379 380struct htp_ssm_conv_context scctx = {0 }; 381scctx .octx = octx ; 382scctx .row_start = row_start ; 383scctx .nrows = nrows ; 384 385uint32_t use_hvx = 0 ; 386if (nrows >=VLEN_FP32 && n_t >=VLEN_FP32 ) { 387use_hvx = 1 ; 388 } 389 390const uint32_t raw_rpt = fastdiv (nrows + n_threads - 1 ,& octx -> n_threads_div ); 391scctx .nrows_per_thread = hex_round_up (raw_rpt ,VLEN_FP32 ); 392 393const uint32_t d_inner_per_thread = scctx .nrows_per_thread ; 394const uint32_t ncs = src0 -> ne [0 ]; 395 396const uint32_t src1_T_size = hex_round_up (d_conv * d_inner_per_thread * sizeof (float ),256 ); 397const uint32_t src0_T_max = HTP_SSM_CONV_VTCM_BUDGET > src1_T_size ?HTP_SSM_CONV_VTCM_BUDGET - src1_T_size :0 ; 398 399uint32_t d_inner_tile = (src0_T_max /sizeof (float )) /ncs ; 400d_inner_tile -= (d_inner_tile %VLEN_FP32 ); 401if (d_inner_tile == 0 ) { 402FARF (HIGH ,"ssm_conv-f32: inner tile rounds to 0 (ncs=%u), falling back to scalar\n" ,ncs ); 403use_hvx = 0 ; 404 }else { 405scctx .d_inner_tile = d_inner_tile ; 406 407octx -> src0_spad .size_per_thread = hex_round_up (d_inner_tile * ncs * sizeof (float ),256 ); 408octx -> src1_spad .size_per_thread = src1_T_size ; 409octx -> dst_spad .size_per_thread = 0 ; 410 411octx -> src0_spad .size = octx -> src0_spad .size_per_thread * n_threads ; 412octx -> src1_spad .size = octx -> src1_spad .size_per_thread * n_threads ; 413octx -> dst_spad .size = 0 ; 414 415octx -> src0_spad .data = octx -> ctx -> vtcm_base ; 416octx -> src1_spad .data = octx -> src0_spad .data + octx -> src0_spad .size ; 417octx -> src0_spad .src = NULL ; 418octx -> src1_spad .src = NULL ; 419 420const size_t total_spad = octx -> src0_spad .size + octx -> src1_spad .size ; 421if (total_spad > octx -> ctx -> vtcm_size ) { 422FARF (HIGH ,"ssm_conv-f32: scratchpad %zu exceeds VTCM %zu, falling back to scalar\n" , 423total_spad ,octx -> ctx -> vtcm_size ); 424use_hvx = 0 ; 425 } 426 } 427 428FARF (HIGH ,"ssm-conv-f32: (%ux%ux%ux%u) x (%ux%ux%ux%u) -> (%ux%ux%ux%u) : use_hvx %d\n" ,src0 -> ne [0 ], 429src0 -> ne [1 ],src0 -> ne [2 ],src0 -> ne [3 ],src1 -> ne [0 ],src1 -> ne [1 ],src1 -> ne [2 ],src1 -> ne [3 ],dst -> ne [0 ], 430dst -> ne [1 ],dst -> ne [2 ],dst -> ne [3 ],use_hvx ); 431 432if (use_hvx ) { 433work_queue_run (octx -> ctx -> work_queue ,ssm_conv_thread_f32_f32_hvx ,& scctx ,n_threads ); 434 }else { 435work_queue_run (octx -> ctx -> work_queue ,ssm_conv_thread_f32_f32 ,& scctx ,n_threads ); 436 } 437 438return HTP_STATUS_OK ; 439} 440 441int op_ssm_conv (struct htp_ops_context * octx ) { 442const struct htp_tensor * dst = octx -> dst ; 443 444int err = HTP_STATUS_OK ; 445 446switch (dst -> type ) { 447case HTP_TYPE_F32 : 448err = op_ssm_conv_f32 (octx ); 449break ; 450default : 451err = HTP_STATUS_NO_SUPPORT ; 452break ; 453 } 454 455return err ; 456}