char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
91f6a6cf3
char/aliceai-t5-moe
1#version 450 2 3#extension GL_EXT_control_flow_attributes : enable 4#extension GL_EXT_shader_16bit_storage : require 5 6#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require 7#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require 8#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require 9#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require 10 11#extension GL_KHR_memory_scope_semantics : enable 12#extension GL_KHR_cooperative_matrix : enable 13#extension GL_NV_cooperative_matrix2 : enable 14#ifdef GGML_VULKAN_COOPMAT2_DECODE_VECTOR 15#extension GL_NV_cooperative_matrix_decode_vector : enable 16#endif 17#extension GL_EXT_buffer_reference : enable 18#extension GL_KHR_shader_subgroup_ballot : enable 19#extension GL_KHR_shader_subgroup_vote : enable 20#ifdef DATA_A_BF16 21#extension GL_EXT_bfloat16 : enable 22#endif 23 24#include "ggml_type_ids.glsl" 25 26#ifdef MULMAT_QUANT 27layout (constant_id = 7) const uint MmTypeA = 0; 28layout (constant_id = 8) const uint MmABlockBytes = 2; 29#endif 30 31#include "types.glsl" 32#include "utils.glsl" 33 34layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in; 35 36#define IS_MUL_MM2 1 37 38layout (constant_id = 0) const uint BLOCK_SIZE = 256; 39layout (constant_id = 1) const uint BM = 64; 40layout (constant_id = 2) const uint BN = 64; 41layout (constant_id = 3) const uint BK = 16; // Assumed to be 32 if working with a quant 42 43layout (constant_id = 4) const bool enable_smaller_matrices = false; 44const uint BNover2 = enable_smaller_matrices ? (BN / 2) : BN; 45const uint BNover4 = enable_smaller_matrices ? (BN / 4) : BN; 46layout (constant_id = 5) const uint ALIGNED = 0; 47layout (constant_id = 6) const uint subgroup_size = 32; 48 49#ifdef MULMAT_QUANT 50 51uint mm_quant_k() { 52 switch (MmTypeA) { 53 case GGML_TYPE_Q4_0: case GGML_TYPE_Q4_1: case GGML_TYPE_Q5_0: case GGML_TYPE_Q5_1: 54 case GGML_TYPE_Q8_0: 55 return 32u; 56 case GGML_TYPE_Q1_0: 57 return 128u; 58 case GGML_TYPE_Q2_0: 59 return 64u; 60 default: 61 return 256u; 62 } 63} 64#endif 65 66layout (push_constant) uniform parameter 67{ 68 uint M; 69 uint N; 70 uint K; 71 uint stride_a; 72 uint stride_b; 73 uint stride_d; 74 75 uint batch_stride_a; 76 uint batch_stride_b; 77 uint batch_stride_d; 78 79#ifdef MUL_MAT_ID 80 uint nei0; 81 uint nei1; 82 uint nbi1; 83 uint ne11; 84 uint n_experts; 85 uint hoist_row_ids; 86#else 87 uint base_work_group_z; 88 uint num_batches; 89 uint k_split; 90 uint ne02; 91 uint ne12; 92 uint broadcast2; 93 uint broadcast3; 94 // N dimension for the B matrix can be >= p.N 95 uint padded_N; 96#endif 97} p; 98 99 100#ifndef MULMAT_QUANT 101layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; 102#else 103layout (binding = 0) readonly buffer A {uint8_t data_a[];}; 104#endif 105layout (binding = 1) readonly buffer B {B_TYPE data_b[];}; 106layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; 107#if defined(MUL_MAT_ID) && defined(GGML_VULKAN_COOPMAT2_DECODE_VECTOR) 108layout (binding = 1) readonly buffer B4 {B_TYPEV4 data_b_v4[];}; 109#endif 110 111#if defined(MULMAT_QUANT) || QUANT_K > 1 112#include "dequant_funcs_cm2.glsl" 113#ifndef MULMAT_QUANT 114// Per-type path: use the alias set by dequant_funcs_cm2.glsl 115#if defined(dequantFuncA_v) && defined(GGML_VULKAN_COOPMAT2_DECODE_VECTOR) 116#define DECODEFUNCA , dequantFuncA, dequantFuncA_v 117#else 118#define DECODEFUNCA , dequantFuncA 119#endif 120#else 121layout(buffer_reference, std430, buffer_reference_align = 1) buffer decodeBufA { 122 uint8_t raw[MmABlockBytes]; 123}; 124 125float16_t mmDecodeA(const in decodeBufA bl_in, const in uint blockCoords[2], const in uint coordInBlock[2]) { 126 switch (MmTypeA) { 127 case GGML_TYPE_Q1_0: return dequantFuncQ1_0 (decodeBufQ1_0 (bl_in), blockCoords, coordInBlock); 128 case GGML_TYPE_Q2_0: return dequantFuncQ2_0 (decodeBufQ2_0 (bl_in), blockCoords, coordInBlock); 129 case GGML_TYPE_Q4_0: return dequantFuncQ4_0 (decodeBufQ4_0 (bl_in), blockCoords, coordInBlock); 130 case GGML_TYPE_Q4_1: return dequantFuncQ4_1 (decodeBufQ4_1 (bl_in), blockCoords, coordInBlock); 131 case GGML_TYPE_Q5_0: return dequantFuncQ5_0 (decodeBufQ5_0 (bl_in), blockCoords, coordInBlock); 132 case GGML_TYPE_Q5_1: return dequantFuncQ5_1 (decodeBufQ5_1 (bl_in), blockCoords, coordInBlock); 133 case GGML_TYPE_Q8_0: return dequantFuncQ8_0 (decodeBufQ8_0 (bl_in), blockCoords, coordInBlock); 134 case GGML_TYPE_Q2_K: return dequantFuncQ2_K (decodeBufQ2_K (bl_in), blockCoords, coordInBlock); 135 case GGML_TYPE_Q3_K: return dequantFuncQ3_K (decodeBufQ3_K (bl_in), blockCoords, coordInBlock); 136 case GGML_TYPE_Q6_K: return dequantFuncQ6_K (decodeBufQ6_K (bl_in), blockCoords, coordInBlock); 137 case GGML_TYPE_TQ1_0: return dequantFuncTQ1_0(decodeBufTQ1_0(bl_in), blockCoords, coordInBlock); 138 case GGML_TYPE_TQ2_0: return dequantFuncTQ2_0(decodeBufTQ2_0(bl_in), blockCoords, coordInBlock); 139 default: return float16_t(0); 140 } 141} 142 143#ifdef GGML_VULKAN_COOPMAT2_DECODE_VECTOR 144f16vec4 mmDecodeA_v(const in decodeBufA bl_in, const in uint blockCoords[2], const in uint coordInBlock[2]) { 145 switch (MmTypeA) { 146 case GGML_TYPE_Q1_0: return dequantFuncQ1_0_v (decodeBufQ1_0 (bl_in), blockCoords, coordInBlock); 147 case GGML_TYPE_Q2_0: return dequantFuncQ2_0_v (decodeBufQ2_0 (bl_in), blockCoords, coordInBlock); 148 case GGML_TYPE_Q4_0: return dequantFuncQ4_0_v (decodeBufQ4_0 (bl_in), blockCoords, coordInBlock); 149 case GGML_TYPE_Q4_1: return dequantFuncQ4_1_v (decodeBufQ4_1 (bl_in), blockCoords, coordInBlock); 150 case GGML_TYPE_Q5_0: return dequantFuncQ5_0_v (decodeBufQ5_0 (bl_in), blockCoords, coordInBlock); 151 case GGML_TYPE_Q5_1: return dequantFuncQ5_1_v (decodeBufQ5_1 (bl_in), blockCoords, coordInBlock); 152 case GGML_TYPE_Q8_0: return dequantFuncQ8_0_v (decodeBufQ8_0 (bl_in), blockCoords, coordInBlock); 153 case GGML_TYPE_Q2_K: return dequantFuncQ2_K_v (decodeBufQ2_K (bl_in), blockCoords, coordInBlock); 154 case GGML_TYPE_Q3_K: return dequantFuncQ3_K_v (decodeBufQ3_K (bl_in), blockCoords, coordInBlock); 155 case GGML_TYPE_Q6_K: return dequantFuncQ6_K_v (decodeBufQ6_K (bl_in), blockCoords, coordInBlock); 156 case GGML_TYPE_TQ1_0: return dequantFuncTQ1_0_v(decodeBufTQ1_0(bl_in), blockCoords, coordInBlock); 157 case GGML_TYPE_TQ2_0: return dequantFuncTQ2_0_v(decodeBufTQ2_0(bl_in), blockCoords, coordInBlock); 158 default: return f16vec4(0); 159 } 160} 161#define DECODEFUNCA , mmDecodeA, mmDecodeA_v 162#else 163#define DECODEFUNCA , mmDecodeA 164#endif 165#endif 166#else 167#define DECODEFUNCA 168#endif 169 170#if !defined(fetch_scales) 171#define fetch_scales(a, b, c, d, e, f) 172#endif 173#if !defined(store_scales) 174#define store_scales(a) 175#endif 176 177#if defined(DATA_A_BF16) 178#define MAT_TYPE bfloat16_t 179#else 180#define MAT_TYPE FLOAT_TYPE 181#endif 182 183#ifdef MUL_MAT_ID 184layout (binding = 3) readonly buffer IDS {int data_ids[];}; 185layout (binding = 4) readonly buffer Counts {int data_expert_count[];}; 186 187shared u16vec4 row_ids[BN]; 188 189layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufB { 190 B_TYPE b[]; 191}; 192 193uint _ne1; 194shared uvec4 ballots_sh[BLOCK_SIZE / subgroup_size]; 195 196B_TYPE decodeFuncB(const in decodeBufB bl, const in uint blockCoords[2], const in uint coordInBlock[2]) 197{ 198 const uint row_i = blockCoords[0]; 199 200 const u16vec4 row_idx = row_ids[row_i]; 201#if defined(GGML_VULKAN_COOPMAT2_DECODE_VECTOR) 202 // The decode-vector path gives B a K-dimension tensor-layout block size of BK. 203 const uint k = blockCoords[1] * BK + coordInBlock[1]; 204#else 205 const uint k = blockCoords[1]; 206#endif 207 B_TYPE ret = data_b[row_idx.y * p.batch_stride_b + row_idx.x * p.stride_b + k]; 208 209 return ret; 210} 211 212#if defined(GGML_VULKAN_COOPMAT2_DECODE_VECTOR) 213B_TYPEV4 decodeFuncB_v(const in decodeBufB bl, const in uint blockCoords[2], const in uint coordInBlock[2]) 214{ 215 const uint row_i = blockCoords[0]; 216 217 const u16vec4 row_idx = row_ids[row_i]; 218 const uint k = blockCoords[1] * BK + coordInBlock[1]; 219 const uint base = row_idx.y * p.batch_stride_b + row_idx.x * p.stride_b + k; 220 221 return data_b_v4[base >> 2]; 222} 223#define DECODEFUNCB , decodeFuncB, decodeFuncB_v 224#else 225#define DECODEFUNCB , decodeFuncB 226#endif 227 228D_TYPE perElemOpD(const in uint32_t r, const in uint32_t c, const in D_TYPE elem, const in uint32_t ir, const in uint32_t ic) 229{ 230 uint dr = ir * BM + r; 231 uint dc = ic * BN + c; 232 233 if (dr < p.M && dc < _ne1) { 234 uint row_i = c; 235 const u16vec4 row_idx = row_ids[row_i]; 236 data_d[row_idx.y * p.batch_stride_d + row_idx.z * p.stride_d + dr] = elem; 237 } 238 return elem; 239} 240 241void load_row_ids(uint expert_idx, bool nei0_is_pow2, uint ic) { 242 _ne1 = 0; 243 uint num_elements = p.nei1 * p.nei0; 244 uint nei0shift = findLSB(p.nei0); 245 246 uint ids[16]; 247 uint iter = 0; 248 249 uint expert_count = data_expert_count[expert_idx]; 250 251 for (uint j = 0; j < num_elements; j += BLOCK_SIZE) { 252 // prefetch up to 16 elements 253 if (iter == 0) { 254 [[unroll]] for (uint k = 0; k < 16; ++k) { 255 uint i = j + gl_LocalInvocationIndex + k*BLOCK_SIZE; 256 bool in_range = i < num_elements; 257 uint ii1; 258 if (nei0_is_pow2) { 259 ii1 = i >> nei0shift; 260 } else { 261 ii1 = i / p.nei0; 262 } 263 uint ii0 = i - ii1 * p.nei0; 264 ids[k] = in_range ? data_ids[ii1*p.nbi1 + ii0] : 0; 265 } 266 } 267 uint i = j + gl_LocalInvocationIndex; 268 bool in_range = i < num_elements; 269 uint ii1; 270 if (nei0_is_pow2) { 271 ii1 = i >> nei0shift; 272 } else { 273 ii1 = i / p.nei0; 274 } 275 uint ii0 = i - ii1 * p.nei0; 276 uint id = ids[iter++]; 277 uvec4 ballot = subgroupBallot(in_range && id == expert_idx); 278 279 if (gl_SubgroupInvocationID == 0) { 280 ballots_sh[gl_SubgroupID] = ballot; 281 } 282 barrier(); 283 284 uint subgroup_base = 0; 285 uint total = 0; 286 for (uint k = 0; k < gl_NumSubgroups; ++k) { 287 if (k == gl_SubgroupID) { 288 subgroup_base = total; 289 } 290 total += subgroupBallotBitCount(ballots_sh[k]); 291 } 292 barrier(); 293 294 uint idx = subgroup_base + subgroupBallotExclusiveBitCount(ballot); 295 if (in_range && id == expert_idx && _ne1 + idx >= ic * BN && _ne1 + idx < (ic + 1) * BN) { 296 row_ids[_ne1 + idx - ic * BN] = u16vec4(fastmod(ii0, p.ne11), ii1, ii0, 0); 297 } 298 _ne1 += total; 299 iter &= 15; 300 if (_ne1 >= (ic + 1) * BN || _ne1 == expert_count) { 301 break; 302 } 303 } 304 barrier(); 305} 306 307void load_row_ids_hoisted(uint expert_idx, uint ic) { 308 _ne1 = uint(data_expert_count[expert_idx]); 309 310 const uint tile_begin = ic * BN; 311 const uint tile_count = tile_begin < _ne1 ? min(BN, _ne1 - tile_begin) : 0; 312 const uint expert_offset = uint(data_expert_count[p.n_experts + expert_idx]); 313 const uint row_ids_offset = 2 * p.n_experts + 1 + expert_offset + tile_begin; 314 315 for (uint i = gl_LocalInvocationIndex; i < tile_count; i += BLOCK_SIZE) { 316 const uint packed_row_id = uint(data_expert_count[row_ids_offset + i]); 317 const uint ii0 = packed_row_id & 0xffffu; 318 const uint ii1 = packed_row_id >> 16; 319 row_ids[i] = u16vec4(fastmod(ii0, p.ne11), ii1, ii0, 0); 320 } 321 barrier(); 322} 323#endif 324 325#ifdef MULMAT_QUANT 326#include "iq_shmem_init.glsl" 327#endif 328 329void main() { 330 const uint tid = gl_LocalInvocationIndex; 331 const uint ic = gl_WorkGroupID.y; 332 333#ifdef MUL_MAT_ID 334 const uint expert_idx = gl_WorkGroupID.z; 335 if (ic * BN >= data_expert_count[expert_idx]) { 336 return; 337 } 338 // initialize to row 0 so we don't need to bounds check 339 if (tid < BN) { 340 row_ids[tid] = u16vec4(0); 341 } 342#if !defined(NEEDS_INIT_IQ_SHMEM) 343 barrier(); 344#endif 345#endif 346 347#if defined(NEEDS_INIT_IQ_SHMEM) || defined(MULMAT_QUANT) 348 init_iq_shmem(gl_WorkGroupSize); 349#endif 350 351#ifndef MUL_MAT_ID 352 const uint batch_idx = gl_WorkGroupID.z + p.base_work_group_z; 353 354 const uint i13 = batch_idx / p.ne12; 355 const uint i12 = batch_idx % p.ne12; 356 357 const uint i03 = i13 / p.broadcast3; 358 const uint i02 = i12 / p.broadcast2; 359 360 const uint batch_idx_a = i03 * p.ne02 + i02; 361#endif 362 363 const uint blocks_m = (p.M + BM - 1) / BM; 364 const uint ir = gl_WorkGroupID.x % blocks_m; 365 const uint ik = gl_WorkGroupID.x / blocks_m; 366 367#ifdef MUL_MAT_ID 368 if (p.hoist_row_ids != 0) { 369 load_row_ids_hoisted(expert_idx, ic); 370 } else if (bitCount(p.nei0) == 1) { 371 load_row_ids(expert_idx, true, ic); 372 } else { 373 load_row_ids(expert_idx, false, ic); 374 } 375 376 // Workgroup has no work 377 if (ic * BN >= _ne1) return; 378#endif 379 380#ifdef MUL_MAT_ID 381 uint start_k = 0; 382 const uint end_k = p.K; 383#else 384 uint start_k = ik * p.k_split; 385 const uint end_k = min(p.K, (ik + 1) * p.k_split); 386#endif 387 388#ifdef MULMAT_QUANT 389 const uint qk = mm_quant_k(); 390#else 391 const uint qk = QUANT_K; 392#endif 393 394#ifdef MUL_MAT_ID 395 uint pos_a = expert_idx * (p.batch_stride_a / qk); 396 uint pos_b = 0; 397#else 398 uint pos_a = batch_idx_a * (p.batch_stride_a / qk); 399 uint pos_b = batch_idx * p.batch_stride_b; 400 uint pos_d = batch_idx * p.batch_stride_d + ik * p.batch_stride_d * p.num_batches; 401#endif 402 403#ifdef MULMAT_QUANT 404 // pos_a is a byte offset into the raw buffer; strides stay in block units 405 pos_a *= MmABlockBytes; 406#endif 407 408 uint stride_a = p.stride_a / qk; 409 uint stride_b = p.stride_b; 410 411 // Hint to the compiler that values are aligned (want 16B alignment). 412 // Quants are always block-aligned, no alignment needed. 413 if (ALIGNED != 0) { 414#if !defined(MULMAT_QUANT) && QUANT_K == 1 415 stride_a &= ~7; 416#endif 417 stride_b &= ~7; 418 } 419 420 // Create layouts for both clamped and unclamped accesses 421 tensorLayoutNV<2> tensorLayoutA = createTensorLayoutNV(2); 422 tensorLayoutNV<2, gl_CooperativeMatrixClampModeConstantNV> tensorLayoutAClamp = createTensorLayoutNV(2, gl_CooperativeMatrixClampModeConstantNV); 423 tensorLayoutNV<2> tensorLayoutB = createTensorLayoutNV(2); 424#ifndef MUL_MAT_ID 425 tensorLayoutNV<2, gl_CooperativeMatrixClampModeConstantNV> tensorLayoutBClamp = createTensorLayoutNV(2, gl_CooperativeMatrixClampModeConstantNV); 426#endif 427 tensorLayoutNV<2, gl_CooperativeMatrixClampModeConstantNV> tensorLayoutD = createTensorLayoutNV(2, gl_CooperativeMatrixClampModeConstantNV); 428 429 tensorLayoutA = setTensorLayoutBlockSizeNV(tensorLayoutA, 1, qk); 430 tensorLayoutAClamp = setTensorLayoutBlockSizeNV(tensorLayoutAClamp, 1, qk); 431#if defined(MUL_MAT_ID) && defined(GGML_VULKAN_COOPMAT2_DECODE_VECTOR) 432 tensorLayoutB = setTensorLayoutBlockSizeNV(tensorLayoutB, 1, BK); 433#endif 434 435 // Use end_k rather than p.K as the dimension because that's what 436 // we need to bound check against when using split_k. 437 tensorLayoutA = setTensorLayoutDimensionNV(tensorLayoutA, p.M, end_k); 438#ifdef MUL_MAT_ID 439 // MUL_MAT_ID pads each B row to stride_b so partial K tiles read zeros without clamping. 440 tensorLayoutB = setTensorLayoutDimensionNV(tensorLayoutB, BN, p.stride_b); 441#else 442 // Bounds check B against padded_N, but bounds check D against N. 443 tensorLayoutB = setTensorLayoutDimensionNV(tensorLayoutB, p.padded_N, end_k); 444#endif 445 tensorLayoutD = setTensorLayoutDimensionNV(tensorLayoutD, p.N, p.M); 446 tensorLayoutAClamp = setTensorLayoutDimensionNV(tensorLayoutAClamp, p.M, end_k); 447#ifndef MUL_MAT_ID 448 tensorLayoutBClamp = setTensorLayoutDimensionNV(tensorLayoutBClamp, p.padded_N, end_k); 449#endif 450 451 tensorLayoutD = setTensorLayoutStrideNV(tensorLayoutD, p.stride_d, 1); 452 453 tensorViewNV<2, false, 1, 0> tensorViewTranspose = createTensorViewNV(2, false, 1, 0); 454 455#if !defined(MUL_MAT_ID) 456 457 const uint START_ALIGN_K = 256; 458 // For Qi_K (block size 256), unroll whole 256 element tiles. 459 // For legacy quants (block size 32), unroll 8x. 460 const uint UNROLL_K = (qk == 256) ? 256 : (BK * 8); 461 const uint unroll_count = UNROLL_K / BK; 462 463 // Detect a fast path where all loads are entirely in bounds and no clamping is required 464 if ((ir + 1) * BM <= p.M && (ic + 1) * BN <= p.padded_N && (start_k % START_ALIGN_K) == 0 && (end_k % BK) == 0 && 465#if !defined(MULMAT_QUANT) && QUANT_K == 1 466 (stride_a % 8) == 0 && 467#endif 468 (stride_b % 8) == 0) { 469 // Hint to the compiler that values are aligned (want 16B alignment) 470 start_k &= ~(START_ALIGN_K-1); 471 stride_b &= ~7; 472#if !defined(MULMAT_QUANT) && QUANT_K == 1 473 stride_a &= ~7; 474#endif 475 476 tensorLayoutA = setTensorLayoutStrideNV(tensorLayoutA, stride_a, 1); 477 tensorLayoutB = setTensorLayoutStrideNV(tensorLayoutB, stride_b, 1); 478 479 uint k_iters = (end_k - start_k) / UNROLL_K; 480 uint block_k = start_k; 481 482 // fetch scale values for a tile of quants. These will be copied into shared memory. 483 // The fetches and stores are pipelined to hide the latency. 484 fetch_scales(ir * BM, pos_a, stride_a, start_k, tid, true); 485 486 if (enable_smaller_matrices && ic * BN + BNover4 >= p.N) { 487 coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BNover4, gl_MatrixUseAccumulator> sum = coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BNover4, gl_MatrixUseAccumulator>(0.0); 488 for (uint i = 0; i < k_iters; ++i) { 489 490 store_scales(tid); 491 if (block_k + UNROLL_K < end_k) { 492 fetch_scales(ir * BM, pos_a, stride_a, block_k + UNROLL_K, tid, true); 493 } 494 495 // Manually partial unroll 496 [[unroll]] for (uint j = 0; j < unroll_count; ++j) { 497 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 498 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BNover4, gl_MatrixUseB> mat_b; 499 500 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); 501 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BNover4, block_k, BK), tensorViewTranspose); 502 503 sum = coopMatMulAdd(mat_a, mat_b, sum); 504 block_k += BK; 505 } 506 } 507 // Do any remaining iterations that were not unrolled 508 if (block_k < end_k) { 509 store_scales(tid); 510 } 511 while (block_k < end_k) { 512 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 513 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BNover4, gl_MatrixUseB> mat_b; 514 515 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); 516 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BNover4, block_k, BK), tensorViewTranspose); 517 518 sum = coopMatMulAdd(mat_a, mat_b, sum); 519 block_k += BK; 520 } 521#if defined(ACC_TYPE_MAX) 522 [[unroll]] for (uint i = 0; i < sum.length(); ++i) { sum[i] = clamp(sum[i], -ACC_TYPE_MAX, ACC_TYPE_MAX); } 523#endif 524 525 coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BNover4, gl_MatrixUseAccumulator> mat_d = coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BNover4, gl_MatrixUseAccumulator>(sum); 526 527 coopMatStoreTensorNV(mat_d, data_d, pos_d, sliceTensorLayoutNV(tensorLayoutD, ic * BN, BNover4, ir * BM, BM), tensorViewTranspose); 528 return; 529 } else if (enable_smaller_matrices && ic * BN + BNover2 >= p.N) { 530 coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BNover2, gl_MatrixUseAccumulator> sum = coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BNover2, gl_MatrixUseAccumulator>(0.0); 531 for (uint i = 0; i < k_iters; ++i) { 532 533 store_scales(tid); 534 if (block_k + UNROLL_K < end_k) { 535 fetch_scales(ir * BM, pos_a, stride_a, block_k + UNROLL_K, tid, true); 536 } 537 538 // Manually partial unroll 539 [[unroll]] for (uint j = 0; j < unroll_count; ++j) { 540 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 541 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BNover2, gl_MatrixUseB> mat_b; 542 543 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); 544 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BNover2, block_k, BK), tensorViewTranspose); 545 546 sum = coopMatMulAdd(mat_a, mat_b, sum); 547 block_k += BK; 548 } 549 } 550 // Do any remaining iterations that were not unrolled 551 if (block_k < end_k) { 552 store_scales(tid); 553 } 554 while (block_k < end_k) { 555 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 556 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BNover2, gl_MatrixUseB> mat_b; 557 558 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); 559 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BNover2, block_k, BK), tensorViewTranspose); 560 561 sum = coopMatMulAdd(mat_a, mat_b, sum); 562 block_k += BK; 563 } 564#if defined(ACC_TYPE_MAX) 565 [[unroll]] for (uint i = 0; i < sum.length(); ++i) { sum[i] = clamp(sum[i], -ACC_TYPE_MAX, ACC_TYPE_MAX); } 566#endif 567 568 coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BNover2, gl_MatrixUseAccumulator> mat_d = coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BNover2, gl_MatrixUseAccumulator>(sum); 569 570 coopMatStoreTensorNV(mat_d, data_d, pos_d, sliceTensorLayoutNV(tensorLayoutD, ic * BN, BNover2, ir * BM, BM), tensorViewTranspose); 571 return; 572 } else { 573 coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BN, gl_MatrixUseAccumulator> sum = coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BN, gl_MatrixUseAccumulator>(0.0); 574 575 for (uint i = 0; i < k_iters; ++i) { 576 577 store_scales(tid); 578 if (block_k + UNROLL_K < end_k) { 579 fetch_scales(ir * BM, pos_a, stride_a, block_k + UNROLL_K, tid, true); 580 } 581 582 // Manually partial unroll 583 [[unroll]] for (uint j = 0; j < unroll_count; ++j) { 584 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 585 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BN, gl_MatrixUseB> mat_b; 586 587 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); 588 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BN, block_k, BK), tensorViewTranspose); 589 590 sum = coopMatMulAdd(mat_a, mat_b, sum); 591 block_k += BK; 592 } 593 } 594 // Do any remaining iterations that were not unrolled 595 if (block_k < end_k) { 596 store_scales(tid); 597 } 598 while (block_k < end_k) { 599 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 600 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BN, gl_MatrixUseB> mat_b; 601 602 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); 603 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, ic * BN, BN, block_k, BK), tensorViewTranspose); 604 605 sum = coopMatMulAdd(mat_a, mat_b, sum); 606 block_k += BK; 607 } 608#if defined(ACC_TYPE_MAX) 609 [[unroll]] for (uint i = 0; i < sum.length(); ++i) { sum[i] = clamp(sum[i], -ACC_TYPE_MAX, ACC_TYPE_MAX); } 610#endif 611 612 coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BN, gl_MatrixUseAccumulator> mat_d = coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BN, gl_MatrixUseAccumulator>(sum); 613 614 coopMatStoreTensorNV(mat_d, data_d, pos_d, sliceTensorLayoutNV(tensorLayoutD, ic * BN, BN, ir * BM, BM), tensorViewTranspose); 615 return; 616 } 617 } else 618#endif // !defined(MUL_MAT_ID) 619 { 620 tensorLayoutA = setTensorLayoutStrideNV(tensorLayoutA, stride_a, 1); 621 622 tensorLayoutAClamp = setTensorLayoutStrideNV(tensorLayoutAClamp, stride_a, 1); 623 624 tensorLayoutB = setTensorLayoutStrideNV(tensorLayoutB, stride_b, 1); 625 626#ifndef MUL_MAT_ID 627 tensorLayoutBClamp = setTensorLayoutStrideNV(tensorLayoutBClamp, stride_b, 1); 628#endif 629 630 uint k_iters = (end_k - start_k + BK - 1) / BK; 631 632 fetch_scales(ir * BM, pos_a, stride_a, start_k, tid, false); 633 store_scales(tid); 634 635#ifdef MUL_MAT_ID 636 if (enable_smaller_matrices && ic * BN + BNover4 >= _ne1) { 637 coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BNover4, gl_MatrixUseAccumulator> sum; 638 sum = coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BNover4, gl_MatrixUseAccumulator>(0.0); 639 640 [[dont_unroll]] 641 for (uint block_k = start_k, i = 0; i < k_iters; block_k += BK, ++i) { 642 643 if ((block_k % qk) == 0) { 644 store_scales(tid); 645 } 646 if (block_k + BK < end_k && ((block_k + BK) % qk) == 0) { 647 fetch_scales(ir * BM, pos_a, stride_a, block_k + BK, tid, false); 648 } 649 650 if ((ir + 1) * BM <= p.M && block_k + BK <= end_k) { 651 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 652 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BNover4, gl_MatrixUseB> mat_b; 653 654 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); 655 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, 0, BNover4, block_k, BK), tensorViewTranspose DECODEFUNCB); 656 657 sum = coopMatMulAdd(mat_a, mat_b, sum); 658 } else { 659 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 660 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BNover4, gl_MatrixUseB> mat_b; 661 662 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutAClamp, ir * BM, BM, block_k, BK) DECODEFUNCA); 663 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, 0, BNover4, block_k, BK), tensorViewTranspose DECODEFUNCB); 664 665 sum = coopMatMulAdd(mat_a, mat_b, sum); 666 } 667 } 668#if defined(ACC_TYPE_MAX) 669 [[unroll]] for (uint i = 0; i < sum.length(); ++i) { sum[i] = clamp(sum[i], -ACC_TYPE_MAX, ACC_TYPE_MAX); } 670#endif 671 672 // Convert from ACC_TYPE to D_TYPE 673 coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BNover4, gl_MatrixUseAccumulator> mat_d; 674 mat_d = coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BNover4, gl_MatrixUseAccumulator>(sum); 675 676 // Call callback to store each element, remapping row through shared memory 677 coopMatPerElementNV(mat_d, mat_d, perElemOpD, ir, ic); 678 return; 679 } 680 if (enable_smaller_matrices && ic * BN + BNover2 >= _ne1) { 681 coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BNover2, gl_MatrixUseAccumulator> sum; 682 sum = coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BNover2, gl_MatrixUseAccumulator>(0.0); 683 684 [[dont_unroll]] 685 for (uint block_k = start_k, i = 0; i < k_iters; block_k += BK, ++i) { 686 687 if ((block_k % qk) == 0) { 688 store_scales(tid); 689 } 690 if (block_k + BK < end_k && ((block_k + BK) % qk) == 0) { 691 fetch_scales(ir * BM, pos_a, stride_a, block_k + BK, tid, false); 692 } 693 694 if ((ir + 1) * BM <= p.M && block_k + BK <= end_k) { 695 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 696 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BNover2, gl_MatrixUseB> mat_b; 697 698 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); 699 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, 0, BNover2, block_k, BK), tensorViewTranspose DECODEFUNCB); 700 701 sum = coopMatMulAdd(mat_a, mat_b, sum); 702 } else { 703 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 704 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BNover2, gl_MatrixUseB> mat_b; 705 706 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutAClamp, ir * BM, BM, block_k, BK) DECODEFUNCA); 707 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, 0, BNover2, block_k, BK), tensorViewTranspose DECODEFUNCB); 708 709 sum = coopMatMulAdd(mat_a, mat_b, sum); 710 } 711 } 712#if defined(ACC_TYPE_MAX) 713 [[unroll]] for (uint i = 0; i < sum.length(); ++i) { sum[i] = clamp(sum[i], -ACC_TYPE_MAX, ACC_TYPE_MAX); } 714#endif 715 716 // Convert from ACC_TYPE to D_TYPE 717 coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BNover2, gl_MatrixUseAccumulator> mat_d; 718 mat_d = coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BNover2, gl_MatrixUseAccumulator>(sum); 719 720 // Call callback to store each element, remapping row through shared memory 721 coopMatPerElementNV(mat_d, mat_d, perElemOpD, ir, ic); 722 return; 723 } 724#endif 725 coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BN, gl_MatrixUseAccumulator> sum; 726 sum = coopmat<ACC_TYPE, gl_ScopeWorkgroup, BM, BN, gl_MatrixUseAccumulator>(0.0); 727 728 [[dont_unroll]] 729 for (uint block_k = start_k, i = 0; i < k_iters; block_k += BK, ++i) { 730 731 if ((block_k % qk) == 0) { 732 store_scales(tid); 733 } 734 if (block_k + BK < end_k && ((block_k + BK) % qk) == 0) { 735 fetch_scales(ir * BM, pos_a, stride_a, block_k + BK, tid, false); 736 } 737 738 if ((ir + 1) * BM <= p.M && block_k + BK <= end_k) { 739 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 740 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BN, gl_MatrixUseB> mat_b; 741 742 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutA, ir * BM, BM, block_k, BK) DECODEFUNCA); 743#ifdef MUL_MAT_ID 744 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, 0, BN, block_k, BK), tensorViewTranspose DECODEFUNCB); 745#else 746 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutBClamp, ic * BN, BN, block_k, BK), tensorViewTranspose); 747#endif 748 749 sum = coopMatMulAdd(mat_a, mat_b, sum); 750 } else { 751 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BM, BK, gl_MatrixUseA> mat_a; 752 coopmat<MAT_TYPE, gl_ScopeWorkgroup, BK, BN, gl_MatrixUseB> mat_b; 753 754 coopMatLoadTensorNV(mat_a, data_a, pos_a, sliceTensorLayoutNV(tensorLayoutAClamp, ir * BM, BM, block_k, BK) DECODEFUNCA); 755#ifdef MUL_MAT_ID 756 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutB, 0, BN, block_k, BK), tensorViewTranspose DECODEFUNCB); 757#else 758 coopMatLoadTensorNV(mat_b, data_b, pos_b, sliceTensorLayoutNV(tensorLayoutBClamp, ic * BN, BN, block_k, BK), tensorViewTranspose); 759#endif 760 761 sum = coopMatMulAdd(mat_a, mat_b, sum); 762 } 763 } 764#if defined(ACC_TYPE_MAX) 765 [[unroll]] for (uint i = 0; i < sum.length(); ++i) { sum[i] = clamp(sum[i], -ACC_TYPE_MAX, ACC_TYPE_MAX); } 766#endif 767 768 // Convert from ACC_TYPE to D_TYPE 769 coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BN, gl_MatrixUseAccumulator> mat_d; 770 mat_d = coopmat<D_TYPE, gl_ScopeWorkgroup, BM, BN, gl_MatrixUseAccumulator>(sum); 771 772#ifdef MUL_MAT_ID 773 // Call callback to store each element, remapping row through shared memory 774 coopMatPerElementNV(mat_d, mat_d, perElemOpD, ir, ic); 775#else 776 coopMatStoreTensorNV(mat_d, data_d, pos_d, sliceTensorLayoutNV(tensorLayoutD, ic * BN, BN, ir * BM, BM), tensorViewTranspose); 777#endif 778 } 779}