char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
a43c3986b
char/aliceai-t5-moe
1#include "common.h" 2 3typedef void (im2col_t)( 4 constant ggml_metal_kargs_im2col & args, 5 device const float * x, 6 device char * dst, 7 uint3 tgpig[[threadgroup_position_in_grid]], 8 uint3 tgpg[[threadgroups_per_grid]], 9 uint3 tpitg[[thread_position_in_threadgroup]], 10 uint3 ntg[[threads_per_threadgroup]]); 11 12template <typename T> 13kernel void kernel_im2col( 14 constant ggml_metal_kargs_im2col & args, 15 device const float * x, 16 device char * dst, 17 uint3 tgpig[[threadgroup_position_in_grid]], 18 uint3 tgpg[[threadgroups_per_grid]], 19 uint3 tpitg[[thread_position_in_threadgroup]], 20 uint3 ntg[[threads_per_threadgroup]]) { 21// const int64_t IC = tgpg[0]; 22 const int64_t OH = tgpg[1]; 23 const int64_t OW = tgpg[2]; 24 25 const int64_t KH = ntg[1]; 26 const int64_t KW = ntg[2]; 27 28 int64_t in = tpitg[0]; 29 const int64_t ikh = tpitg[1]; 30 const int64_t ikw = tpitg[2]; 31 32 const int64_t iic = tgpig[0]; 33 const int64_t ioh = tgpig[1]; 34 const int64_t iow = tgpig[2]; 35 36 const int64_t iiw = iow*args.s0 + ikw*args.d0 - args.p0; 37 const int64_t iih = ioh*args.s1 + ikh*args.d1 - args.p1; 38 39 int64_t offset_dst = (in*OH*OW + ioh*OW + iow)*args.CHW + (iic*(KH*KW) + ikh*KW + ikw); 40 41 device T * pdst = (device T *) (dst); 42 43 if (iih < 0 || iih >= args.IH || iiw < 0 || iiw >= args.IW) { 44 while (in < args.N) { 45 pdst[offset_dst] = 0.0f; 46 offset_dst += ntg[0]*args.CHW*OH*OW; 47 48 in += ntg[0]; 49 } 50 } else { 51 int64_t offset_src = in*args.ofs0 + iic*args.ofs1 + iih*args.IW + iiw; 52 53 while (in < args.N) { 54 pdst[offset_dst] = x[offset_src]; 55 56 offset_dst += ntg[0]*args.CHW*OH*OW; 57 offset_src += ntg[0]*args.ofs0; 58 59 in += ntg[0]; 60 } 61 } 62} 63 64template [[host_name("kernel_im2col_f32")]] kernel im2col_t kernel_im2col<float>; 65template [[host_name("kernel_im2col_f16")]] kernel im2col_t kernel_im2col<half>; 66 67// TODO: optimize 68typedef void (im2col_ext_t)( 69 constant ggml_metal_kargs_im2col & args, 70 device const float * x, 71 device char * dst, 72 uint3 tgpig[[threadgroup_position_in_grid]], 73 uint3 tgpg[[threadgroups_per_grid]], 74 uint3 tpitg[[thread_position_in_threadgroup]], 75 uint3 ntg[[threads_per_threadgroup]]); 76 77template <typename T> 78kernel void kernel_im2col_ext( 79 constant ggml_metal_kargs_im2col & args, 80 device const float * x, 81 device char * dst, 82 uint3 tgpig[[threadgroup_position_in_grid]], 83 uint3 tgpg[[threadgroups_per_grid]], // tgpg[0] = D x IC x KH x KW, CHW = IC x KH x KW 84 uint3 tpitg[[thread_position_in_threadgroup]], 85 uint3 ntg[[threads_per_threadgroup]]) { // [M, 1, 1] 86 const int64_t KHW = (int64_t)args.KHW; 87 88 const int64_t d = tgpig[0] / args.CHW; 89 const int64_t chw = tgpig[0] % args.CHW; 90 const int64_t tgpig_0 = chw / KHW; // 0 ~ (IC - 1) 91 const int64_t HW = tgpig[0] % KHW; 92 93 const int64_t tpitg_0 = (d * ntg[0]) + tpitg[0]; 94 if (tpitg_0 >= args.N) { 95 return; 96 } 97 98 const int64_t tpitg_1 = HW / args.KW; 99 const int64_t tpitg_2 = HW % args.KW; 100 101 const int64_t iiw = tgpig[2] * args.s0 + tpitg_2 * args.d0 - args.p0; 102 const int64_t iih = tgpig[1] * args.s1 + tpitg_1 * args.d1 - args.p1; 103 104 const int64_t offset_dst = 105 (tpitg_0 * tgpg[1] * tgpg[2] + tgpig[1] * tgpg[2] + tgpig[2]) * args.CHW + 106 (tgpig_0 * KHW + tpitg_1 * args.KW + tpitg_2); 107 108 device T * pdst = (device T *) (dst); 109 110 if (iih < 0 || iih >= args.IH || iiw < 0 || iiw >= args.IW) { 111 pdst[offset_dst] = 0.0f; 112 } else { 113 const int64_t offset_src = tpitg_0 * args.ofs0 + tgpig_0 * args.ofs1; 114 pdst[offset_dst] = x[offset_src + iih * args.IW + iiw]; 115 } 116} 117 118template [[host_name("kernel_im2col_ext_f32")]] kernel im2col_ext_t kernel_im2col_ext<float>; 119template [[host_name("kernel_im2col_ext_f16")]] kernel im2col_ext_t kernel_im2col_ext<half>; 120 121template <typename T> 122kernel void kernel_col2im_1d( 123 constant ggml_metal_kargs_col2im_1d & args, 124 device const T * col, 125 device T * dst, 126 uint tgpig [[threadgroup_position_in_grid]], 127 uint tpitg [[thread_position_in_threadgroup]], 128 uint ntg [[threads_per_threadgroup]]) { 129 130 const int idx = tgpig * ntg + tpitg; 131 if (idx >= args.T_out * args.OC) { 132 return; 133 } 134 135 const int t_out = idx % args.T_out; 136 const int oc = idx / args.T_out; 137 const int t_abs = t_out + args.p0; // absolute position in uncropped signal 138 139 int t_in_min = (t_abs - args.K + args.s0) / args.s0; // ceil((t_abs - K + 1) / s0) 140 if (t_in_min < 0) { 141 t_in_min = 0; 142 } 143 int t_in_max = t_abs / args.s0; 144 if (t_in_max >= args.T_in) { 145 t_in_max = args.T_in - 1; 146 } 147 148 float sum = 0.0f; 149 for (int t_in = t_in_min; t_in <= t_in_max; t_in++) { 150 const int k = t_abs - t_in * args.s0; 151 sum += float(col[(oc * args.K + k) + t_in * args.K_OC]); 152 } 153 154 dst[t_out + oc * args.T_out] = T(sum); 155} 156 157template [[host_name("kernel_col2im_1d_f32")]] kernel void kernel_col2im_1d<float>(constant ggml_metal_kargs_col2im_1d &, device const float *, device float *, uint, uint, uint); 158template [[host_name("kernel_col2im_1d_f16")]] kernel void kernel_col2im_1d<half>(constant ggml_metal_kargs_col2im_1d &, device const half *, device half *, uint, uint, uint); 159#if defined(GGML_METAL_HAS_BF16) 160template [[host_name("kernel_col2im_1d_bf16")]] kernel void kernel_col2im_1d<bfloat>(constant ggml_metal_kargs_col2im_1d &, device const bfloat *, device bfloat *, uint, uint, uint); 161#endif 162 163template <typename TK> 164kernel void kernel_conv_2d( 165 constant ggml_metal_kargs_conv_2d & args, 166 device const char * weights, 167 device const char * src, 168 device char * dst, 169 uint3 tgpig[[threadgroup_position_in_grid]], 170 uint3 tgpg[[threadgroups_per_grid]], 171 uint3 tpitg[[thread_position_in_threadgroup]], 172 uint3 ntg[[threads_per_threadgroup]]) { 173 174 const uint threads_per_tg = ntg.x * ntg.y * ntg.z; 175 const uint tg_index = (tgpig.z * tgpg.y + tgpig.y) * tgpg.x + tgpig.x; 176 const uint local_thread = tpitg.z * (ntg.x * ntg.y) + tpitg.y * ntg.x + tpitg.x; 177 const uint thread_index = tg_index * threads_per_tg + local_thread; 178 const uint64_t total_threads = (uint64_t) threads_per_tg * tgpg.x * tgpg.y * tgpg.z; 179 const uint64_t total_outputs = (uint64_t) args.N * args.OC * args.OH * args.OW; 180 181 for (uint64_t index = thread_index; index < total_outputs; index += total_threads) { 182 uint64_t tmp = index; 183 184 const int32_t ow = tmp % args.OW; tmp /= args.OW; 185 const int32_t oh = tmp % args.OH; tmp /= args.OH; 186 const int32_t oc = tmp % args.OC; tmp /= args.OC; 187 const int32_t n = tmp; 188 189 float acc = 0.0f; 190 191 const int32_t base_x = ow*args.s0 - args.p0; 192 const int32_t base_y = oh*args.s1 - args.p1; 193 194 int32_t ky_start = 0; 195 if (base_y < 0) { 196 ky_start = (-base_y + args.d1 - 1)/args.d1; 197 } 198 int32_t ky_end = args.KH; 199 const int32_t y_max = args.IH - 1 - base_y; 200 if (y_max < 0) { 201 ky_end = ky_start; 202 } else if (base_y + (args.KH - 1)*args.d1 >= args.IH) { 203 ky_end = min(ky_end, y_max/args.d1 + 1); 204 } 205 206 int32_t kx_start = 0; 207 if (base_x < 0) { 208 kx_start = (-base_x + args.d0 - 1)/args.d0; 209 } 210 int32_t kx_end = args.KW; 211 const int32_t x_max = args.IW - 1 - base_x; 212 if (x_max < 0) { 213 kx_end = kx_start; 214 } else if (base_x + (args.KW - 1)*args.d0 >= args.IW) { 215 kx_end = min(kx_end, x_max/args.d0 + 1); 216 } 217 218 if (ky_start < ky_end && kx_start < kx_end) { 219 const uint64_t src_base_n = (uint64_t) n * args.nb13; 220 const uint64_t w_base_oc = (uint64_t) oc * args.nb03; 221 222 for (int32_t ic = 0; ic < args.IC; ++ic) { 223 const uint64_t src_base_nc = src_base_n + (uint64_t) ic * args.nb12; 224 const uint64_t w_base_ocic = w_base_oc + (uint64_t) ic * args.nb02; 225 226 for (int32_t ky = ky_start; ky < ky_end; ++ky) { 227 const int32_t iy = base_y + ky*args.d1; 228 const uint64_t src_base_row = src_base_nc + (uint64_t) iy * args.nb11; 229 const uint64_t w_base_row = w_base_ocic + (uint64_t) ky * args.nb01; 230 231 for (int32_t kx = kx_start; kx < kx_end; ++kx) { 232 const int32_t ix = base_x + kx*args.d0; 233 const uint64_t src_offs = src_base_row + (uint64_t) ix * args.nb10; 234 const uint64_t w_offs = w_base_row + (uint64_t) kx * args.nb00; 235 236 const float x = *(device const float *)(src + src_offs); 237 const float w = (float) (*(device const TK *)(weights + w_offs)); 238 239 acc += x * w; 240 } 241 } 242 } 243 } 244 245 const uint64_t dst_offs = 246 (uint64_t) n * args.nb3 + 247 (uint64_t) oc * args.nb2 + 248 (uint64_t) oh * args.nb1 + 249 (uint64_t) ow * args.nb0; 250 251 *(device float *)(dst + dst_offs) = acc; 252 } 253} 254 255template [[host_name("kernel_conv_2d_f32_f32")]] 256kernel void kernel_conv_2d<float>( 257 constant ggml_metal_kargs_conv_2d & args, 258 device const char * weights, 259 device const char * src, 260 device char * dst, 261 uint3 tgpig[[threadgroup_position_in_grid]], 262 uint3 tgpg[[threadgroups_per_grid]], 263 uint3 tpitg[[thread_position_in_threadgroup]], 264 uint3 ntg[[threads_per_threadgroup]]); 265 266template [[host_name("kernel_conv_2d_f16_f32")]] 267kernel void kernel_conv_2d<half>( 268 constant ggml_metal_kargs_conv_2d & args, 269 device const char * weights, 270 device const char * src, 271 device char * dst, 272 uint3 tgpig[[threadgroup_position_in_grid]], 273 uint3 tgpg[[threadgroups_per_grid]], 274 uint3 tpitg[[thread_position_in_threadgroup]], 275 uint3 ntg[[threads_per_threadgroup]]); 276 277typedef void (conv_transpose_1d_t)( 278 constant ggml_metal_kargs_conv_transpose_1d & args, 279 device const float * src0, 280 device const float * src1, 281 device char * dst, 282 uint3 tgpig[[threadgroup_position_in_grid]], 283 uint3 tgpg[[threadgroups_per_grid]]); 284 285template <typename T> 286kernel void kernel_conv_transpose_1d( 287 constant ggml_metal_kargs_conv_transpose_1d & args, 288 device const T * src0, 289 device const float * src1, 290 device char * dst, 291 uint3 tgpig[[threadgroup_position_in_grid]], 292 uint3 tgpg[[threadgroups_per_grid]]) { 293 294 // For output position j on the time axis, only input positions 295 // i such that i*s0 <= j < i*s0 + K 296 // contribute -- i.e. i in [ceil((j - K + 1)/s0), floor(j/s0)] 297 // intersected with [0, IL-1]. That's at most ceil(K/s0) values 298 // (typically 2 for stride==K/2 transposed convs). 299 const int32_t j = tgpig[0]; 300 const int32_t s0 = args.s0; 301 const int32_t K = args.K; 302 const int32_t IL = args.IL; 303 304 int32_t i_min; 305 { 306 int32_t a = j - K + 1; 307 i_min = a <= 0 ? 0 : (a + s0 - 1) / s0; // ceil(a/s0) for a>0 308 } 309 int32_t i_max = j / s0; 310 if (i_max > IL - 1) i_max = IL - 1; 311 312 float v = 0.0f; 313 if (i_min <= i_max) { 314 for (int64_t c = 0; c < args.IC; c++) { 315 const int32_t kernel_offset = c * tgpg[1] * K + K * tgpig[1]; 316 const int32_t input_offset = c * IL; 317 318 for (int32_t i = i_min; i <= i_max; i++) { 319 v += float(src0[kernel_offset + j - i * s0]) * src1[input_offset + i]; 320 } 321 } 322 } 323 324 device float * dst_ptr = (device float *) (dst + tgpig[0] * args.nb0 + tgpig[1] * args.nb1); 325 326 dst_ptr[0] = v; 327} 328 329template [[host_name("kernel_conv_transpose_1d_f32_f32")]] 330kernel void kernel_conv_transpose_1d<float>( 331 constant ggml_metal_kargs_conv_transpose_1d & args, 332 device const float * src0, 333 device const float * src1, 334 device char * dst, 335 uint3 tgpig[[threadgroup_position_in_grid]], 336 uint3 tgpg[[threadgroups_per_grid]]); 337 338template [[host_name("kernel_conv_transpose_1d_f16_f32")]] 339kernel void kernel_conv_transpose_1d<half>( 340 constant ggml_metal_kargs_conv_transpose_1d & args, 341 device const half * src0, 342 device const float * src1, 343 device char * dst, 344 uint3 tgpig[[threadgroup_position_in_grid]], 345 uint3 tgpg[[threadgroups_per_grid]]); 346 347 348typedef void (conv_transpose_2d_t)( 349 constant ggml_metal_kargs_conv_transpose_2d & args, 350 device const float * src0, 351 device const float * src1, 352 device char * dst, 353 uint3 tgpig[[threadgroup_position_in_grid]], 354 uint3 tgpg[[threadgroups_per_grid]]); 355 356template <typename T> 357kernel void kernel_conv_transpose_2d( 358 constant ggml_metal_kargs_conv_transpose_2d & args, 359 device const T * src0, 360 device const float * src1, 361 device char * dst, 362 threadgroup float * shared_sum [[threadgroup(0)]], 363 uint3 tgpig[[threadgroup_position_in_grid]], 364 uint3 tpitg[[thread_position_in_threadgroup]], 365 uint3 ntg[[threads_per_threadgroup]]) { 366 367 const int64_t out_x = tgpig[0]; 368 const int64_t out_y = tgpig[1]; 369 const int64_t batch = tgpig[2] / args.OC; 370 const int64_t out_c = tgpig[2] % args.OC; 371 372 const int64_t kw = tpitg[0]; 373 const int64_t kh = tpitg[1]; 374 375 float v = 0.0f; 376 377 for (int64_t in_c = 0; in_c < args.IC; in_c++) { 378 int64_t in_y = out_y - kh; 379 380 if (in_y < 0 || in_y % args.s0) continue; 381 382 in_y /= args.s0; 383 384 if (in_y >= args.IH) continue; 385 386 int64_t in_x = out_x - kw; 387 388 if (in_x < 0 || in_x % args.s0) continue; 389 390 in_x /= args.s0; 391 392 if (in_x >= args.IW) continue; 393 394 const int64_t input_idx = (args.IW * args.IH) * (args.IC * batch + in_c) + (args.IW) * in_y + in_x; 395 const int64_t kernel_idx = (args.KH * args.KW * args.OC) * in_c + (args.KH * args.KW) * out_c + (args.KW) * kh + kw; 396 397 v += (float)src0[kernel_idx] * src1[input_idx]; 398 } 399 400 const uint tid = tpitg.y * ntg.x + tpitg.x; 401 shared_sum[tid] = v; 402 403 threadgroup_barrier(mem_flags::mem_threadgroup); 404 405 if (tid == 0) { 406 float total = 0.0f; 407 const uint num_threads = ntg.x * ntg.y; 408 for (uint i = 0; i < num_threads; i++) { 409 total += shared_sum[i]; 410 } 411 412 device float * dst_ptr = (device float *) (dst + batch*args.nb3 + out_c*args.nb2 + out_y * args.nb1 + out_x*args.nb0); 413 dst_ptr[0] = total; 414 } 415} 416 417template [[host_name("kernel_conv_transpose_2d_f32_f32")]] 418kernel void kernel_conv_transpose_2d<float>( 419 constant ggml_metal_kargs_conv_transpose_2d & args, 420 device const float * src0, 421 device const float * src1, 422 device char * dst, 423 threadgroup float * shared_sum [[threadgroup(0)]], 424 uint3 tgpig[[threadgroup_position_in_grid]], 425 uint3 tpitg[[thread_position_in_threadgroup]], 426 uint3 ntg[[threads_per_threadgroup]]); 427 428template [[host_name("kernel_conv_transpose_2d_f16_f32")]] 429kernel void kernel_conv_transpose_2d<half>( 430 constant ggml_metal_kargs_conv_transpose_2d & args, 431 device const half * src0, 432 device const float * src1, 433 device char * dst, 434 threadgroup float * shared_sum [[threadgroup(0)]], 435 uint3 tgpig[[threadgroup_position_in_grid]], 436 uint3 tpitg[[thread_position_in_threadgroup]], 437 uint3 ntg[[threads_per_threadgroup]]); 438 439// grid: x = C tile, y = OH, z = OW * N (for channel-contiguous layouts) 440template <typename TK> 441kernel void kernel_conv_2d_dw_tiled( 442 constant ggml_metal_kargs_conv_2d_dw & args, 443 device const char * weights, 444 device const char * src, 445 device char * dst, 446 uint3 tgpig[[threadgroup_position_in_grid]], 447 uint3 tpitg[[thread_position_in_threadgroup]], 448 uint3 ntg[[threads_per_threadgroup]]) { 449 450 const int32_t c = (int32_t)(tgpig.x * ntg.x + tpitg.x); 451 if (c >= args.C) { 452 return; 453 } 454 455 const int32_t oh = tgpig.y; 456 const int32_t own = tgpig.z; 457 const int32_t ow = own % args.OW; 458 const int32_t n = own / args.OW; 459 460 const int32_t base_y = oh*args.s1 - args.p1; 461 462 int32_t ky_start = 0; 463 if (base_y < 0) { 464 ky_start = (-base_y + args.d1 - 1)/args.d1; 465 } 466 int32_t ky_end = args.KH; 467 const int32_t y_max = args.IH - 1 - base_y; 468 if (y_max < 0) { 469 ky_end = ky_start; 470 } else if (base_y + (args.KH - 1)*args.d1 >= args.IH) { 471 ky_end = min(ky_end, y_max/args.d1 + 1); 472 } 473 474 const int32_t base_x = ow*args.s0 - args.p0; 475 476 int32_t kx_start = 0; 477 if (base_x < 0) { 478 kx_start = (-base_x + args.d0 - 1)/args.d0; 479 } 480 int32_t kx_end = args.KW; 481 const int32_t x_max = args.IW - 1 - base_x; 482 if (x_max < 0) { 483 kx_end = kx_start; 484 } else if (base_x + (args.KW - 1)*args.d0 >= args.IW) { 485 kx_end = min(kx_end, x_max/args.d0 + 1); 486 } 487 488 float acc = 0.0f; 489 490 if (ky_start < ky_end && kx_start < kx_end) { 491 const uint64_t w_base = (uint64_t) c * args.nb02; 492 const uint64_t src_base = (uint64_t) n * args.nb13 + (uint64_t) c * args.nb12; 493 494 for (int32_t ky = ky_start; ky < ky_end; ++ky) { 495 const int32_t iy = base_y + ky*args.d1; 496 const uint64_t src_row = src_base + (uint64_t) iy * args.nb11; 497 const uint64_t w_row = w_base + (uint64_t) ky * args.nb01; 498 499 for (int32_t kx = kx_start; kx < kx_end; ++kx) { 500 const int32_t ix = base_x + kx*args.d0; 501 const float x = *(device const float *)(src + src_row + (uint64_t) ix * args.nb10); 502 const float w = (float)(*(device const TK *)(weights + w_row + (uint64_t) kx * args.nb00)); 503 acc += x * w; 504 } 505 } 506 } 507 508 const uint64_t dst_offs = 509 (uint64_t) n * args.nb3 + 510 (uint64_t) c * args.nb2 + 511 (uint64_t) oh * args.nb1 + 512 (uint64_t) ow * args.nb0; 513 514 *(device float *)(dst + dst_offs) = acc; 515} 516 517// grid: x = OW tile, y = OH, z = C * N (for spatially-contiguous layouts) 518template <typename TK> 519kernel void kernel_conv_2d_dw( 520 constant ggml_metal_kargs_conv_2d_dw & args, 521 device const char * weights, 522 device const char * src, 523 device char * dst, 524 uint3 tgpig[[threadgroup_position_in_grid]], 525 uint3 tpitg[[thread_position_in_threadgroup]], 526 uint3 ntg[[threads_per_threadgroup]]) { 527 528 const int32_t oh = tgpig.y; 529 const int32_t cn = tgpig.z; 530 const int32_t c = cn % args.C; 531 const int32_t n = cn / args.C; 532 533 const int32_t base_y = oh*args.s1 - args.p1; 534 535 int32_t ky_start = 0; 536 if (base_y < 0) { 537 ky_start = (-base_y + args.d1 - 1)/args.d1; 538 } 539 int32_t ky_end = args.KH; 540 const int32_t y_max = args.IH - 1 - base_y; 541 if (y_max < 0) { 542 ky_end = ky_start; 543 } else if (base_y + (args.KH - 1)*args.d1 >= args.IH) { 544 ky_end = min(ky_end, y_max/args.d1 + 1); 545 } 546 547 const uint64_t w_base = (uint64_t) c * args.nb02; 548 const uint64_t src_base = (uint64_t) n * args.nb13 + (uint64_t) c * args.nb12; 549 550 const int32_t ow = (int32_t)(tgpig.x * ntg.x + tpitg.x); 551 if (ow >= args.OW) { 552 return; 553 } 554 555 float acc = 0.0f; 556 557 const int32_t base_x = ow*args.s0 - args.p0; 558 559 int32_t kx_start = 0; 560 if (base_x < 0) { 561 kx_start = (-base_x + args.d0 - 1)/args.d0; 562 } 563 int32_t kx_end = args.KW; 564 const int32_t x_max = args.IW - 1 - base_x; 565 if (x_max < 0) { 566 kx_end = kx_start; 567 } else if (base_x + (args.KW - 1)*args.d0 >= args.IW) { 568 kx_end = min(kx_end, x_max/args.d0 + 1); 569 } 570 571 if (ky_start < ky_end && kx_start < kx_end) { 572 for (int32_t ky = ky_start; ky < ky_end; ++ky) { 573 const int32_t iy = base_y + ky*args.d1; 574 const uint64_t src_row = src_base + (uint64_t) iy * args.nb11; 575 const uint64_t w_row = w_base + (uint64_t) ky * args.nb01; 576 577 for (int32_t kx = kx_start; kx < kx_end; ++kx) { 578 const int32_t ix = base_x + kx*args.d0; 579 const float x = *(device const float *)(src + src_row + (uint64_t) ix * args.nb10); 580 const float w = (float)(*(device const TK *)(weights + w_row + (uint64_t) kx * args.nb00)); 581 acc += x * w; 582 } 583 } 584 } 585 586 const uint64_t dst_offs = 587 (uint64_t) n * args.nb3 + 588 (uint64_t) c * args.nb2 + 589 (uint64_t) oh * args.nb1 + 590 (uint64_t) ow * args.nb0; 591 592 *(device float *)(dst + dst_offs) = acc; 593} 594 595template [[host_name("kernel_conv_2d_dw_f32_f32")]] 596kernel void kernel_conv_2d_dw<float>( 597 constant ggml_metal_kargs_conv_2d_dw & args, 598 device const char * weights, 599 device const char * src, 600 device char * dst, 601 uint3 tgpig[[threadgroup_position_in_grid]], 602 uint3 tpitg[[thread_position_in_threadgroup]], 603 uint3 ntg[[threads_per_threadgroup]]); 604 605template [[host_name("kernel_conv_2d_dw_f16_f32")]] 606kernel void kernel_conv_2d_dw<half>( 607 constant ggml_metal_kargs_conv_2d_dw & args, 608 device const char * weights, 609 device const char * src, 610 device char * dst, 611 uint3 tgpig[[threadgroup_position_in_grid]], 612 uint3 tpitg[[thread_position_in_threadgroup]], 613 uint3 ntg[[threads_per_threadgroup]]); 614 615template [[host_name("kernel_conv_2d_dw_tiled_f32_f32")]] 616kernel void kernel_conv_2d_dw_tiled<float>( 617 constant ggml_metal_kargs_conv_2d_dw & args, 618 device const char * weights, 619 device const char * src, 620 device char * dst, 621 uint3 tgpig[[threadgroup_position_in_grid]], 622 uint3 tpitg[[thread_position_in_threadgroup]], 623 uint3 ntg[[threads_per_threadgroup]]); 624 625template [[host_name("kernel_conv_2d_dw_tiled_f16_f32")]] 626kernel void kernel_conv_2d_dw_tiled<half>( 627 constant ggml_metal_kargs_conv_2d_dw & args, 628 device const char * weights, 629 device const char * src, 630 device char * dst, 631 uint3 tgpig[[threadgroup_position_in_grid]], 632 uint3 tpitg[[thread_position_in_threadgroup]], 633 uint3 ntg[[threads_per_threadgroup]]); 634 635template <typename T> 636kernel void kernel_conv_3d( 637 constant ggml_metal_kargs_conv_3d & args, 638 device const char * src0, // Weights [IC * OC, KD, KH, KW] 639 device const char * src1, // Inputs [IC * N, ID, IH, IW] 640 device char * dst, // Outputs [OC * N, OD, OH, OW] 641 uint3 tgpig[[threadgroup_position_in_grid]], 642 uint3 tpitg[[thread_position_in_threadgroup]]) { 643 644 // 1. Un-flatten the spatial dimension from Grid X 645 int64_t spatial_idx = tgpig.x * 32 + tpitg.x; 646 647 if (spatial_idx >= args.OW * args.OH * args.OD) { 648 return; // Thread falls outside the spatial volume 649 } 650 651 int64_t od = spatial_idx / (args.OW * args.OH); 652 int64_t oh = (spatial_idx / args.OW) % args.OH; 653 int64_t ow = spatial_idx % args.OW; 654 655 // 2. Map Y to Channels, Z to Batch 656 int64_t oc = tgpig.y; 657 int64_t batch_idx = tgpig.z; 658 659 // 3. Calculate anchor coordinates in the Input volume 660 int64_t i_w_base = ow * args.s0 - args.p0; 661 int64_t i_h_base = oh * args.s1 - args.p1; 662 int64_t i_d_base = od * args.s2 - args.p2; 663 664 float sum = 0.0f; 665 666 // 4. Gather Loop (Iterate over Input Channels -> Depth -> Height -> Width) 667 for (int64_t ic = 0; ic < args.IC; ++ic) { 668 669 // ggml packs batch and channel together in the 4th dimension 670 int64_t src_cn_idx = batch_idx * args.IC + ic; 671 int64_t w_cn_idx = oc * args.IC + ic; 672 673 for (int64_t kz = 0; kz < args.KD; ++kz) { 674 int64_t id = i_d_base + kz * args.d2; 675 if (id < 0 || id >= args.ID) continue; // Boundary check (Padding) 676 677 for (int64_t ky = 0; ky < args.KH; ++ky) { 678 int64_t ih = i_h_base + ky * args.d1; 679 if (ih < 0 || ih >= args.IH) continue; 680 681 for (int64_t kx = 0; kx < args.KW; ++kx) { 682 int64_t iw = i_w_base + kx * args.d0; 683 if (iw < 0 || iw >= args.IW) continue; 684 685 // Convert multi-dimensional coordinates to flat byte offsets 686 int64_t w_idx = kx*args.nb00 + ky*args.nb01 + kz*args.nb02 + w_cn_idx*args.nb03; 687 int64_t i_idx = iw*args.nb10 + ih*args.nb11 + id*args.nb12 + src_cn_idx*args.nb13; 688 689 // Dereference memory and cast weights to f32 if they were f16 690 float w_val = (float)*(device const T*)((device const char*)src0 + w_idx); 691 float i_val = *(device const float*)((device const char*)src1 + i_idx); 692 693 sum += w_val * i_val; 694 } 695 } 696 } 697 } 698 699 // 5. Write the accumulated value out to RAM 700 int64_t dst_cn_idx = batch_idx * args.OC + oc; 701 int64_t d_idx = ow*args.nb0 + oh*args.nb1 + od*args.nb2 + dst_cn_idx*args.nb3; 702 703 *(device float*)(dst + d_idx) = sum; 704} 705 706// Explicit instantiations so the JIT compiler can find them by name 707template [[host_name("kernel_conv_3d_f32_f32")]] 708kernel void kernel_conv_3d<float>( 709 constant ggml_metal_kargs_conv_3d & args, 710 device const char * src0, 711 device const char * src1, 712 device char * dst, 713 uint3 tgpig[[threadgroup_position_in_grid]], 714 uint3 tpitg[[thread_position_in_threadgroup]]); 715 716// Explicit instantiation for f16 weights 717template [[host_name("kernel_conv_3d_f16_f32")]] 718kernel void kernel_conv_3d<half>( 719 constant ggml_metal_kargs_conv_3d & args, 720 device const char * src0, 721 device const char * src1, 722 device char * dst, 723 uint3 tgpig[[threadgroup_position_in_grid]], 724 uint3 tpitg[[thread_position_in_threadgroup]]);