char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
11cd98842
char/aliceai-t5-moe
1#include "common.h" 2 3// ref: ggml.c:ggml_compute_forward_ssm_conv_f32 4kernel void kernel_ssm_conv_f32_f32( 5 constant ggml_metal_kargs_ssm_conv & args, 6 device const void * src0, 7 device const void * src1, 8 device float * dst, 9 uint3 tgpig[[threadgroup_position_in_grid]], 10 uint3 tpitg[[thread_position_in_threadgroup]], 11 uint3 ntg[[threads_per_threadgroup]]) { 12 const int64_t ir = tgpig.x; 13 const int64_t i2 = tgpig.y; 14 const int64_t i3 = tgpig.z; 15 16 const int64_t nc = args.ne10; 17 //const int64_t ncs = args.ne00; 18 //const int64_t nr = args.ne01; 19 //const int64_t n_t = args.ne1; 20 //const int64_t n_s = args.ne2; 21 22 device const float * s = (device const float *) ((device const char *) src0 + ir*args.nb01 + i2*args.nb00 + i3*args.nb02); 23 device const float * c = (device const float *) ((device const char *) src1 + ir*args.nb11); 24 device float * x = (device float *) ((device char *) dst + ir*args.nb0 + i2*args.nb1 + i3*args.nb2); 25 26 float sumf = 0.0f; 27 28 for (int64_t i0 = 0; i0 < nc; ++i0) { 29 sumf += s[i0] * c[i0]; 30 } 31 32 x[0] = sumf; 33} 34 35kernel void kernel_ssm_conv_f32_f32_4( 36 constant ggml_metal_kargs_ssm_conv & args, 37 device const void * src0, 38 device const void * src1, 39 device float * dst, 40 uint3 tgpig[[threadgroup_position_in_grid]], 41 uint3 tpitg[[thread_position_in_threadgroup]], 42 uint3 ntg[[threads_per_threadgroup]]) { 43 const int64_t ir = tgpig.x; 44 const int64_t i2 = tgpig.y; 45 const int64_t i3 = tgpig.z; 46 47 const int64_t nc = args.ne10; 48 //const int64_t ncs = args.ne00; 49 //const int64_t nr = args.ne01; 50 //const int64_t n_t = args.ne1; 51 //const int64_t n_s = args.ne2; 52 53 device const float4 * s = (device const float4 *) ((device const char *) src0 + ir*args.nb01 + i2*args.nb00 + i3*args.nb02); 54 device const float4 * c = (device const float4 *) ((device const char *) src1 + ir*args.nb11); 55 device float * x = (device float *) ((device char *) dst + ir*args.nb0 + i2*args.nb1 + i3*args.nb2); 56 57 float sumf = 0.0f; 58 59 for (int64_t i0 = 0; i0 < nc/4; ++i0) { 60 sumf += dot(s[i0], c[i0]); 61 } 62 63 x[0] = sumf; 64} 65 66constant short FC_ssm_conv_bs [[function_constant(FC_SSM_CONV + 0)]]; 67 68// Batched version: each threadgroup processes multiple tokens for better efficiency 69// Thread layout: each thread handles one token, threadgroup covers BATCH_SIZE tokens 70kernel void kernel_ssm_conv_f32_f32_batched( 71 constant ggml_metal_kargs_ssm_conv & args, 72 device const void * src0, 73 device const void * src1, 74 device float * dst, 75 uint3 tgpig[[threadgroup_position_in_grid]], 76 uint3 tpitg[[thread_position_in_threadgroup]], 77 uint3 ntg[[threads_per_threadgroup]]) { 78 // tgpig.x = row index (ir) 79 // tgpig.y = batch of tokens (i2_base / BATCH_SIZE) 80 // tgpig.z = sequence index (i3) 81 // tpitg.x = thread within batch (0..BATCH_SIZE-1) 82 const short BATCH_SIZE = FC_ssm_conv_bs; 83 84 const int64_t ir = tgpig.x; 85 const int64_t i2_base = tgpig.y * BATCH_SIZE; 86 const int64_t i3 = tgpig.z; 87 const int64_t i2_off = tpitg.x; 88 const int64_t i2 = i2_base + i2_off; 89 90 const int64_t nc = args.ne10; // conv kernel size (typically 4) 91 const int64_t n_t = args.ne1; // number of tokens 92 93 // Bounds check for partial batches at the end 94 if (i2 >= n_t) { 95 return; 96 } 97 98 // Load conv weights (shared across all tokens for this row) 99 device const float * c = (device const float *) ((device const char *) src1 + ir*args.nb11); 100 101 // Load source for this specific token 102 device const float * s = (device const float *) ((device const char *) src0 + ir*args.nb01 + i2*args.nb00 + i3*args.nb02); 103 104 // Output location for this token 105 device float * x = (device float *) ((device char *) dst + ir*args.nb0 + i2*args.nb1 + i3*args.nb2); 106 107 float sumf = 0.0f; 108 for (int64_t i0 = 0; i0 < nc; ++i0) { 109 sumf += s[i0] * c[i0]; 110 } 111 112 x[0] = sumf; 113} 114 115kernel void kernel_ssm_conv_f32_f32_batched_4( 116 constant ggml_metal_kargs_ssm_conv & args, 117 device const void * src0, 118 device const void * src1, 119 device float * dst, 120 uint3 tgpig[[threadgroup_position_in_grid]], 121 uint3 tpitg[[thread_position_in_threadgroup]], 122 uint3 ntg[[threads_per_threadgroup]]) { 123 // tgpig.x = row index (ir) 124 // tgpig.y = batch of tokens (i2_base / BATCH_SIZE) 125 // tgpig.z = sequence index (i3) 126 // tpitg.x = thread within batch (0..BATCH_SIZE-1) 127 const short BATCH_SIZE = FC_ssm_conv_bs; 128 129 const int64_t ir = tgpig.x; 130 const int64_t i2_base = tgpig.y * BATCH_SIZE; 131 const int64_t i3 = tgpig.z; 132 const int64_t i2_off = tpitg.x; 133 const int64_t i2 = i2_base + i2_off; 134 135 const int64_t nc = args.ne10; // conv kernel size (typically 4) 136 const int64_t n_t = args.ne1; // number of tokens 137 138 // Bounds check for partial batches at the end 139 if (i2 >= n_t) { 140 return; 141 } 142 143 // Load conv weights (shared across all tokens for this row) 144 device const float4 * c = (device const float4 *) ((device const char *) src1 + ir*args.nb11); 145 146 // Load source for this specific token 147 device const float4 * s = (device const float4 *) ((device const char *) src0 + ir*args.nb01 + i2*args.nb00 + i3*args.nb02); 148 149 // Output location for this token 150 device float * x = (device float *) ((device char *) dst + ir*args.nb0 + i2*args.nb1 + i3*args.nb2); 151 152 float sumf = 0.0f; 153 for (int64_t i0 = 0; i0 < nc/4; ++i0) { 154 sumf += dot(s[i0], c[i0]); 155 } 156 157 x[0] = sumf; 158} 159 160// ref: ggml.c:ggml_compute_forward_ssm_scan_f32, Mamba-2 part 161// Optimized version: reduces redundant memory loads by having one thread load shared values 162// TAIL == false is the whole-sequence / decode path: token_offset folds away at compile time. 163template<bool TAIL> 164kernel void kernel_ssm_scan_impl( 165 constant ggml_metal_kargs_ssm_scan & args, 166 device const void * src0, 167 device const void * src1, 168 device const void * src2, 169 device const void * src3, 170 device const void * src4, 171 device const void * src5, 172 device const void * src6, 173 device float * dst, 174 threadgroup float * shared [[threadgroup(0)]], 175 uint3 tgpig[[threadgroup_position_in_grid]], 176 ushort3 tpitg[[thread_position_in_threadgroup]], 177 ushort sgitg[[simdgroup_index_in_threadgroup]], 178 ushort tiisg[[thread_index_in_simdgroup]], 179 ushort sgptg[[simdgroups_per_threadgroup]], 180 uint3 tgpg[[threadgroups_per_grid]]) { 181 constexpr short NW = N_SIMDWIDTH; 182 183 // Shared memory layout: 184 // [0..sgptg*NW-1]: partial sums for reduction (existing) 185 // [sgptg*NW..sgptg*NW+sgptg-1]: pre-computed x_dt values for each token in batch 186 // [sgptg*NW+sgptg..sgptg*NW+2*sgptg-1]: pre-computed dA values for each token in batch 187 threadgroup float * shared_sums = shared; 188 threadgroup float * shared_x_dt = shared + sgptg * NW; 189 threadgroup float * shared_dA = shared + sgptg * NW + sgptg; 190 191 shared_sums[tpitg.x] = 0.0f; 192 193 const int32_t i0 = tpitg.x; 194 const int32_t i1 = tgpig.x; 195 const int32_t ir = tgpig.y; // current head 196 const int32_t i3 = tgpig.z; // current seq 197 198 const int32_t nc = args.d_state; 199 const int32_t nr = args.d_inner; 200 const int32_t nh = args.n_head; 201 const int32_t ng = args.n_group; 202 const int32_t n_t = args.n_seq_tokens; 203 const int32_t n_s = args.n_seqs; 204 const int32_t K = args.K; 205 const int32_t n_t_total = TAIL ? args.n_seq_tokens_total : n_t; 206 const int32_t t_off = TAIL ? args.token_offset : 0; 207 208 const int32_t s_off = args.s_off; 209 210 device const int32_t * ids = (device const int32_t *) src6; 211 212 device float * s_buff = (device float *) ((device char *) dst + ir*args.nb02 + i3*args.nb03 + s_off); 213 device const float * s0_buff = t_off != 0 ? 214 s_buff : 215 (device const float *) ((device const char *) src0 + ir*args.nb02 + ids[i3]*args.nb03); 216 217 const int32_t i = i0 + i1*nc; 218 const int32_t g = ir / (nh / ng); // repeat_interleave 219 220 float s0 = s0_buff[i]; 221 float s = 0.0f; 222 223 device const float * A = (device const float *) ((device const char *) src3 + ir*args.nb31); // {ne30, nh} 224 225 const float A0 = A[i0%args.ne30]; 226 227 device const float * x = (device const float *)((device const char *) src1 + i1*args.nb10 + ir*args.nb11 + t_off*args.nb12 + i3*args.nb13); // {dim, nh, nt, ns} 228 device const float * dt = (device const float *)((device const char *) src2 + ir*args.nb20 + t_off*args.nb21 + i3*args.nb22); // {nh, nt, ns} 229 device const float * B = (device const float *)((device const char *) src4 + g*args.nb41 + t_off*args.nb42 + i3*args.nb43); // {d_state, ng, nt, ns} 230 device const float * C = (device const float *)((device const char *) src5 + g*args.nb51 + t_off*args.nb52 + i3*args.nb53); // {d_state, ng, nt, ns} 231 232 device float * y = dst + (i1 + ir*nr + t_off*nh*nr + i3*(n_t_total*nh*nr)); // {dim, nh, nt, ns} 233 234 for (int i2 = 0; i2 < n_t; i2 += sgptg) { 235 threadgroup_barrier(mem_flags::mem_threadgroup); 236 237 // Pre-compute x_dt and dA for this batch of tokens 238 // Only first sgptg threads do the loads and expensive math 239 if (i0 < sgptg && i2 + i0 < n_t) { 240 // ns12 and ns21 are element strides (nb12/nb10, nb21/nb20) 241 device const float * x_t = x + i0 * args.ns12; 242 device const float * dt_t = dt + i0 * args.ns21; 243 244 const float dt0 = dt_t[0]; 245 const float dtsp = dt0 <= 20.0f ? log(1.0f + exp(dt0)) : dt0; 246 shared_x_dt[i0] = x_t[0] * dtsp; 247 shared_dA[i0] = dtsp; // Store dtsp, compute exp(dtsp * A0) per-thread since A0 varies 248 } 249 250 threadgroup_barrier(mem_flags::mem_threadgroup); 251 252 for (int t = 0; t < sgptg && i2 + t < n_t; t++) { 253 const float x_dt = shared_x_dt[t]; 254 const float dA = exp(shared_dA[t] * A0); 255 256 s = (s0 * dA) + (B[i0] * x_dt); 257 258 const float sumf = simd_sum(s * C[i0]); 259 260 if (tiisg == 0) { 261 shared_sums[t*NW + sgitg] = sumf; 262 } 263 264 // recurse 265 s0 = s; 266 267 const int32_t slot = n_t - 1 - (i2 + t); 268 if (slot > 0 && slot < K) { 269 device float * s_snapshot = (device float *) ((device char *) s_buff + (int64_t) slot*n_s*args.nb03); 270 s_snapshot[i] = s; 271 } 272 273 B += args.ns42; 274 C += args.ns52; 275 } 276 277 // Advance pointers for next batch 278 x += sgptg * args.ns12; 279 dt += sgptg * args.ns21; 280 281 threadgroup_barrier(mem_flags::mem_threadgroup); 282 283 const float sumf = simd_sum(shared_sums[sgitg*NW + tiisg]); 284 285 if (tiisg == 0 && i2 + sgitg < n_t) { 286 y[sgitg*nh*nr] = sumf; 287 } 288 289 y += sgptg*nh*nr; 290 } 291 292 s_buff[i] = s; 293} 294 295typedef decltype(kernel_ssm_scan_impl<false>) kernel_ssm_scan_t; 296 297template [[host_name("kernel_ssm_scan_f32")]] kernel kernel_ssm_scan_t kernel_ssm_scan_impl<false>; 298template [[host_name("kernel_ssm_scan_f32_tail")]] kernel kernel_ssm_scan_t kernel_ssm_scan_impl<true>; 299 300// Chunked SSD SSM scan via Metal simdgroup MMatrix Multiply-Accumulate (simdgroup_float8x8) fast path. 301// One threadgroup per (head, sequence) and tokens are processed in chunks. 302// C*B^T computed in each chunk one time and reused across the head_dim channel tiles. 303kernel void kernel_ssm_scan_ssd_mma_f32( 304 constant ggml_metal_kargs_ssm_scan & args, 305 device const void * src0, 306 device const void * src1, 307 device const void * src2, 308 device const void * src3, 309 device const void * src4, 310 device const void * src5, 311 device const void * src6, 312 device float * dst, 313 threadgroup float * shared [[threadgroup(0)]], 314 uint3 tgpig[[threadgroup_position_in_grid]], 315 ushort tiitg[[thread_index_in_threadgroup]], 316 ushort sgitg[[simdgroup_index_in_threadgroup]], 317 ushort tiisg[[thread_index_in_simdgroup]]) { 318 constexpr short CS = OP_SSM_SCAN_SSD_CS; 319 constexpr short TC = 8; // Tile Count of each edge in a simdgroup 8x8 tile 320 constexpr short HD = OP_SSM_SCAN_SSD_HD; 321 constexpr short NSG = OP_SSM_SCAN_SSD_NSG; 322 323 // acs/exp(acs)/state-decay vectors, dtX[CS][HD], four private SAM row tiles [8][CS], 324 // and two 8x8 scratch tiles per simdgroup. Total: 26.75 KiB. 325 threadgroup float * shared_acs = shared; 326 threadgroup float * shared_exp_acs = shared + CS; 327 threadgroup float * shared_state_decay = shared + 2*CS; 328 threadgroup float * shared_dtx = shared + 3*CS; 329 threadgroup float * shared_sam = shared + 3*CS + CS*HD; 330 threadgroup float * sam_rows = shared_sam + sgitg*TC*CS; 331 threadgroup float * shared_tile = shared_sam + NSG*TC*CS; 332 threadgroup float * tile0 = shared_tile + sgitg*2*TC*TC; 333 threadgroup float * tile1 = tile0 + TC*TC; 334 335 const int32_t ir = tgpig.y; // current head 336 const int32_t i3 = tgpig.z; // current seq 337 338 const int32_t nc = args.d_state; 339 const int32_t nr = args.d_inner; 340 const int32_t nh = args.n_head; 341 const int32_t ng = args.n_group; 342 const int32_t n_t = args.n_seq_tokens; 343 const int32_t n_t_total = args.n_seq_tokens_total; 344 const int32_t g = ir / (nh / ng); 345 346 device const int32_t * ids = (device const int32_t *) src6; 347 348 device const float * s0_buff = (device const float *) ((device const char *) src0 + ir*args.nb02 + ids[i3]*args.nb03); 349 device float * s_buff = (device float *) ((device char *) dst + ir*args.nb02 + i3*args.nb03 + args.s_off); 350 351 device const float * A = (device const float *) ((device const char *) src3 + ir*args.nb31); 352 device const float * x = (device const float *) ((device const char *) src1 + ir*args.nb11 + i3*args.nb13); 353 device const float * dt = (device const float *) ((device const char *) src2 + ir*args.nb20 + i3*args.nb22); 354 device const float * B = (device const float *) ((device const char *) src4 + g*args.nb41 + i3*args.nb43); 355 device const float * C = (device const float *) ((device const char *) src5 + g*args.nb51 + i3*args.nb53); 356 357 device float * y = dst + (ir*nr + i3*(n_t_total*nh*nr)); 358 359 for (int32_t t0 = 0; t0 < n_t; t0 += CS) { 360 for (int32_t idx = tiitg; idx < CS*HD; idx += NSG*N_SIMDWIDTH) { 361 const int32_t t = idx / HD; 362 const int32_t c = idx % HD; 363 const float dt0 = dt[(t0 + t) * (int32_t) args.ns21]; 364 const float dtsp = dt0 <= 20.0f ? log(1.0f + exp(dt0)) : dt0; 365 shared_dtx[idx] = x[(t0 + t) * (int32_t) args.ns12 + c] * dtsp; 366 } 367 if (tiitg < CS) { 368 const float dt0 = dt[(t0 + tiitg) * (int32_t) args.ns21]; 369 const float dtsp = dt0 <= 20.0f ? log(1.0f + exp(dt0)) : dt0; 370 shared_acs[tiitg] = dtsp * A[0]; 371 } 372 threadgroup_barrier(mem_flags::mem_threadgroup); 373 374 if (tiitg == 0) { 375 float acc = 0.0f; 376 for (short t = 0; t < CS; ++t) { 377 acc += shared_acs[t]; 378 shared_acs[t] = acc; 379 } 380 } 381 threadgroup_barrier(mem_flags::mem_threadgroup); 382 if (tiitg < CS) { 383 shared_exp_acs[tiitg] = exp(shared_acs[tiitg]); 384 shared_state_decay[tiitg] = exp(shared_acs[CS - 1] - shared_acs[tiitg]); 385 } 386 threadgroup_barrier(mem_flags::mem_threadgroup); 387 388 device const float * state = t0 == 0 ? s0_buff : s_buff; 389 390 // Build one 8x64 row tile of SAM per simdgroup, then reuse it across every channel tile. 391 for (short ib = sgitg; ib < CS/TC; ib += NSG) { 392 for (short jb = 0; jb <= ib; ++jb) { 393 simdgroup_float8x8 cb = make_filled_simdgroup_matrix<float, 8>(0.0f); 394 395 for (int32_t k0 = 0; k0 < nc; k0 += TC) { 396 simdgroup_float8x8 mc; 397 simdgroup_float8x8 mb; 398 simdgroup_load(mc, C + (t0 + ib*TC)*(int32_t) args.ns52 + k0, args.ns52); 399 simdgroup_load(mb, B + (t0 + jb*TC)*(int32_t) args.ns42 + k0, args.ns42, 0, true); 400 simdgroup_multiply_accumulate(cb, mc, mb, cb); 401 } 402 403 threadgroup float * sam = sam_rows + jb*TC; 404 simdgroup_store(cb, sam, CS); 405 simdgroup_barrier(mem_flags::mem_threadgroup); 406 for (short e = tiisg; e < TC*TC; e += N_SIMDWIDTH) { 407 const short ri = e / TC; 408 const short rj = e % TC; 409 const short i = ib*TC + ri; 410 const short j = jb*TC + rj; 411 sam[ri*CS + rj] = j <= i ? 412 sam[ri*CS + rj] * exp(shared_acs[i] - shared_acs[j]) : 0.0f; 413 } 414 simdgroup_barrier(mem_flags::mem_threadgroup); 415 } 416 417 for (short ch = 0; ch < HD/TC; ++ch) { 418 simdgroup_float8x8 y_diag = make_filled_simdgroup_matrix<float, 8>(0.0f); 419 simdgroup_float8x8 y_inter = make_filled_simdgroup_matrix<float, 8>(0.0f); 420 421 for (short jb = 0; jb <= ib; ++jb) { 422 simdgroup_float8x8 sam; 423 simdgroup_float8x8 mdtx; 424 simdgroup_load(sam, sam_rows + jb*TC, CS); 425 simdgroup_load(mdtx, shared_dtx + jb*TC*HD + ch*TC, HD); 426 simdgroup_multiply_accumulate(y_diag, sam, mdtx, y_diag); 427 } 428 429 for (int32_t k0 = 0; k0 < nc; k0 += TC) { 430 simdgroup_float8x8 mc; 431 simdgroup_float8x8 ms; 432 simdgroup_load(mc, C + (t0 + ib*TC)*(int32_t) args.ns52 + k0, args.ns52); 433 simdgroup_load(ms, state + ch*TC*nc + k0, nc, 0, true); 434 simdgroup_multiply_accumulate(y_inter, mc, ms, y_inter); 435 } 436 437 simdgroup_store(y_diag, tile0, TC); 438 simdgroup_store(y_inter, tile1, TC); 439 simdgroup_barrier(mem_flags::mem_threadgroup); 440 for (short e = tiisg; e < TC*TC; e += N_SIMDWIDTH) { 441 const short ri = e / TC; 442 const short ci = e % TC; 443 const int32_t token = t0 + ib*TC + ri; 444 y[token*nh*nr + ch*TC + ci] = 445 tile0[e] + shared_exp_acs[ib*TC + ri] * tile1[e]; 446 } 447 simdgroup_barrier(mem_flags::mem_threadgroup); 448 } 449 } 450 451 // All simdgroups must finish reading s_buff before any thread overwrites it. 452 threadgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup); 453 454 // Keep the carried-state reduction in token order. Reassociating this particular product 455 // with MMA compounds rounding differences at every chunk boundary; CB, y_diag, and C*S 456 // remain on the matrix unit. 457 const float chunk_decay = exp(shared_acs[CS - 1]); 458 for (int32_t idx = tiitg; idx < nc*HD; idx += NSG*N_SIMDWIDTH) { 459 const int32_t ci = idx / nc; 460 const int32_t si = idx % nc; 461 float state_c = 0.0f; 462 for (short t = 0; t < CS; ++t) { 463 state_c += shared_state_decay[t] * 464 B[(t0 + t)*(int32_t) args.ns42 + si] * 465 shared_dtx[t*HD + ci]; 466 } 467 s_buff[idx] = chunk_decay * state[idx] + state_c; 468 } 469 470 // All state tiles must be visible before the next chunk consumes s_buff as S_prev. 471 threadgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup); 472 } 473}