char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
eafe15a5e
char/aliceai-t5-moe
1#include "hex-common.h" 2#include "hex-profile.h" 3#include "htp-ctx.h" 4#include "htp-ops.h" 5#include "htp-tensor.h" 6#include "hexagon_types.h" 7#include "hexagon_protos.h" 8#include "hvx_hexagon_protos.h" 9#include "hex-dma.h" 10#include "htp-vtcm.h" 11#include "hvx-utils.h" 12#include "hex-fastdiv.h" 13#include <string.h> 14 15struct htp_concat_context { 16struct htp_ops_context * octx ; 17uint32_t dim ; 18uint32_t nrows_per_thread ; 19uint32_t row_start ; 20uint32_t nrows ; 21uint32_t elem_start ; 22uint32_t nelems ; 23struct fastdiv_values div_ne0 ; 24struct fastdiv_values div_ne1 ; 25struct fastdiv_values div_ne2 ; 26}; 27 28static void concat_2d_f32_transposed (unsigned int nth ,unsigned int ith ,void * data ) { 29struct htp_concat_context * cctx = (struct htp_concat_context * )data ; 30struct htp_ops_context * octx = cctx -> octx ; 31 32const struct htp_tensor * src0 = octx -> src [0 ]; 33const struct htp_tensor * src1 = octx -> src [1 ]; 34const struct htp_tensor * dst = octx -> dst ; 35 36const uint32_t src0_ne0 = src0 -> ne [0 ]; 37const uint32_t src1_ne0 = src1 -> ne [0 ]; 38 39const uint32_t row_end = cctx -> row_start + cctx -> nrows ; 40const uint32_t start_i = cctx -> row_start + ith * cctx -> nrows_per_thread ; 41const uint32_t end_i = (start_i + cctx -> nrows_per_thread < row_end ) ? (start_i + cctx -> nrows_per_thread ) :row_end ; 42if (start_i >=end_i )return ; 43 44dma_queue * q = octx -> ctx -> dma [ith ]; 45 46uint8_t * spad0_base = octx -> src0_spad .data + ith * octx -> src0_spad .size_per_thread ; 47uint8_t * spad1_base = octx -> src1_spad .data + ith * octx -> src1_spad .size_per_thread ; 48 49const uint32_t block_i = 32 ; 50const uint32_t spad1_stride = block_i * sizeof (float ); 51 52int32_t offsets [32 ] __attribute__((aligned (128 ))); 53for (int k = 0 ;k < 32 ;k ++ ) { 54offsets [k ]= k * spad1_stride ; 55 } 56HVX_Vector vv = * (HVX_Vector * )offsets ; 57const uint32_t src1_ne0_padded = hex_round_up (src1_ne0 ,32 ); 58const uint32_t spad0_row_bytes = hex_round_up ((src0_ne0 + src1_ne0_padded )* sizeof (float ),VLEN ); 59uint32_t mu = src1_ne0_padded * spad1_stride ; 60 61struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 62 63for (uint32_t i = start_i ;i < end_i ;i += block_i ) { 64uint32_t current_block_i = (end_i - i < block_i ) ? (end_i - i ) :block_i ; 65 66uint32_t src1_width_bytes = current_block_i * sizeof (float ); 67uint8_t * src1_ptr = (uint8_t * )src1 -> data + i * src1 -> nb [1 ]; 68dma_queue_push (q ,dma_make_ptr (spad1_base ,src1_ptr ),spad1_stride ,src1 -> nb [0 ],src1_width_bytes ,src1_ne0 ); 69 70uint32_t src0_row_bytes = src0_ne0 * sizeof (float ); 71uint8_t * src0_ptr = (uint8_t * )src0 -> data + i * src0 -> nb [1 ]; 72dma_queue_push (q ,dma_make_ptr (spad0_base ,src0_ptr ),spad0_row_bytes ,src0 -> nb [1 ],src0_row_bytes ,current_block_i ); 73 74dma_queue_pop (q );// src1 75 76HVX_Vector * vtcm_tmp = (HVX_Vector * )(spad1_base + src1_ne0_padded * spad1_stride ); 77 78htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )i ); 79for (uint32_t j = 0 ;j < src1_ne0_padded ;j += 32 ) { 80#pragma unroll(4) 81for (uint32_t ii = 0 ;ii < current_block_i ;ii ++ ) { 82size_t rt = (size_t )(spad1_base + j * spad1_stride + ii * sizeof (float )); 83Q6_vgather_ARMVw (& vtcm_tmp [ii ],rt ,mu ,vv ); 84uint8_t * dst_ptr = spad0_base + ii * spad0_row_bytes + (src0_ne0 + j )* sizeof (float ); 85hvx_vmemu (dst_ptr )= vtcm_tmp [ii ]; 86 } 87 } 88htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )i ); 89 90dma_queue_pop (q );// src0 91 92uint8_t * dst_ptr = (uint8_t * )dst -> data + i * dst -> nb [1 ]; 93dma_queue_push (q ,dma_make_ptr (dst_ptr ,spad0_base ),dst -> nb [1 ],spad0_row_bytes , (src0_ne0 + src1_ne0 )* sizeof (float ),current_block_i ); 94 95dma_queue_pop (q ); 96 } 97} 98 99static void concat_2d_f16_transposed (unsigned int nth ,unsigned int ith ,void * data ) { 100struct htp_concat_context * cctx = (struct htp_concat_context * )data ; 101struct htp_ops_context * octx = cctx -> octx ; 102 103const struct htp_tensor * src0 = octx -> src [0 ]; 104const struct htp_tensor * src1 = octx -> src [1 ]; 105const struct htp_tensor * dst = octx -> dst ; 106 107const uint32_t src0_ne0 = src0 -> ne [0 ]; 108const uint32_t src1_ne0 = src1 -> ne [0 ]; 109 110const uint32_t row_end = cctx -> row_start + cctx -> nrows ; 111const uint32_t start_i = cctx -> row_start + ith * cctx -> nrows_per_thread ; 112const uint32_t end_i = (start_i + cctx -> nrows_per_thread < row_end ) ? (start_i + cctx -> nrows_per_thread ) :row_end ; 113if (start_i >=end_i )return ; 114 115dma_queue * q = octx -> ctx -> dma [ith ]; 116 117uint8_t * spad0_base = octx -> src0_spad .data + ith * octx -> src0_spad .size_per_thread ; 118uint8_t * spad1_base = octx -> src1_spad .data + ith * octx -> src1_spad .size_per_thread ; 119 120const uint32_t block_i = 64 ; 121const uint32_t spad1_stride = block_i * sizeof (__fp16 ); 122 123int16_t offsets [64 ] __attribute__((aligned (128 ))); 124for (int k = 0 ;k < 64 ;k ++ ) { 125offsets [k ]= k * spad1_stride ; 126 } 127HVX_Vector vv = * (HVX_Vector * )offsets ; 128const uint32_t src1_ne0_padded = hex_round_up (src1_ne0 ,64 ); 129const uint32_t spad0_row_bytes = hex_round_up ((src0_ne0 + src1_ne0_padded )* sizeof (__fp16 ),VLEN ); 130uint32_t mu = src1_ne0_padded * spad1_stride ; 131 132struct htp_thread_trace * tr = & octx -> ctx -> trace [ith ]; 133 134for (uint32_t i = start_i ;i < end_i ;i += block_i ) { 135uint32_t current_block_i = (end_i - i < block_i ) ? (end_i - i ) :block_i ; 136 137uint32_t src1_width_bytes = current_block_i * sizeof (__fp16 ); 138uint8_t * src1_ptr = (uint8_t * )src1 -> data + i * src1 -> nb [1 ]; 139dma_queue_push (q ,dma_make_ptr (spad1_base ,src1_ptr ),spad1_stride ,src1 -> nb [0 ],src1_width_bytes ,src1_ne0 ); 140 141uint32_t src0_row_bytes = src0_ne0 * sizeof (__fp16 ); 142uint8_t * src0_ptr = (uint8_t * )src0 -> data + i * src0 -> nb [1 ]; 143dma_queue_push (q ,dma_make_ptr (spad0_base ,src0_ptr ),spad0_row_bytes ,src0 -> nb [1 ],src0_row_bytes ,current_block_i ); 144 145dma_queue_pop (q );// src1 146 147HVX_Vector * vtcm_tmp = (HVX_Vector * )(spad1_base + src1_ne0_padded * spad1_stride ); 148 149htp_trace_event_start (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )i ); 150for (uint32_t j = 0 ;j < src1_ne0_padded ;j += 64 ) { 151#pragma unroll(4) 152for (uint32_t ii = 0 ;ii < current_block_i ;ii ++ ) { 153size_t rt = (size_t )(spad1_base + j * spad1_stride + ii * sizeof (__fp16 )); 154Q6_vgather_ARMVh (& vtcm_tmp [ii ],rt ,mu ,vv ); 155uint8_t * dst_ptr = spad0_base + ii * spad0_row_bytes + (src0_ne0 + j )* sizeof (__fp16 ); 156hvx_vmemu (dst_ptr )= vtcm_tmp [ii ]; 157 } 158 } 159htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP , (uint16_t )i ); 160 161dma_queue_pop (q );// src0 162 163uint8_t * dst_ptr = (uint8_t * )dst -> data + i * dst -> nb [1 ]; 164dma_queue_push (q ,dma_make_ptr (dst_ptr ,spad0_base ),dst -> nb [1 ],spad0_row_bytes , (src0_ne0 + src1_ne0 )* sizeof (__fp16 ),current_block_i ); 165 166dma_queue_pop (q ); 167 } 168} 169 170static void concat_generic (unsigned int nth ,unsigned int ith ,void * data ) { 171struct htp_concat_context * cctx = (struct htp_concat_context * )data ; 172struct htp_ops_context * octx = cctx -> octx ; 173 174const struct htp_tensor * src0 = octx -> src [0 ]; 175const struct htp_tensor * src1 = octx -> src [1 ]; 176const struct htp_tensor * dst = octx -> dst ; 177 178const int dim = cctx -> dim ; 179const uint32_t type_size = (dst -> type == HTP_TYPE_F32 || dst -> type == HTP_TYPE_I32 ) ?4 :2 ; 180 181const uint32_t ne [4 ]= {dst -> ne [0 ],dst -> ne [1 ],dst -> ne [2 ],dst -> ne [3 ]}; 182 183// Per-device element range aligned to prevent false sharing 184const uint32_t elem_start = cctx -> elem_start ; 185const uint32_t nelems = cctx -> nelems ; 186const uint32_t chunk_size = (nelems + nth - 1 ) /nth ; 187 188const uint32_t start_idx = MIN (elem_start + ith * chunk_size ,elem_start + nelems ); 189const uint32_t end_idx = MIN (start_idx + chunk_size ,elem_start + nelems ); 190 191// Naive scalar element-wise copy 192for (uint32_t idx = start_idx ;idx < end_idx ;idx ++ ) { 193uint32_t idx_div_ne0 = fastdiv (idx ,& cctx -> div_ne0 ); 194uint32_t i0 = idx - idx_div_ne0 * ne [0 ]; 195 196uint32_t idx_div_ne01 = fastdiv (idx_div_ne0 ,& cctx -> div_ne1 ); 197uint32_t i1 = idx_div_ne0 - idx_div_ne01 * ne [1 ]; 198 199uint32_t idx_div_ne012 = fastdiv (idx_div_ne01 ,& cctx -> div_ne2 ); 200uint32_t i2 = idx_div_ne01 - idx_div_ne012 * ne [2 ]; 201uint32_t i3 = idx_div_ne012 ; 202 203uint8_t * dst_ptr = (uint8_t * )dst -> data + i3 * dst -> nb [3 ]+ i2 * dst -> nb [2 ]+ i1 * dst -> nb [1 ]+ i0 * dst -> nb [0 ]; 204 205uint32_t idx_dim = 0 ; 206if (dim == 0 )idx_dim = i0 ; 207else if (dim == 1 )idx_dim = i1 ; 208else if (dim == 2 )idx_dim = i2 ; 209else if (dim == 3 )idx_dim = i3 ; 210 211const struct htp_tensor * src = (idx_dim < src0 -> ne [dim ]) ?src0 :src1 ; 212 213uint32_t s0 = i0 ; 214uint32_t s1 = i1 ; 215uint32_t s2 = i2 ; 216uint32_t s3 = i3 ; 217 218if (dim == 0 && src == src1 )s0 -= src0 -> ne [0 ]; 219if (dim == 1 && src == src1 )s1 -= src0 -> ne [1 ]; 220if (dim == 2 && src == src1 )s2 -= src0 -> ne [2 ]; 221if (dim == 3 && src == src1 )s3 -= src0 -> ne [3 ]; 222 223uint8_t * src_ptr = (uint8_t * )src -> data + s3 * src -> nb [3 ]+ s2 * src -> nb [2 ]+ s1 * src -> nb [1 ]+ s0 * src -> nb [0 ]; 224 225if (type_size == 4 ) { 226* (float * )dst_ptr = * (float * )src_ptr ; 227 }else { 228* (__fp16 * )dst_ptr = * (__fp16 * )src_ptr ; 229 } 230 } 231} 232 233int op_concat (struct htp_ops_context * octx ) { 234const struct htp_tensor * src0 = octx -> src [0 ]; 235const struct htp_tensor * src1 = octx -> src [1 ]; 236const struct htp_tensor * dst = octx -> dst ; 237 238int dim = octx -> op_params [0 ]; 239 240bool is_2d = dst -> ne [2 ]== 1 && dst -> ne [3 ]== 1 ; 241 242const uint32_t type_size = (dst -> type == HTP_TYPE_F32 || dst -> type == HTP_TYPE_I32 ) ?4 :2 ; 243bool is_src1_transposed = (src1 -> nb [0 ]> src1 -> nb [1 ]); 244bool is_src0_transposed = (src0 -> nb [0 ]> src0 -> nb [1 ]); 245 246uint32_t n_threads = octx -> n_threads ; 247struct htp_concat_context cctx ; 248cctx .octx = octx ; 249cctx .dim = dim ; 250cctx .div_ne0 = init_fastdiv_values (dst -> ne [0 ]); 251cctx .div_ne1 = init_fastdiv_values (dst -> ne [1 ]); 252cctx .div_ne2 = init_fastdiv_values (dst -> ne [2 ]); 253 254void (* worker_func )(unsigned int ,unsigned int ,void * )= concat_generic ; 255 256if (dim == 0 && is_2d && is_src1_transposed && !is_src0_transposed ) { 257const uint32_t total_rows = dst -> ne [1 ]; 258const size_t dst_data_row_size = dst -> ne [0 ]* type_size ; 259uint32_t row_start = 0 ; 260uint32_t nrows = total_rows ; 261if (octx -> ctx -> mdev .count > 1 ) { 262uint32_t rows_per_chunk = 0 ; 263htp_tensor_mdev_rows_per_chunk (dst ,type_size , (uint32_t )dst_data_row_size ,& rows_per_chunk ); 264const struct htp_tensor_mdev_range range = htp_tensor_mdev_partition (total_rows ,rows_per_chunk ,octx -> ctx -> mdev .idx ,octx -> ctx -> mdev .count ,& octx -> ctx -> mdev .count_div ); 265row_start = range .start ; 266nrows = range .count ; 267 } 268 269if (nrows == 0 ) { 270return HTP_STATUS_OK ; 271 } 272 273cctx .row_start = row_start ; 274cctx .nrows = nrows ; 275 276uint32_t block_i = (type_size == 4 ) ?32 :64 ; 277 278cctx .nrows_per_thread = fastdiv (nrows + n_threads - 1 ,& octx -> n_threads_div ); 279 280// Allocate VTCM 281uint32_t spad1_stride = block_i * type_size ; 282 283uint32_t src1_ne0_padded = hex_round_up (src1 -> ne [0 ],block_i ); 284uint32_t spad0_row_bytes = hex_round_up ((src0 -> ne [0 ]+ src1_ne0_padded )* type_size ,VLEN ); 285 286octx -> src0_spad .size_per_thread = block_i * spad0_row_bytes ; 287octx -> src1_spad .size_per_thread = src1_ne0_padded * spad1_stride + block_i * VLEN ; 288 289octx -> src0_spad .size = n_threads * octx -> src0_spad .size_per_thread ; 290octx -> src1_spad .size = n_threads * octx -> src1_spad .size_per_thread ; 291 292if (octx -> src0_spad .size + octx -> src1_spad .size > octx -> ctx -> vtcm_size ) { 293return HTP_STATUS_VTCM_TOO_SMALL ; 294 } 295 296octx -> src0_spad .data = octx -> ctx -> vtcm_base ; 297octx -> src1_spad .data = octx -> src0_spad .data + octx -> src0_spad .size ; 298octx -> src0_spad .src = NULL ; 299octx -> src1_spad .src = NULL ; 300 301if (type_size == 4 ) { 302worker_func = concat_2d_f32_transposed ; 303 }else { 304worker_func = concat_2d_f16_transposed ; 305 } 306 }else { 307const uint32_t total_elements = dst -> ne [0 ]* dst -> ne [1 ]* dst -> ne [2 ]* dst -> ne [3 ]; 308uint32_t elem_start = 0 ; 309uint32_t nelems = total_elements ; 310if (octx -> ctx -> mdev .count > 1 ) { 311const uint32_t elems_per_chunk = HEX_L2_LINE_SIZE /type_size ; 312const bool can_split = htp_tensor_mdev_data_aligned (dst )&& htp_tensor_is_contiguous (dst ,type_size )&& !htp_tensor_is_permuted (dst ); 313const struct htp_tensor_mdev_range range = htp_tensor_mdev_partition (total_elements ,can_split ?elems_per_chunk :0 ,octx -> ctx -> mdev .idx ,octx -> ctx -> mdev .count ,& octx -> ctx -> mdev .count_div ); 314elem_start = range .start ; 315nelems = range .count ; 316 } 317 318if (nelems == 0 ) { 319return HTP_STATUS_OK ; 320 } 321 322cctx .elem_start = elem_start ; 323cctx .nelems = nelems ; 324 } 325 326work_queue_run (octx -> ctx -> work_queue ,worker_func ,& cctx ,n_threads ); 327return HTP_STATUS_OK ; 328}