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 <hexagon_protos.h> 7#include <hexagon_types.h> 8#include <string.h> 9 10#include "hex-common.h" 11 12#define GGML_COMMON_DECL_C 13#include "ggml-common.h" 14#include "htp-ctx.h" 15#include "htp-ops.h" 16#include "hvx-utils.h" 17#include "hex-dma.h" 18#include "hex-profile.h" 19#include "htp-vtcm.h" 20#include "htp-tensor.h" 21 22struct htp_im2col_context { 23struct htp_ops_context * octx ; 24uint32_t patch_base ;// first patch index assigned to this dev 25uint32_t npatches ;// number of patches assigned to this dev 26uint32_t npatches_per_thread ;// patches = N*OH*OW (pure-DDR kernel) 27 28uint32_t pe_row_base ;// first N*OH row index assigned to this dev (DMA path) 29uint32_t pe_nrows ;// number of N*OH rows assigned to this dev (DMA path) 30uint32_t pe_rows_per_thread ;// N*OH rows per worker 31uint32_t pe_src_row_bytes ;// one output row's source: IC*KH*IW*4, rounded 256 32uint32_t pe_dst_row_bytes ;// one output row's dst: OW*patch_stride*2, rounded 256 33 34// Patch-embed DMA path VTCM ping-pong. 35uint8_t * pe_vtcm_src ;// base of the 2x src buffers region 36uint8_t * pe_vtcm_dst ;// base of the 2x dst buffers region 37uint32_t pe_src_size_per_thread ;// 2 * pe_src_row_bytes 38uint32_t pe_dst_size_per_thread ;// 2 * pe_dst_row_bytes 39}; 40 41// Per-op VTCM layout for the patch-embed DMA path 42struct htp_im2col_vtcm_layout { 43size_t off_src ; 44size_t off_dst ; 45size_t src_bytes_per_thread ; 46size_t dst_bytes_per_thread ; 47size_t total_bytes ; 48}; 49 50static inline void htp_im2col_vtcm_layout_build (struct htp_im2col_vtcm_layout * L , 51size_t src_row_bytes , 52size_t dst_row_bytes , 53uint32_t n_threads ) { 54L -> src_bytes_per_thread = 2 * src_row_bytes ; 55L -> dst_bytes_per_thread = 2 * dst_row_bytes ; 56 57L -> off_src = 0 ; 58L -> off_dst = L -> off_src + L -> src_bytes_per_thread * n_threads ; 59L -> total_bytes = L -> off_dst + L -> dst_bytes_per_thread * n_threads ; 60} 61 62#define IM2COL_PATCHEMBED_BODY (FNAME ,DST_CTYPE ,COPY_FN ,SPLAT_FN ,DST_ELEM ,TAG ) \ 63 static void FNAME(unsigned int nth, unsigned int ith, void * data) { \ 64 struct htp_im2col_context * ictx = (struct htp_im2col_context *) data; \ 65 struct htp_ops_context * octx = ictx->octx; \ 66 struct htp_thread_trace * restrict tr = &octx->ctx->trace[ith]; \ 67 const struct htp_tensor * restrict src0 = octx->src[0]; \ 68 const struct htp_tensor * restrict src1 = octx->src[1]; \ 69 const struct htp_tensor * restrict dst = octx->dst; \ 70 const int32_t s0 = octx->op_params[0], s1 = octx->op_params[1]; \ 71 const int32_t p0 = octx->op_params[2], p1 = octx->op_params[3]; \ 72 const int32_t d0 = octx->op_params[4], d1 = octx->op_params[5]; \ 73 const uint32_t N = src1->ne[3], IC = src1->ne[2], IH = src1->ne[1], IW = src1->ne[0]; \ 74 const uint32_t KH = src0->ne[1], KW = src0->ne[0]; \ 75 const uint32_t OH = dst->ne[2]; \ 76 const uint32_t OW = dst->ne[1]; \ 77 const uint32_t patch_stride = IC * KH * KW; \ 78 const float * restrict src_data = (const float *) src1->data; \ 79 DST_CTYPE * restrict dst_data = (DST_CTYPE *) dst->data; \ 80 const uint32_t patch_end = ictx->patch_base + ictx->npatches; \ 81 const uint32_t patch_start = ictx->patch_base + ictx->npatches_per_thread * ith; \ 82 const uint32_t patch_stop = MIN(patch_start + ictx->npatches_per_thread, patch_end);\ 83 if (patch_start >= patch_stop) { \ 84 return; \ 85 } \ 86 htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_COMP, patch_start); \ 87 for (uint32_t p = patch_start; p < patch_stop; p++) { \ 88 const uint32_t iow = p % OW; \ 89 const uint32_t ioh = (p / OW) % OH; \ 90 const uint32_t in = p / (OW * OH); \ 91 DST_CTYPE * restrict dst_patch = dst_data + (uint64_t) p * patch_stride; \ 92 for (uint32_t iic = 0; iic < IC; iic++) { \ 93 const float * restrict src_plane = src_data + ((uint64_t) in * IC + iic) * IH * IW; \ 94 for (uint32_t ikh = 0; ikh < KH; ikh++) { \ 95 const int32_t iih = (int32_t) ioh * s1 + (int32_t) ikh * d1 - p1; \ 96 DST_CTYPE * restrict out_run = dst_patch + iic * (KH * KW) + ikh * KW; \ 97 if (iih < 0 || iih >= (int32_t) IH) { \ 98 SPLAT_FN(out_run, 0.0f, KW); \ 99 continue; \ 100 } \ 101 const int32_t iiw0 = (int32_t) iow * s0 - p0; \ 102 const float * restrict src_run = src_plane + (uint64_t) iih * IW + iiw0; \ 103 if (d0 == 1) { \ 104/* contiguous source run: [lo,hi) is in-bounds, tails are zero pad */ \ 105const int32_t lo = iiw0 < 0 ?- iiw0 :0 ; \ 106int32_t hi = (int32_t )IW - iiw0 ; \ 107if (hi > (int32_t )KW ) { \ 108hi = (int32_t )KW ; \ 109 } \ 110if (hi <=lo ) { \ 111SPLAT_FN (out_run ,0.0f ,KW ); \ 112 }else { \ 113if (lo > 0 ) { \ 114SPLAT_FN (out_run ,0.0f , (uint32_t )lo ); \ 115 } \ 116COPY_FN ((uint8_t * ) (out_run + lo ), (const uint8_t * ) (src_run + lo ), \ 117 (uint32_t ) (hi - lo )); \ 118if (hi < (int32_t )KW ) { \ 119SPLAT_FN (out_run + hi ,0.0f , (KW - (uint32_t )hi )); \ 120 } \ 121 } \ 122continue ; \ 123 } \ 124for (uint32_t ikw = 0 ;ikw < KW ;ikw ++ ) { \ 125const int32_t iiw = (int32_t )iow * s0 + (int32_t )ikw * d0 - p0 ; \ 126out_run [ikw ]= (iiw < 0 || iiw >= (int32_t )IW ) ? \ 127 (DST_CTYPE )0.0f : \ 128 (DST_CTYPE )src_plane [(uint64_t )iih * IW + iiw ]; \ 129 } \ 130 } \ 131 } \ 132 } \ 133htp_trace_event_stop (tr ,HTP_TRACE_EVT_HVX_COMP ,patch_start ); \ 134 } 135 136IM2COL_PATCHEMBED_BODY (im2col_patchembed_thread ,__fp16 ,hvx_copy_f16_f32_uu ,hvx_splat_f16_u ,sizeof (__fp16 ),"f32-f16" ) 137IM2COL_PATCHEMBED_BODY (im2col_patchembed_f32_thread ,float ,hvx_copy_f32_uu ,hvx_splat_f32_u ,sizeof (float ),"f32-f32" ) 138 139#define IM2COL_PATCHEMBED_DMA_BODY (FNAME ,DST_CTYPE ,COPY_FN ,SPLAT_FN ,DST_ELEM ,TAG ) \ 140 static void FNAME(unsigned int nth, unsigned int ith, void * data) { \ 141 struct htp_im2col_context * ictx = (struct htp_im2col_context *) data; \ 142 struct htp_ops_context * octx = ictx->octx; \ 143 struct htp_thread_trace * restrict tr = &octx->ctx->trace[ith]; \ 144 const struct htp_tensor * restrict src1 = octx->src[1]; \ 145 const struct htp_tensor * restrict dst = octx->dst; \ 146 const uint32_t N = src1->ne[3], IC = src1->ne[2], IH = src1->ne[1], IW = src1->ne[0]; \ 147 const uint32_t KH = octx->src[0]->ne[1], KW = octx->src[0]->ne[0]; \ 148 const uint32_t OH = dst->ne[2], OW = dst->ne[1]; \ 149 const uint32_t patch_stride = IC * KH * KW; \ 150 const float * restrict src_data = (const float *) src1->data; \ 151 DST_CTYPE * restrict dst_data = (DST_CTYPE *) dst->data; \ 152 dma_queue * dmaq = octx->ctx->dma[ith]; \ 153 uint8_t * src_base = ictx->pe_vtcm_src + ith * ictx->pe_src_size_per_thread; \ 154 uint8_t * dst_base = ictx->pe_vtcm_dst + ith * ictx->pe_dst_size_per_thread; \ 155 float * srcb = (float *) src_base; \ 156 DST_CTYPE * dstb = (DST_CTYPE *) dst_base; \ 157 const uint32_t row_end_max = ictx->pe_row_base + ictx->pe_nrows; \ 158 const uint32_t per_thread = ictx->pe_rows_per_thread; \ 159 const uint32_t row_start = ictx->pe_row_base + per_thread * ith; \ 160 const uint32_t row_end = MIN(row_start + per_thread, row_end_max); \ 161 if (row_start >= row_end) \ 162 return; \ 163 for (uint32_t r = row_start; r < row_end; r++) { \ 164 const uint32_t in = r / OH; \ 165 const uint32_t ioh = r % OH; \ 166 for (uint32_t ikh = 0; ikh < KH; ikh++) { \ 167 int32_t iih = (int32_t) ioh * (int32_t) KH + (int32_t) ikh; \ 168 int ok = (iih >= 0 && iih < (int32_t) IH); \ 169 for (uint32_t iic = 0; iic < IC; iic++) { \ 170 float * vdst = srcb + ((uint64_t) (iic * KH + ikh)) * IW; \ 171 const float * _vsrc = \ 172 ok ? (src_data + ((uint64_t) (in * IC + iic) * IH + iih) * IW) : (const float *) vdst; \ 173 dma_queue_push_ddr_to_vtcm( \ 174 dmaq, dma_make_ptr((uint8_t *) vdst, ok ? (const uint8_t *) _vsrc : (const uint8_t *) vdst), \ 175 IW * sizeof(float), IW * sizeof(float), ok ? 1 : 0); \ 176 } \ 177 } \ 178 for (uint32_t i = 0; i < IC * KH; i++) \ 179 dma_queue_pop(dmaq); \ 180 htp_trace_event_start(tr, HTP_TRACE_EVT_HVX_COMP, r); \ 181 for (uint32_t iow = 0; iow < OW; iow++) { \ 182 DST_CTYPE * dst_patch = dstb + (uint64_t) iow * patch_stride; \ 183 for (uint32_t ikh = 0; ikh < KH; ikh++) { \ 184 int32_t iih = (int32_t) ioh * (int32_t) KH + (int32_t) ikh; \ 185 for (uint32_t iic = 0; iic < IC; iic++) { \ 186 DST_CTYPE * out_run = dst_patch + iic * (KH * KW) + ikh * KW; \ 187 if (iih < 0 || iih >= (int32_t) IH) { \ 188 SPLAT_FN(out_run, 0.0f, KW); \ 189 continue; \ 190 } \ 191 const float * src_run = srcb + ((uint64_t) (iic * KH + ikh)) * IW + (uint64_t) iow * KW; \ 192 COPY_FN((uint8_t *) out_run, (const uint8_t *) src_run, KW); \ 193 } \ 194 } \ 195 } \ 196 htp_trace_event_stop(tr, HTP_TRACE_EVT_HVX_COMP, r); \ 197 DST_CTYPE * ddr_row = dst_data + ((uint64_t) (in * OH + ioh) * OW) * patch_stride; \ 198 dma_queue_push_vtcm_to_ddr(dmaq, dma_make_ptr((uint8_t *) ddr_row, (uint8_t *) dstb), \ 199 OW * patch_stride * (DST_ELEM), OW * patch_stride * (DST_ELEM), 1); \ 200 dma_queue_flush(dmaq); \ 201 } \ 202 } 203 204IM2COL_PATCHEMBED_DMA_BODY (im2col_patchembed_dma_thread ,__fp16 ,hvx_copy_f16_f32_uu ,hvx_splat_f16_u ,sizeof (__fp16 ),"pe-dma-f16" ) 205IM2COL_PATCHEMBED_DMA_BODY (im2col_patchembed_dma_f32_thread ,float ,hvx_copy_f32_uu ,hvx_splat_f32_u ,sizeof (float ),"pe-dma-f32" ) 206 207static bool im2col_use_patchembed_dma (const struct htp_ops_context * octx ) { 208const int32_t s0 = octx -> op_params [0 ],s1 = octx -> op_params [1 ]; 209const int32_t p0 = octx -> op_params [2 ],p1 = octx -> op_params [3 ]; 210const int32_t d0 = octx -> op_params [4 ],d1 = octx -> op_params [5 ]; 211const int is_2D = octx -> op_params [6 ]== 1 ; 212if (!is_2D ) { 213return false; 214 } 215if (octx -> dst -> type != HTP_TYPE_F16 && octx -> dst -> type != HTP_TYPE_F32 ) { 216return false; 217 } 218const uint32_t KH = octx -> src [0 ]-> ne [1 ],KW = octx -> src [0 ]-> ne [0 ]; 219if (s0 != (int32_t )KW || s1 != (int32_t )KH ) { 220return false;// non-overlapping 221 } 222if (p0 != 0 || p1 != 0 ) { 223return false;// no padding 224 } 225if (d0 != 1 || d1 != 1 ) { 226return false;// no dilation 227 } 228return true; 229} 230 231// Sizes the per-thread 2x(src,dst) VTCM ping-pong for the patch-embed DMA path. 232// Returns false if it doesn't fit the VTCM budget (caller falls back). 233static bool im2col_patchembed_dma_fits (struct htp_ops_context * octx , 234struct htp_im2col_context * ictx , 235uint32_t n_threads ) { 236const uint32_t IC = octx -> src [1 ]-> ne [2 ],IW = octx -> src [1 ]-> ne [0 ]; 237const uint32_t KH = octx -> src [0 ]-> ne [1 ],KW = octx -> src [0 ]-> ne [0 ]; 238const uint32_t OW = octx -> dst -> ne [1 ]; 239const uint32_t patch_stride = IC * KH * KW ; 240 241ictx -> pe_src_row_bytes = hex_round_up (IC * KH * IW * sizeof (float ),256 ); 242const uint32_t dst_elem = (octx -> dst -> type == HTP_TYPE_F16 ) ?sizeof (__fp16 ) :sizeof (float ); 243ictx -> pe_dst_row_bytes = hex_round_up (OW * patch_stride * dst_elem ,256 ); 244 245// 2 src + 2 dst buffers per thread (ping-pong), src region first then dst. 246struct htp_im2col_vtcm_layout L ; 247htp_im2col_vtcm_layout_build (& L ,ictx -> pe_src_row_bytes ,ictx -> pe_dst_row_bytes ,n_threads ); 248if (L .total_bytes > octx -> ctx -> vtcm_size ) { 249return false; 250 } 251 252uint8_t * const base = octx -> ctx -> vtcm_base ; 253ictx -> pe_vtcm_src = VTCM_LAYOUT_PTR (uint8_t ,base ,L .off_src ); 254ictx -> pe_vtcm_dst = VTCM_LAYOUT_PTR (uint8_t ,base ,L .off_dst ); 255ictx -> pe_src_size_per_thread = (uint32_t )L .src_bytes_per_thread ; 256ictx -> pe_dst_size_per_thread = (uint32_t )L .dst_bytes_per_thread ; 257return true; 258} 259 260int op_im2col (struct htp_ops_context * octx ) { 261const struct htp_tensor * src1 = octx -> src [1 ]; 262const struct htp_tensor * dst = octx -> dst ; 263 264if (src1 -> type != HTP_TYPE_F32 || (dst -> type != HTP_TYPE_F16 && dst -> type != HTP_TYPE_F32 )) { 265FARF (ERROR ,"im2col: only (F32 image -> F16/F32 columns) supported" ); 266return HTP_STATUS_NO_SUPPORT ; 267 } 268 269if (octx -> flags & HTP_OPFLAGS_SKIP_COMPUTE ) { 270return HTP_STATUS_OK ; 271 } 272 273const uint32_t N = src1 -> ne [3 ]; 274const uint32_t OH = dst -> ne [2 ]; 275const uint32_t OW = dst -> ne [1 ]; 276const uint32_t total_patches = N * OH * OW ; 277const uint32_t total_rows = N * OH ; 278 279uint32_t patch_base = 0 ; 280uint32_t npatches = total_patches ; 281if (octx -> ctx -> mdev .count > 1 ) { 282const uint32_t patch_size = dst -> nb [1 ]; 283const uint32_t patches_per_chunk = (patch_size > 0 ) ? (HEX_L2_LINE_SIZE /hex_gcd_u32 (patch_size ,HEX_L2_LINE_SIZE )) :1 ; 284const struct htp_tensor_mdev_range range = htp_tensor_mdev_partition (total_patches ,htp_tensor_mdev_data_aligned (dst ) ?patches_per_chunk :0 ,octx -> ctx -> mdev .idx ,octx -> ctx -> mdev .count ,& octx -> ctx -> mdev .count_div ); 285patch_base = range .start ; 286npatches = range .count ; 287 } 288 289uint32_t row_base = 0 ; 290uint32_t nrows = total_rows ; 291if (octx -> ctx -> mdev .count > 1 ) { 292const uint32_t row_size = dst -> nb [2 ]; 293const uint32_t rows_per_chunk = (row_size > 0 ) ? (HEX_L2_LINE_SIZE /hex_gcd_u32 (row_size ,HEX_L2_LINE_SIZE )) :1 ; 294const struct htp_tensor_mdev_range range = htp_tensor_mdev_partition (total_rows ,htp_tensor_mdev_data_aligned (dst ) ?rows_per_chunk :0 ,octx -> ctx -> mdev .idx ,octx -> ctx -> mdev .count ,& octx -> ctx -> mdev .count_div ); 295row_base = range .start ; 296nrows = range .count ; 297 } 298 299if (npatches == 0 && nrows == 0 ) { 300return HTP_STATUS_OK ; 301 } 302 303const uint32_t n_threads = MIN (octx -> n_threads ,MAX (npatches ,1 )); 304 305struct htp_im2col_context ictx = {0 }; 306ictx .octx = octx ; 307ictx .patch_base = patch_base ; 308ictx .npatches = npatches ; 309ictx .npatches_per_thread = (npatches + n_threads - 1 ) /n_threads ; 310 311// Clean non-overlapping patch-embed -> DMA kernel (if it fits VTCM); 312// everything else (padding/dilation/stride edges) -> pure-DDR kernel. 313if (im2col_use_patchembed_dma (octx )&& nrows > 0 ) { 314const uint32_t pth = MIN (octx -> n_threads ,nrows ); 315if (pth > 0 && im2col_patchembed_dma_fits (octx ,& ictx ,pth )) { 316ictx .pe_row_base = row_base ; 317ictx .pe_nrows = nrows ; 318ictx .pe_rows_per_thread = (nrows + pth - 1 ) /pth ; 319if (dst -> type == HTP_TYPE_F16 ) { 320work_queue_run (octx -> ctx -> work_queue ,im2col_patchembed_dma_thread ,& ictx ,pth ); 321 }else { 322work_queue_run (octx -> ctx -> work_queue ,im2col_patchembed_dma_f32_thread ,& ictx ,pth ); 323 } 324return HTP_STATUS_OK ; 325 } 326// else: doesn't fit -> fall through to the pure-DDR kernel below. 327 } 328 329if (npatches == 0 ) { 330return HTP_STATUS_OK ; 331 } 332 333if (dst -> type == HTP_TYPE_F16 ) { 334work_queue_run (octx -> ctx -> work_queue ,im2col_patchembed_thread ,& ictx ,n_threads ); 335 }else { 336work_queue_run (octx -> ctx -> work_queue ,im2col_patchembed_f32_thread ,& ictx ,n_threads ); 337 } 338return HTP_STATUS_OK ; 339}