char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
95ef7fc16
char/aliceai-t5-moe
1//------------------------------------------------------------------------------ 2// This file is contains kernels for data conversion. 3// These kernels are used when loading the model , so its performance is less 4// important. 5//------------------------------------------------------------------------------ 6#pragma OPENCL EXTENSION cl_khr_fp16 : enable 7 8#ifdef cl_intel_required_subgroup_size 9#pragma OPENCL EXTENSION cl_intel_required_subgroup_size : enable 10#define INTEL_GPU 1 11#define REQD_SUBGROUP_SIZE_16 __attribute__((intel_reqd_sub_group_size(16))) 12#define REQD_SUBGROUP_SIZE_32 __attribute__((intel_reqd_sub_group_size(32))) 13#elif defined(cl_qcom_reqd_sub_group_size) 14#pragma OPENCL EXTENSION cl_qcom_reqd_sub_group_size : enable 15#define ADRENO_GPU 1 16#define REQD_SUBGROUP_SIZE_64 __attribute__((qcom_reqd_sub_group_size("half" ))) 17#define REQD_SUBGROUP_SIZE_128 __attribute__((qcom_reqd_sub_group_size("full" ))) 18#endif 19 20#define QK4_0 32 21#define QR4_0 2 22#define QK4_1 32 23#define QR4_1 2 24#define QK5_0 32 25#define QR5_0 2 26#define QK5_1 32 27#define QR5_1 2 28#define QK8_0 32 29#define QR8_0 1 30#define QK1_0 128 31#define QR1_0 1 32#define QK_K 256 33#define K_SCALE_SIZE (3 * QK_K / 64) 34#define K_QUANTS_PER_ITERATION 2 35 36typedef char int8_t; 37typedef uchar uint8_t; 38typedef short int16_t; 39typedef ushort uint16_t; 40typedef int int32_t; 41typedef uint uint32_t; 42 43//------------------------------------------------------------------------------ 44// block_q1_0 45//------------------------------------------------------------------------------ 46typedef struct { 47 half d; // delta 48 uchar qs[QK1_0/8]; // 1-bit signs (16 bytes) 49} block_q1_0; 50 51//------------------------------------------------------------------------------ 52// block_q4_0 53//------------------------------------------------------------------------------ 54struct block_q4_0 55{ 56 half d; 57 uint8_t qs[QK4_0 / 2]; 58}; 59 60//------------------------------------------------------------------------------ 61// block_q4_1 62//------------------------------------------------------------------------------ 63struct block_q4_1 { 64 half d; // delta 65 half m; // min 66 uchar qs[QK4_1 / 2]; // nibbles / quants 67}; 68 69//------------------------------------------------------------------------------ 70// block_q5_0 71//------------------------------------------------------------------------------ 72struct block_q5_0 { 73 half d; // delta 74 uchar qh[4]; // 5-th bit of quants 75 uchar qs[QK5_0 / 2]; // nibbles / quants 76}; 77 78//------------------------------------------------------------------------------ 79// block_q5_1 80//------------------------------------------------------------------------------ 81struct block_q5_1 { 82 half d; // delta 83 half m; // min 84 uchar qh[4]; // 5-th bit of quants 85 uchar qs[QK5_1 / 2]; // nibbles / quants 86}; 87 88//------------------------------------------------------------------------------ 89// block_q4_k 90//------------------------------------------------------------------------------ 91struct block_q4_K { 92 half d; // delta 93 half dm; // min 94 uchar s[K_SCALE_SIZE]; 95 uchar q[QK_K / 2]; // nibbles / quants 96}; 97 98//------------------------------------------------------------------------------ 99// block_q5_k 100//------------------------------------------------------------------------------ 101struct block_q5_K { 102 half d; // delta 103 half dm; // min 104 uchar s[K_SCALE_SIZE]; 105 uchar qh[QK_K / 8]; 106 uchar qs[QK_K / 2]; // nibbles / quants 107}; 108 109//------------------------------------------------------------------------------ 110// block_q6_K 111//------------------------------------------------------------------------------ 112struct block_q6_K { 113 uint8_t ql[QK_K/2]; // quants, lower 4 bits 114 uint8_t qh[QK_K/4]; // quants, upper 2 bits 115 int8_t scales[QK_K/16]; // scales, quantized with 8 bits 116 half d; // super-block scale 117}; 118 119//------------------------------------------------------------------------------ 120// block_iq4_nl 121//------------------------------------------------------------------------------ 122#define QK4_NL 32 123 124struct block_iq4_nl 125{ 126 half d; 127 uint8_t qs[QK4_NL / 2]; 128}; 129 130//------------------------------------------------------------------------------ 131// bf16 to f16 132//------------------------------------------------------------------------------ 133kernel void kernel_convert_bf16_to_f16( 134 global const ushort * src, 135 global half * dst, 136 ulong off_dst, 137 ulong n 138) { 139 uint i = get_global_id(0); 140 if (i >= n) { 141 return; 142 } 143 144 dst[i + off_dst] = (half) as_float((uint) src[i] << 16); 145} 146 147//------------------------------------------------------------------------------ 148// f16 to bf16 149//------------------------------------------------------------------------------ 150kernel void kernel_convert_f16_to_bf16( 151 global const half * src, 152 ulong off_src, 153 global ushort * dst, 154 ulong n 155) { 156 uint i = get_global_id(0); 157 if (i >= n) { 158 return; 159 } 160 161 float f = (float) src[i + off_src]; 162 uint bits = as_uint(f); 163 if ((bits & 0x7fffffffu) > 0x7f800000u) { 164 // nan to quiet nan 165 dst[i] = (ushort)((bits >> 16) | 0x40u); 166 } else { 167 uint rounded = bits + 0x7fffu + ((bits >> 16) & 1u); 168 dst[i] = (ushort)(rounded >> 16); 169 } 170} 171 172//------------------------------------------------------------------------------ 173// kernel_convert_block_q1_0 174// Convert block_q1_0 (AOS) to 2 separate arrays (SOA): quant bytes + scales. 175// q1_0 bits are stored in natural order (bit j of byte i -> weight 8*i + j) 176//------------------------------------------------------------------------------ 177kernel void kernel_convert_block_q1_0( 178 global block_q1_0 * src0, 179 global uchar * dst_q, 180 global half * dst_d 181) { 182 global block_q1_0 * b = (global block_q1_0 *) src0 + get_global_id(0); 183 global uchar * q = (global uchar *) dst_q + (QK1_0/8)*get_global_id(0); 184 global half * d = (global half *) dst_d + get_global_id(0); 185 186 *d = b->d; 187 188 for (int i = 0; i < QK1_0/8; ++i) { 189 q[i] = b->qs[i]; 190 } 191} 192 193kernel void kernel_restore_block_q1_0( 194 global uchar * src_q, 195 global half * src_d, 196 global block_q1_0 * dst 197) { 198 global block_q1_0 * b = (global block_q1_0 *) dst + get_global_id(0); 199 global uchar * q = (global uchar *) src_q + (QK1_0/8)*get_global_id(0); 200 global half * d = (global half *) src_d + get_global_id(0); 201 202 b->d = *d; 203 for (int i = 0; i < QK1_0/8; ++i) { 204 b->qs[i] = q[i]; 205 } 206} 207 208//------------------------------------------------------------------------------ 209// kernel_convert_block_q4_0 210// Convert the block_q4_0 format to 2 separate arrays (AOS -> SOA). 211// This kernel does not deshuffle the bits. 212//------------------------------------------------------------------------------ 213kernel void kernel_convert_block_q4_0( 214 global struct block_q4_0 * src0, 215 global uchar * dst_q, 216 global half * dst_d 217) { 218 global struct block_q4_0 * b = (global struct block_q4_0 *) src0 + get_global_id(0); 219 global uchar * q = (global uchar *) dst_q + QK4_0/2*get_global_id(0); 220 global half * d = (global half *) dst_d + get_global_id(0); 221 222 *d = b->d; 223 224 for (int i = 0; i < QK4_0/2; ++i) { 225 q[i] = b->qs[i]; 226 } 227} 228 229kernel void kernel_restore_block_q4_0( 230 global uchar * src_q, 231 global half * src_d, 232 global struct block_q4_0 * dst 233) { 234 global struct block_q4_0 * b = (global struct block_q4_0 *) dst + get_global_id(0); 235 global uchar * q = (global uchar *) src_q + QK4_0/2*get_global_id(0); 236 global half * d = (global half *) src_d + get_global_id(0); 237 238 b->d = *d; 239 for (int i = 0; i < QK4_0/2; ++i) { 240 b->qs[i] = q[i]; 241 } 242} 243 244//------------------------------------------------------------------------------ 245// kernel_convert_block_q4_0_noshuffle 246// Flatten q4_0 weights and unshuffle the bits 247//------------------------------------------------------------------------------ 248 249kernel void kernel_convert_block_q4_0_noshuffle( 250 global struct block_q4_0 * src0, 251 global uchar * dst_q, 252 global half * dst_d 253) { 254 global struct block_q4_0 * b = (global struct block_q4_0 *) src0 + get_global_id(0); 255 global uchar * q = (global uchar *) dst_q + QK4_0/2*get_global_id(0); 256 global half * d = (global half *) dst_d + get_global_id(0); 257 258 *d = b->d; 259 for (int i = 0; i < QK4_0/4; ++i) { 260 uchar x0 = b->qs[2*i + 0]; 261 uchar x1 = b->qs[2*i + 1]; 262 263 q[i + 0 ] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 264 q[i + QK4_0/4] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 265 266#ifdef ADRENO_GPU 267 // Workaround for adreno - must have the following printf statement for 268 // the kernel to work properly. Otherwise it produces incorrect result. 269 // convert_uchar above also seems necessary. 270 // Compare against a large number so that it does not print anything. 271 // get_sub_group_local_id() also works. 272 if (get_global_id(0) == 65536*4096) { 273 printf("%04x - %02x\n" , * ( global ushort* ) d , (( x0 & 0xF0 ) >> 4 ) | (x1 & 0xF0)); 274} 275#endif 276} 277} 278 279kernel void kernel_restore_block_q4_0_noshuffle( 280global uchar * src_q, 281global half * src_d, 282global struct block_q4_0 * dst, 283uchar mask_0F, 284uchar mask_F0 285) { 286global struct block_q4_0 * b = (global struct block_q4_0 *) dst + get_global_id(0); 287global uchar * q = (global uchar *) src_q + QK4_0/2*get_global_id(0); 288global half * d = (global half *) src_d + get_global_id(0); 289 290b->d = *d; 291for (int i = 0; i < QK4_0/4; ++i) { 292uchar x0 = q[i + 0 ] ; 293uchar x1 = q[i + QK4_0/4]; 294 295b->qs[2*i + 0] = convert_uchar((x0 & mask_0F) | (( x1 & mask_0F ) << 4 ) ); 296 b->qs[2*i + 1] = convert_uchar(((x0 & mask_F0) >> 4) | (x1 & mask_F0)); 297 } 298} 299 300kernel void kernel_convert_block_q4_0_trans4_ns( 301 global struct block_q4_0 * src0, 302 __global uint * dst_q, 303 __global half * dst_d, 304 uint ne00, 305 uint ne01 306) { 307 uint i00 = get_global_id(1); 308 uint i01 = get_global_id(0); 309 uint i02 = get_global_id(2); 310 311 if (i01 >= ne01) { 312 return; 313 } 314 315 uint ne00_blk = ne00 / QK4_0; 316 uint src_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 317 uint dst_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 318 319 global struct block_q4_0 * b = src0 + src_blk_offset; 320 dst_d[dst_blk_offset] = b->d; 321 322 // extract quantization and unshuffle 323 ushort8 pre_block = ((global ushort8 *)(&(b->qs[0])))[0]; 324 325 ushort8 post_block = (ushort8)(0); 326 327 uchar * pre_block_ptr = (uchar *)(&pre_block); 328 uchar * post_block_ptr = (uchar *)(&post_block); 329 330 for (int i = 0; i < QK4_0 / 4; ++i) { 331 uchar x0 = pre_block_ptr[2*i + 0]; 332 uchar x1 = pre_block_ptr[2*i + 1]; 333 334 post_block_ptr[i + 0 ] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 335 post_block_ptr[i + QK4_0 / 4] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 336 } 337 338 uint4 q_block = as_uint4(post_block); 339 340 uint offset = i02 * ne00_blk * ne01 * 4 + i00 * ne01 * 4 + i01; 341 dst_q[offset] = q_block.x; 342 dst_q[offset + ne01] = q_block.y; 343 dst_q[offset + ne01 * 2] = q_block.z; 344 dst_q[offset + ne01 * 3] = q_block.w; 345} 346 347kernel void kernel_restore_block_q4_0_trans4_ns( 348 __global uint * src_q, 349 __global half * src_d, 350 __global struct block_q4_0 * dst0, 351 uint ne00, 352 uint ne01 353) { 354 uint i00 = get_global_id(1); 355 uint i01 = get_global_id(0); 356 uint i02 = get_global_id(2); 357 358 if (i01 >= ne01) { 359 return; 360 } 361 362 uint ne00_blk = ne00 / QK4_0; 363 uint dst_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 364 uint src_d_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 365 366 __global struct block_q4_0 * b = dst0 + dst_blk_offset; 367 b->d = src_d[src_d_offset]; 368 369 // collect transposed quantization parts for a block 370 uint src_q_offset = i02 * ne00_blk * ne01 * 4 + i00 * ne01 * 4 + i01; 371 uint4 q_block; 372 q_block.x = src_q[src_q_offset]; 373 q_block.y = src_q[src_q_offset + ne01]; 374 q_block.z = src_q[src_q_offset + ne01 * 2]; 375 q_block.w = src_q[src_q_offset + ne01 * 3]; 376 377 ushort8 post_block = as_ushort8(q_block); 378 ushort8 pre_block = (ushort8)(0); 379 380 uchar * pre_block_ptr = (uchar *)(&pre_block); 381 uchar * post_block_ptr = (uchar *)(&post_block); 382 383 for (int i = 0; i < QK4_0 / 4; ++i) { 384 uchar x0 = post_block_ptr[i + 0]; 385 uchar x1 = post_block_ptr[i + QK4_0 / 4]; 386 387 pre_block_ptr[2 * i + 0] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 388 pre_block_ptr[2 * i + 1] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 389 } 390 391 ((__global ushort8 *)(&(b->qs[0])))[0] = pre_block; 392} 393 394//------------------------------------------------------------------------------ 395// kernel_convert_block_q4_1 396// Convert the block_q4_1 format to 2 separate arrays (AOS -> SOA). 397// This kernel does not deshuffle the bits. 398//------------------------------------------------------------------------------ 399kernel void kernel_convert_block_q4_1( 400 global struct block_q4_1 * src0, 401 global uchar * dst_q, 402 global half * dst_d, 403 global half * dst_m 404) { 405 global struct block_q4_1 * b = (global struct block_q4_1 *) src0 + get_global_id(0); 406 global uchar * q = (global uchar *) dst_q + QK4_1/2*get_global_id(0); 407 global half * d = (global half *) dst_d + get_global_id(0); 408 global half * m = (global half *) dst_m + get_global_id(0); 409 410 *d = b->d; 411 *m = b->m; 412 413 for (int i = 0; i < QK4_1/2; ++i) { 414 q[i] = b->qs[i]; 415 } 416} 417 418kernel void kernel_restore_block_q4_1( 419 global uchar * src_q, 420 global half * src_d, 421 global half * src_m, 422 global struct block_q4_1 * dst 423) { 424 global struct block_q4_1 * b = (global struct block_q4_1 *) dst + get_global_id(0); 425 global uchar * q = (global uchar *) src_q + QK4_1/2*get_global_id(0); 426 global half * d = (global half *) src_d + get_global_id(0); 427 global half * m = (global half *) src_m + get_global_id(0); 428 429 b->d = *d; 430 b->m = *m; 431 for (int i = 0; i < QK4_1/2; ++i) { 432 b->qs[i] = q[i]; 433 } 434} 435 436kernel void kernel_convert_block_q4_1_noshuffle( 437 global struct block_q4_1 * src0, 438 global uchar * dst_q, 439 global half * dst_d, 440 global half * dst_m 441) { 442 global struct block_q4_1 * b = (global struct block_q4_1 *) src0 + get_global_id(0); 443 global uchar * q = (global uchar *) dst_q + QK4_1/2*get_global_id(0); 444 global half * d = (global half *) dst_d + get_global_id(0); 445 global half * m = (global half *) dst_m + get_global_id(0); 446 447 *d = b->d; 448 *m = b->m; 449 for (int i = 0; i < QK4_1/4; ++i) { 450 uchar x0 = b->qs[2*i + 0]; 451 uchar x1 = b->qs[2*i + 1]; 452 453 q[i + 0 ] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 454 q[i + QK4_1/4] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 455 456#ifdef ADRENO_GPU 457 if (get_global_id(0) == 65536*4096) { 458 printf("%04x - %02x\n" , * ( global ushort* ) d , (( x0 & 0xF0 ) >> 4 ) | (x1 & 0xF0)); 459} 460#endif 461} 462} 463 464kernel void kernel_restore_block_q4_1_noshuffle( 465global uchar * src_q, 466global half * src_d, 467global half * src_m, 468global struct block_q4_1 * dst, 469uchar mask_0F, 470uchar mask_F0 471) { 472global struct block_q4_1 * b = (global struct block_q4_1 *) dst + get_global_id(0); 473global uchar * q = (global uchar *) src_q + QK4_1/2*get_global_id(0); 474global half * d = (global half *) src_d + get_global_id(0); 475global half * m = (global half *) src_m + get_global_id(0); 476 477b->d = *d; 478b->m = *m; 479for (int i = 0; i < QK4_1/4; ++i) { 480uchar x0 = q[i + 0 ] ; 481uchar x1 = q[i + QK4_1/4]; 482 483b->qs[2*i + 0] = convert_uchar((x0 & mask_0F) | (( x1 & mask_0F ) << 4 ) ); 484 b->qs[2*i + 1] = convert_uchar(((x0 & mask_F0) >> 4) | (x1 & mask_F0)); 485 } 486} 487 488kernel void kernel_convert_block_q4_1_trans4_ns( 489 __global struct block_q4_1 * src0, 490 __global uint * dst_q, 491 __global half * dst_d, 492 __global half * dst_m, 493 uint ne00, 494 uint ne01 495) { 496 uint i00 = get_global_id(1); 497 uint i01 = get_global_id(0); 498 uint i02 = get_global_id(2); 499 500 if (i01 >= ne01) { 501 return; 502 } 503 504 uint ne00_blk = ne00 / QK4_1; 505 uint src_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 506 uint dst_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 507 508 global struct block_q4_1 * b = src0 + src_blk_offset; 509 dst_d[dst_blk_offset] = b->d; 510 dst_m[dst_blk_offset] = b->m; 511 512 // extract quantization and unshuffle 513 ushort8 pre_block = ((global ushort8 *)(&(b->qs[0])))[0]; 514 515 ushort8 post_block = (ushort8)(0); 516 517 uchar * pre_block_ptr = (uchar *)(&pre_block); 518 uchar * post_block_ptr = (uchar *)(&post_block); 519 520 for (int i = 0; i < QK4_1 / 4; ++i) { 521 uchar x0 = pre_block_ptr[2*i + 0]; 522 uchar x1 = pre_block_ptr[2*i + 1]; 523 524 post_block_ptr[i + 0 ] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 525 post_block_ptr[i + QK4_1 / 4] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 526 } 527 528 uint4 q_block = as_uint4(post_block); 529 530 uint offset = i02 * ne00_blk * ne01 * 4 + i00 * ne01 * 4 + i01; 531 dst_q[offset] = q_block.x; 532 dst_q[offset + ne01] = q_block.y; 533 dst_q[offset + ne01 * 2] = q_block.z; 534 dst_q[offset + ne01 * 3] = q_block.w; 535} 536 537kernel void kernel_restore_block_q4_1_trans4_ns( 538 __global uint * src_q, 539 __global half * src_d, 540 __global half * src_m, 541 __global struct block_q4_1 * dst0, 542 uint ne00, 543 uint ne01 544) { 545 int i00 = get_global_id(1); 546 uint i01 = get_global_id(0); 547 uint i02 = get_global_id(2); 548 549 if (i01 >= ne01) { 550 return; 551 } 552 553 uint ne00_blk = ne00 / QK4_1; 554 uint dst_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 555 uint src_dm_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 556 557 __global struct block_q4_1 * b = dst0 + dst_blk_offset; 558 b->d = src_d[src_dm_offset]; 559 b->m = src_m[src_dm_offset]; 560 561 // collect transposed quantization parts for a block 562 uint src_q_offset = i02 * ne00_blk * ne01 * 4 + i00 * ne01 * 4 + i01; 563 uint4 q_block; 564 q_block.x = src_q[src_q_offset]; 565 q_block.y = src_q[src_q_offset + ne01]; 566 q_block.z = src_q[src_q_offset + ne01 * 2]; 567 q_block.w = src_q[src_q_offset + ne01 * 3]; 568 569 ushort8 post_block = as_ushort8(q_block); 570 ushort8 pre_block = (ushort8)(0); 571 572 uchar * pre_block_ptr = (uchar *)(&pre_block); 573 uchar * post_block_ptr = (uchar *)(&post_block); 574 575 for (int i = 0; i < QK4_0 / 4; ++i) { 576 uchar x0 = post_block_ptr[i + 0]; 577 uchar x1 = post_block_ptr[i + QK4_0 / 4]; 578 579 pre_block_ptr[2 * i + 0] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 580 pre_block_ptr[2 * i + 1] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 581 } 582 583 ((__global ushort8 *)(&(b->qs[0])))[0] = pre_block; 584} 585 586//------------------------------------------------------------------------------ 587// kernel_convert_block_q5_0 588// Convert the block_q5_0 format to 3 separate arrays (AOS -> SOA). 589// This kernel does not deshuffle the bits. 590//------------------------------------------------------------------------------ 591kernel void kernel_convert_block_q5_0( 592 global struct block_q5_0 * src0, 593 global uchar * dst_qs, 594 global uint * dst_qh, 595 global half * dst_d, 596 ulong n_blk 597) { 598 if (get_global_id(0) >= n_blk) { 599 return; 600 } 601 602 global struct block_q5_0 * b = (global struct block_q5_0 *) src0 + get_global_id(0); 603 global uchar * qs = (global uchar *) dst_qs + (QK5_0/2)*get_global_id(0); 604 global uint * qh = (global uint *) dst_qh + get_global_id(0); 605 global half * d = (global half *) dst_d + get_global_id(0); 606 607 *d = b->d; 608 *qh = *((global uint *)(b->qh)); 609 610 for (int i = 0; i < QK5_0/2; ++i) { 611 qs[i] = b->qs[i]; 612 } 613} 614 615kernel void kernel_restore_block_q5_0( 616 global uchar * src_qs, 617 global uint * src_qh, 618 global half * src_d, 619 global struct block_q5_0 * dst 620) { 621 global struct block_q5_0 * b = (global struct block_q5_0 *) dst + get_global_id(0); 622 global uchar * qs = (global uchar *) src_qs + (QK5_0/2)*get_global_id(0); 623 global uint * qh = (global uint *) src_qh + get_global_id(0); 624 global half * d = (global half *) src_d + get_global_id(0); 625 626 b->d = *d; 627 *((global uint *)(b->qh)) = *qh; 628 for (int i = 0; i < QK5_0/2; ++i) { 629 b->qs[i] = qs[i]; 630 } 631} 632 633kernel void kernel_convert_block_q5_0_noshuffle( 634 global struct block_q5_0 * src0, 635 global uchar * dst_q, 636 global uint * dst_qh, 637 global half * dst_d 638) { 639 global struct block_q5_0 * b = (global struct block_q5_0 *) src0 + get_global_id(0); 640 global uchar * q = (global uchar *) dst_q + QK5_0/2*get_global_id(0); 641 global uint * qh = (global uint *) dst_qh + get_global_id(0); 642 global half * d = (global half *) dst_d + get_global_id(0); 643 644 *d = b->d; 645 *qh = *((global uint *)(b->qh)); 646 647 for (int i = 0; i < QK5_0/4; ++i) { 648 uchar x0 = b->qs[2*i + 0]; 649 uchar x1 = b->qs[2*i + 1]; 650 651 q[i + 0 ] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 652 q[i + QK5_0/4] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 653 654#ifdef ADRENO_GPU 655 if (get_global_id(0) == 65536*4096) { 656 printf("%04x - %02x\n" , * ( global ushort* ) d , (( x0 & 0xF0 ) >> 4 ) | (x1 & 0xF0)); 657} 658#endif 659} 660} 661 662kernel void kernel_restore_block_q5_0_noshuffle( 663global uchar * src_q, 664global uint * src_qh, 665global half * src_d, 666global struct block_q5_0 * dst, 667uchar mask_0F, 668uchar mask_F0 669) { 670global struct block_q5_0 * b = (global struct block_q5_0 *) dst + get_global_id(0); 671global uchar * q = (global uchar *) src_q + QK5_0/2*get_global_id(0); 672global uint * qh = (global uint *) src_qh + get_global_id(0); 673global half * d = (global half *) src_d + get_global_id(0); 674 675b->d = *d; 676*((global uint *)(b->qh)) = *qh; 677 678for (int i = 0; i < QK5_0/4; ++i) { 679uchar x0 = q[i + 0 ]; 680uchar x1 = q[i + QK5_0/4]; 681 682b->qs[2*i + 0] = convert_uchar((x0 & mask_0F) | (( x1 & mask_0F ) << 4 ) ); 683 b->qs[2*i + 1] = convert_uchar(((x0 & mask_F0) >> 4) | (x1 & mask_F0)); 684 } 685} 686 687kernel void kernel_convert_block_q5_0_trans4_ns( 688 __global struct block_q5_0 * src0, 689 __global uint * dst_qs, 690 __global uint * dst_qh, 691 __global half * dst_d, 692 uint ne00, 693 uint ne01 694) { 695 uint i00 = get_global_id(1); 696 uint i01 = get_global_id(0); 697 uint i02 = get_global_id(2); 698 699 if (i01 >= ne01) { 700 return; 701 } 702 703 uint ne00_blk = ne00 / QK5_0; 704 uint src_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 705 uint dst_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 706 707 global struct block_q5_0 * b = src0 + src_blk_offset; 708 dst_d[dst_blk_offset] = b->d; 709 710 dst_qh[dst_blk_offset] = ((global uint *)(&(b->qh[0])))[0]; 711 712 // extract quantization and unshuffle 713 ushort8 pre_block = ((global ushort8 *)(&(b->qs[0])))[0]; 714 ushort8 post_block = (ushort8)(0); 715 716 uchar * pre_block_ptr = (uchar *)(&pre_block); 717 uchar * post_block_ptr = (uchar *)(&post_block); 718 719 for (int i = 0; i < QK5_0 / 4; ++i) { 720 uchar x0 = pre_block_ptr[2*i + 0]; 721 uchar x1 = pre_block_ptr[2*i + 1]; 722 723 post_block_ptr[i + 0 ] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 724 post_block_ptr[i + QK5_0 / 4] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 725 } 726 727 uint4 q_block = as_uint4(post_block); 728 729 uint offset = i02 * ne00_blk * ne01 * 4 + i00 * ne01 * 4 + i01; 730 dst_qs[offset] = q_block.x; 731 dst_qs[offset + ne01] = q_block.y; 732 dst_qs[offset + ne01 * 2] = q_block.z; 733 dst_qs[offset + ne01 * 3] = q_block.w; 734} 735 736kernel void kernel_restore_block_q5_0_trans4_ns( 737 __global uint * src_qs, 738 __global uint * src_qh, 739 __global half * src_d, 740 __global struct block_q5_0 * dst0, 741 uint ne00, 742 uint ne01 743) { 744 int i00 = get_global_id(1); 745 uint i01 = get_global_id(0); 746 uint i02 = get_global_id(2); 747 748 if (i01 >= ne01) { 749 return; 750 } 751 752 uint ne00_blk = ne00 / QK5_0; 753 uint dst_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 754 uint src_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 755 756 __global struct block_q5_0 * b = dst0 + dst_blk_offset; 757 b->d = src_d[src_blk_offset]; 758 759 ((__global uint *)(&(b->qh[0])))[0] = src_qh[src_blk_offset]; 760 761 // collect transposed quantization parts for a block 762 uint src_q_offset = i02 * ne00_blk * ne01 * 4 + i00 * ne01 * 4 + i01; 763 uint4 q_block; 764 q_block.x = src_qs[src_q_offset]; 765 q_block.y = src_qs[src_q_offset + ne01]; 766 q_block.z = src_qs[src_q_offset + ne01 * 2]; 767 q_block.w = src_qs[src_q_offset + ne01 * 3]; 768 769 ushort8 post_block = as_ushort8(q_block); 770 ushort8 pre_block = (ushort8)(0); 771 772 uchar * pre_block_ptr = (uchar *)(&pre_block); 773 uchar * post_block_ptr = (uchar *)(&post_block); 774 775 for (int i = 0; i < QK5_0 / 4; ++i) { 776 uchar x0 = post_block_ptr[i + 0]; 777 uchar x1 = post_block_ptr[i + QK5_0 / 4]; 778 779 pre_block_ptr[2 * i + 0] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 780 pre_block_ptr[2 * i + 1] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 781 } 782 783 ((__global ushort8 *)(&(b->qs[0])))[0] = pre_block; 784} 785 786//------------------------------------------------------------------------------ 787// kernel_convert_block_q5_1 788// Convert the block_q5_1 format to 4 separate arrays (AOS -> SOA). 789// This kernel does not deshuffle the bits. 790//------------------------------------------------------------------------------ 791kernel void kernel_convert_block_q5_1( 792 global struct block_q5_1 * src0, 793 global uchar * dst_qs, 794 global uint * dst_qh, 795 global half * dst_d, 796 global half * dst_m, 797 ulong n_blk 798) { 799 if (get_global_id(0) >= n_blk) { 800 return; 801 } 802 803 global struct block_q5_1 * b = (global struct block_q5_1 *) src0 + get_global_id(0); 804 global uchar * qs = (global uchar *) dst_qs + (QK5_1/2)*get_global_id(0); 805 global uint * qh = (global uint *) dst_qh + get_global_id(0); 806 global half * d = (global half *) dst_d + get_global_id(0); 807 global half * m = (global half *) dst_m + get_global_id(0); 808 809 *d = b->d; 810 *m = b->m; 811 *qh = *((global uint *)(b->qh)); 812 813 for (int i = 0; i < QK5_1/2; ++i) { 814 qs[i] = b->qs[i]; 815 } 816} 817 818kernel void kernel_restore_block_q5_1( 819 global uchar * src_qs, 820 global uint * src_qh, 821 global half * src_d, 822 global half * src_m, 823 global struct block_q5_1 * dst 824) { 825 global struct block_q5_1 * b = (global struct block_q5_1 *) dst + get_global_id(0); 826 global uchar * qs = (global uchar *) src_qs + (QK5_1/2)*get_global_id(0); 827 global uint * qh = (global uint *) src_qh + get_global_id(0); 828 global half * d = (global half *) src_d + get_global_id(0); 829 global half * m = (global half *) src_m + get_global_id(0); 830 831 b->d = *d; 832 b->m = *m; 833 *((global uint *)(b->qh)) = *qh; 834 for (int i = 0; i < QK5_1/2; ++i) { 835 b->qs[i] = qs[i]; 836 } 837} 838 839kernel void kernel_convert_block_q5_1_noshuffle( 840 global struct block_q5_1 * src0, 841 global uchar * dst_q, 842 global uint * dst_qh, 843 global half * dst_d, 844 global half * dst_m 845) { 846 global struct block_q5_1 * b = (global struct block_q5_1 *) src0 + get_global_id(0); 847 global uchar * q = (global uchar *) dst_q + QK5_1/2*get_global_id(0); 848 global uint * qh = (global uint *) dst_qh + get_global_id(0); 849 global half * d = (global half *) dst_d + get_global_id(0); 850 global half * m = (global half *) dst_m + get_global_id(0); 851 852 *d = b->d; 853 *m = b->m; 854 *qh = *((global uint *)(b->qh)); 855 856 for (int i = 0; i < QK5_1/4; ++i) { 857 uchar x0 = b->qs[2*i + 0]; 858 uchar x1 = b->qs[2*i + 1]; 859 860 q[i + 0 ] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 861 q[i + QK5_1/4] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 862 863#ifdef ADRENO_GPU 864 if (get_global_id(0) == 65536*4096) { 865 printf("%04x - %02x\n" , * ( global ushort* ) d , (( x0 & 0xF0 ) >> 4 ) | (x1 & 0xF0)); 866} 867#endif 868} 869} 870 871kernel void kernel_restore_block_q5_1_noshuffle( 872global uchar * src_q, 873global uint * src_qh, 874global half * src_d, 875global half * src_m, 876global struct block_q5_1 * dst, 877uchar mask_0F, 878uchar mask_F0 879) { 880global struct block_q5_1 * b = (global struct block_q5_1 *) dst + get_global_id(0); 881global uchar * q = (global uchar *) src_q + QK5_1/2*get_global_id(0); 882global uint * qh = (global uint *) src_qh + get_global_id(0); 883global half * d = (global half *) src_d + get_global_id(0); 884global half * m = (global half *) src_m + get_global_id(0); 885 886b->d = *d; 887b->m = *m; 888*((global uint *)(b->qh)) = *qh; 889 890for (int i = 0; i < QK5_1/4; ++i) { 891uchar x0 = q[i + 0 ]; 892uchar x1 = q[i + QK5_1/4]; 893 894b->qs[2*i + 0] = convert_uchar((x0 & mask_0F) | (( x1 & mask_0F ) << 4 ) ); 895 b->qs[2*i + 1] = convert_uchar(((x0 & mask_F0) >> 4) | (x1 & mask_F0)); 896 } 897} 898 899kernel void kernel_convert_block_q5_1_trans4_ns( 900 __global struct block_q5_1 * src0, 901 __global uint * dst_qs, 902 __global uint * dst_qh, 903 __global half * dst_d, 904 __global half * dst_m, 905 uint ne00, 906 uint ne01 907) { 908 uint i00 = get_global_id(1); 909 uint i01 = get_global_id(0); 910 uint i02 = get_global_id(2); 911 912 if (i01 >= ne01) { 913 return; 914 } 915 916 uint ne00_blk = ne00 / QK5_1; 917 uint src_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 918 uint dst_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 919 920 global struct block_q5_1 * b = src0 + src_blk_offset; 921 dst_d[dst_blk_offset] = b->d; 922 dst_m[dst_blk_offset] = b->m; 923 924 dst_qh[dst_blk_offset] = ((global uint *)(&(b->qh[0])))[0]; 925 926 // extract quantization and unshuffle 927 ushort8 pre_block = ((global ushort8 *)(&(b->qs[0])))[0]; 928 ushort8 post_block = (ushort8)(0); 929 930 uchar * pre_block_ptr = (uchar *)(&pre_block); 931 uchar * post_block_ptr = (uchar *)(&post_block); 932 933 for (int i = 0; i < QK5_1 / 4; ++i) { 934 uchar x0 = pre_block_ptr[2*i + 0]; 935 uchar x1 = pre_block_ptr[2*i + 1]; 936 937 post_block_ptr[i + 0 ] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 938 post_block_ptr[i + QK5_1 / 4] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 939 } 940 941 uint4 q_block = as_uint4(post_block); 942 943 uint offset = i02 * ne00_blk * ne01 * 4 + i00 * ne01 * 4 + i01; 944 dst_qs[offset] = q_block.x; 945 dst_qs[offset + ne01] = q_block.y; 946 dst_qs[offset + ne01 * 2] = q_block.z; 947 dst_qs[offset + ne01 * 3] = q_block.w; 948} 949 950kernel void kernel_restore_block_q5_1_trans4_ns( 951 __global uint * src_qs, 952 __global uint * src_qh, 953 __global half * src_d, 954 __global half * src_m, 955 __global struct block_q5_1 * dst0, 956 uint ne00, 957 uint ne01 958) { 959 int i00 = get_global_id(1); 960 uint i01 = get_global_id(0); 961 uint i02 = get_global_id(2); 962 963 if (i01 >= ne01) { 964 return; 965 } 966 967 uint ne00_blk = ne00 / QK5_1; 968 uint dst_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 969 uint src_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 970 971 __global struct block_q5_1 * b = dst0 + dst_blk_offset; 972 b->d = src_d[src_blk_offset]; 973 b->m = src_m[src_blk_offset]; 974 975 ((__global uint *)(&(b->qh[0])))[0] = src_qh[src_blk_offset]; 976 977 // collect transposed quantization parts for a block 978 uint src_q_offset = i02 * ne00_blk * ne01 * 4 + i00 * ne01 * 4 + i01; 979 uint4 q_block; 980 q_block.x = src_qs[src_q_offset]; 981 q_block.y = src_qs[src_q_offset + ne01]; 982 q_block.z = src_qs[src_q_offset + ne01 * 2]; 983 q_block.w = src_qs[src_q_offset + ne01 * 3]; 984 985 ushort8 post_block = as_ushort8(q_block); 986 ushort8 pre_block = (ushort8)(0); 987 988 uchar * pre_block_ptr = (uchar *)(&pre_block); 989 uchar * post_block_ptr = (uchar *)(&post_block); 990 991 for (int i = 0; i < QK5_1 / 4; ++i) { 992 uchar x0 = post_block_ptr[i + 0]; 993 uchar x1 = post_block_ptr[i + QK5_1 / 4]; 994 995 pre_block_ptr[2 * i + 0] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 996 pre_block_ptr[2 * i + 1] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 997 } 998 ((__global ushort8 *)(&(b->qs[0])))[0] = pre_block; 999} 1000 1001kernel void kernel_convert_block_q4_k_trans4_ns( 1002 __global struct block_q4_K * src0, 1003 __global uint * dst_q, 1004 __global half * dst_d, 1005 __global half * dst_dm, 1006 __global uchar * dst_s, 1007 uint ne00, 1008 uint ne01, 1009 uchar mask_0F, 1010 uchar mask_F0 1011) { 1012 uint i00 = get_global_id(1); 1013 uint i01 = get_global_id(0); 1014 uint i02 = get_global_id(2); 1015 1016 if (i01 >= ne01) { 1017 return; 1018 } 1019 1020 uint ne00_blk = ne00 / QK_K; 1021 uint src_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1022 uint dst_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 1023 1024 __global struct block_q4_K * b = src0 + src_blk_offset; 1025 1026 dst_d [dst_blk_offset] = b->d; 1027 dst_dm[dst_blk_offset] = b->dm; 1028 1029 uint4 qv[8]; 1030 uchar * qv_bytes = (uchar *)qv; 1031 for (int i = 0; i < QK_K / 64; ++i) { 1032 for (int j = 0; j < 16; ++j) { 1033 uchar x0 = b->q[i*32 + 2*j]; 1034 uchar x1 = b->q[i*32 + 2*j + 1]; 1035 1036 qv_bytes[i*32 + j ] = convert_uchar(x0 & mask_0F) | convert_uchar((x1 & mask_0F) << 4); 1037 qv_bytes[i*32 + j + 16] = convert_uchar((x0 & mask_F0) >> 4) | convert_uchar(x1 & mask_F0); 1038 } 1039 } 1040 1041 uint base = i02 * ne00_blk * ne01 * 32 + i00 * ne01 * 32 + i01; 1042 #pragma unroll 1043 for (int p = 0; p < 8; ++p) { 1044 uint4 v = qv[p]; 1045 dst_q[base + (p * 4 + 0) * ne01] = v.x; 1046 dst_q[base + (p * 4 + 1) * ne01] = v.y; 1047 dst_q[base + (p * 4 + 2) * ne01] = v.z; 1048 dst_q[base + (p * 4 + 3) * ne01] = v.w; 1049 } 1050 1051 __global uchar * s_dst = dst_s + (i02 * ne01 + i01) * ne00_blk * K_SCALE_SIZE + i00 * K_SCALE_SIZE; 1052 #pragma unroll 1053 for (int i = 0; i < K_SCALE_SIZE; ++i) { 1054 s_dst[i] = b->s[i]; 1055 } 1056} 1057 1058kernel void kernel_restore_block_q4_k_trans4_ns( 1059 __global uint * src_q, 1060 __global half * src_d, 1061 __global half * src_dm, 1062 __global uchar * src_s, 1063 __global struct block_q4_K * dst0, 1064 uint ne00, 1065 uint ne01, 1066 uchar mask_0F, 1067 uchar mask_F0 1068) { 1069 uint i00 = get_global_id(1); // block index along K 1070 uint i01 = get_global_id(0); // row index 1071 uint i02 = get_global_id(2); // batch index 1072 1073 if (i01 >= ne01) { 1074 return; 1075 } 1076 1077 uint ne00_blk = ne00 / QK_K; 1078 1079 uint src_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 1080 uint dst_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1081 1082 __global struct block_q4_K * b = dst0 + dst_blk_offset; 1083 1084 b->d = src_d[src_blk_offset]; 1085 b->dm = src_dm[src_blk_offset]; 1086 1087 __global uchar * s_src = src_s + (i02 * ne01 + i01) * ne00_blk * K_SCALE_SIZE + i00 * K_SCALE_SIZE; 1088 for (int i = 0; i < K_SCALE_SIZE; ++i) { 1089 b->s[i] = s_src[i]; 1090 } 1091 1092 uint base = i02 * ne00_blk * ne01 * 32 + i00 * ne01 * 32 + i01; 1093 1094 uint4 qv[8]; 1095 for (int p = 0; p < 8; ++p) { 1096 qv[p].x = src_q[base + (p * 4 + 0) * ne01]; 1097 qv[p].y = src_q[base + (p * 4 + 1) * ne01]; 1098 qv[p].z = src_q[base + (p * 4 + 2) * ne01]; 1099 qv[p].w = src_q[base + (p * 4 + 3) * ne01]; 1100 } 1101 1102 uchar * qv_bytes = (uchar *)qv; 1103 for (int i = 0; i < QK_K / 64; ++i) { 1104 for (int j = 0; j < 16; ++j) { 1105 uchar lo = qv_bytes[i*32 + j]; 1106 uchar hi = qv_bytes[i*32 + j + 16]; 1107 b->q[i*32 + 2*j] = convert_uchar((lo & mask_0F) | ((hi & mask_0F) << 4)); 1108 b->q[i*32 + 2*j + 1] = convert_uchar(((lo & mask_F0) >> 4) | (hi & mask_F0)); 1109 } 1110 } 1111} 1112 1113//------------------------------------------------------------------------------ 1114// kernel_convert_block_q4_k_tiled_ns 1115// 1116// Tiled-wide layout for the long-vocab q4_K lm_head/embed GEMV (decode path). 1117// Mirror of kernel_convert_block_q6_k_tiled_ns: recovers each weight's 4-bit 1118// code in CANONICAL ggml element order (e in [0,256)) and re-packs into 32 uints 1119// (8 codes/uint), stored TILED by 64 output rows so the matching GEMV 1120// (gemv_noshuffle_q4_k_f32_tiled) coalesces every weight load. The 12-byte 1121// packed scale block `s` and d/dm are stored per (row, K-block) tiled; the GEMV 1122// re-derives the 8 (scale,min) pairs via get_scale_min_k4, exactly like the o4 1123// kernel. Both ends owned here -> correct by construction vs the reference q4_K 1124// dequant. Requires ne01 % 64 == 0 (gated host-side). Buffer sizes identical to 1125// the trans4_ns layout. 1126// 1127// q uint4 granule g of (row r, K-block sb): idx = ((rt*ne00_blk+sb)*8 + g)*64 + rit 1128// s (12 bytes) of (r, sb): idx = (rt*ne00_blk+sb)*64 + rit, *12 1129// d/dm (half) of (r, sb): idx = (rt*ne00_blk+sb)*64 + rit 1130// where rt = r/64, rit = r%64. 1131//------------------------------------------------------------------------------ 1132kernel void kernel_convert_block_q4_k_tiled_ns( 1133 __global struct block_q4_K * src0, 1134 __global uint * dst_q, // 32 uints / superblock (4-bit codes, 8 codes/uint) 1135 __global half * dst_d, // 1 half / superblock 1136 __global half * dst_dm, // 1 half / superblock 1137 __global uchar * dst_s, // K_SCALE_SIZE (12) bytes / superblock 1138 uint ne00, 1139 uint ne01 1140) { 1141 uint i00 = get_global_id(1); // K-block index (superblock along ne00) 1142 uint i01 = get_global_id(0); // output row index (along ne01) 1143 uint i02 = get_global_id(2); // batch 1144 1145 uint ne00_blk = ne00 / QK_K; 1146 1147 uint src_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1148 __global struct block_q4_K * b = src0 + src_blk_offset; 1149 1150 uint rt = i01 / 64; 1151 uint rit = i01 % 64; 1152 uint tile_blk = (i02 * (ne01 / 64) + rt) * ne00_blk + i00; 1153 1154 // --- recover canonical 4-bit codes in e-order, pack 8 codes/uint --- 1155 uint qw[32] = {0}; 1156 for (uint e = 0; e < 256; ++e) { 1157 uint g = e >> 6; // group 0..3 (q advances 32 bytes/group) 1158 uint within = e & 63u; 1159 uint hlf = within >> 5; // 0 = low nibble, 1 = high nibble 1160 uint l = within & 31u; // 0..31 1161 uchar byte = b->q[g * 32u + l]; 1162 uint code = (hlf == 0u) ? (uint)(byte & 0x0F) : (uint)(byte >> 4); 1163 qw[e >> 3] |= code << ((e & 7u) * 4u); 1164 } 1165 1166 for (uint gr = 0; gr < 8; ++gr) { 1167 uint base = (tile_blk * 8u + gr) * 64u + rit; // uint4 index 1168 dst_q[base * 4u + 0u] = qw[gr * 4u + 0u]; 1169 dst_q[base * 4u + 1u] = qw[gr * 4u + 1u]; 1170 dst_q[base * 4u + 2u] = qw[gr * 4u + 2u]; 1171 dst_q[base * 4u + 3u] = qw[gr * 4u + 3u]; 1172 } 1173 1174 // packed scales (12 bytes), tiled per (row, block) 1175 __global uchar * s_dst = dst_s + (tile_blk * 64u + rit) * K_SCALE_SIZE; 1176 #pragma unroll 1177 for (int i = 0; i < K_SCALE_SIZE; ++i) { 1178 s_dst[i] = b->s[i]; 1179 } 1180 1181 dst_d [tile_blk * 64u + rit] = b->d; 1182 dst_dm[tile_blk * 64u + rit] = b->dm; 1183} 1184 1185kernel void kernel_convert_block_q5_k_trans4_ns( 1186 __global struct block_q5_K * src0, 1187 __global uint * dst_qs, 1188 __global uint * dst_qh, 1189 __global half * dst_d, 1190 __global half * dst_dm, 1191 __global uchar * dst_s, 1192 uint ne00, 1193 uint ne01, 1194 uchar mask_0F, 1195 uchar mask_F0 1196) { 1197 uint i00 = get_global_id(1); 1198 uint i01 = get_global_id(0); 1199 uint i02 = get_global_id(2); 1200 1201 if (i01 >= ne01) { 1202 return; 1203 } 1204 1205 uint ne00_blk = ne00 / QK_K; 1206 uint src_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1207 uint dst_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 1208 1209 __global struct block_q5_K * b = src0 + src_blk_offset; 1210 1211 dst_d [dst_blk_offset] = b->d; 1212 dst_dm[dst_blk_offset] = b->dm; 1213 1214 for (int k = 0; k < 8; k++) { 1215 uchar b0 = 0, b1 = 0, b2 = 0, b3 = 0; 1216 for (int bit = 0; bit < 8; bit++) { 1217 b0 |= (uchar)(((b->qh[bit] >> k) & 1) << bit); 1218 b1 |= (uchar)(((b->qh[8 + bit] >> k) & 1) << bit); 1219 b2 |= (uchar)(((b->qh[16 + bit] >> k) & 1) << bit); 1220 b3 |= (uchar)(((b->qh[24 + bit] >> k) & 1) << bit); 1221 } 1222 uint packed = (uint)b0 | ((uint)b1 << 8) | ((uint)b2 << 16) | ((uint)b3 << 24); 1223 dst_qh[i01 + (i00 * 8 + k) * ne01 + i02 * ne00_blk * 8 * ne01] = packed; 1224 } 1225 1226 uint4 qv[8]; 1227 uchar * qv_bytes = (uchar *)qv; 1228 for (int i = 0; i < QK_K / 64; ++i) { 1229 for (int j = 0; j < 16; ++j) { 1230 uchar x0 = b->qs[i*32 + 2*j]; 1231 uchar x1 = b->qs[i*32 + 2*j + 1]; 1232 1233 qv_bytes[i*32 + j ] = convert_uchar(x0 & mask_0F) | convert_uchar((x1 & mask_0F) << 4); 1234 qv_bytes[i*32 + j + 16] = convert_uchar((x0 & mask_F0) >> 4) | convert_uchar(x1 & mask_F0); 1235 } 1236 } 1237 1238 uint base = i02 * ne00_blk * ne01 * 32 + i00 * ne01 * 32 + i01; 1239 #pragma unroll 1240 for (int p = 0; p < 8; ++p) { 1241 uint4 v = qv[p]; 1242 dst_qs[base + (p * 4 + 0) * ne01] = v.x; 1243 dst_qs[base + (p * 4 + 1) * ne01] = v.y; 1244 dst_qs[base + (p * 4 + 2) * ne01] = v.z; 1245 dst_qs[base + (p * 4 + 3) * ne01] = v.w; 1246 } 1247 1248 __global uchar * s_dst = dst_s + (i02 * ne01 + i01) * ne00_blk * K_SCALE_SIZE + i00 * K_SCALE_SIZE; 1249 #pragma unroll 1250 for (int i = 0; i < K_SCALE_SIZE; ++i) { 1251 s_dst[i] = b->s[i]; 1252 } 1253} 1254 1255kernel void kernel_restore_block_q5_k_trans4_ns( 1256 __global uint * src_qs, 1257 __global uint * src_qh, 1258 __global half * src_d, 1259 __global half * src_dm, 1260 __global uchar * src_s, 1261 __global struct block_q5_K * dst0, 1262 uint ne00, 1263 uint ne01, 1264 uchar mask_0F, 1265 uchar mask_F0 1266) { 1267 uint i00 = get_global_id(1); // block index along K 1268 uint i01 = get_global_id(0); // row index 1269 uint i02 = get_global_id(2); // batch index 1270 1271 if (i01 >= ne01) { 1272 return; 1273 } 1274 1275 uint ne00_blk = ne00 / QK_K; 1276 1277 uint src_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 1278 uint dst_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1279 1280 __global struct block_q5_K * b = dst0 + dst_blk_offset; 1281 1282 b->d = src_d[src_blk_offset]; 1283 b->dm = src_dm[src_blk_offset]; 1284 1285 for (int j = 0; j < 32; j++) b->qh[j] = 0; 1286 for (int k = 0; k < 8; k++) { 1287 uint packed = src_qh[i01 + (i00 * 8 + k) * ne01 + i02 * ne00_blk * 8 * ne01]; 1288 uchar b0 = (uchar)(packed & 0xFF); 1289 uchar b1 = (uchar)((packed >> 8) & 0xFF); 1290 uchar b2 = (uchar)((packed >> 16) & 0xFF); 1291 uchar b3 = (uchar)((packed >> 24) & 0xFF); 1292 for (int bit = 0; bit < 8; bit++) { 1293 b->qh[bit] |= (uchar)(((b0 >> bit) & 1) << k); 1294 b->qh[8 + bit] |= (uchar)(((b1 >> bit) & 1) << k); 1295 b->qh[16 + bit] |= (uchar)(((b2 >> bit) & 1) << k); 1296 b->qh[24 + bit] |= (uchar)(((b3 >> bit) & 1) << k); 1297 } 1298 } 1299 1300 __global uchar * s_src = src_s + (i02 * ne01 + i01) * ne00_blk * K_SCALE_SIZE + i00 * K_SCALE_SIZE; 1301 for (int i = 0; i < K_SCALE_SIZE; ++i) { 1302 b->s[i] = s_src[i]; 1303 } 1304 1305 uint base = i02 * ne00_blk * ne01 * 32 + i00 * ne01 * 32 + i01; 1306 1307 uint4 qv[8]; 1308 for (int p = 0; p < 8; ++p) { 1309 qv[p].x = src_qs[base + (p * 4 + 0) * ne01]; 1310 qv[p].y = src_qs[base + (p * 4 + 1) * ne01]; 1311 qv[p].z = src_qs[base + (p * 4 + 2) * ne01]; 1312 qv[p].w = src_qs[base + (p * 4 + 3) * ne01]; 1313 } 1314 1315 uchar * qv_bytes = (uchar *)qv; 1316 for (int i = 0; i < QK_K / 64; ++i) { 1317 for (int j = 0; j < 16; ++j) { 1318 uchar lo = qv_bytes[i*32 + j]; 1319 uchar hi = qv_bytes[i*32 + j + 16]; 1320 b->qs[i*32 + 2*j] = convert_uchar((lo & mask_0F) | ((hi & mask_0F) << 4)); 1321 b->qs[i*32 + 2*j + 1] = convert_uchar(((lo & mask_F0) >> 4) | (hi & mask_F0)); 1322 } 1323 } 1324} 1325 1326kernel void kernel_convert_block_q6_k_trans4_ns( 1327 __global struct block_q6_K * src0, 1328 __global uint * dst_ql, 1329 __global uint * dst_qh, 1330 __global half * dst_d, 1331 __global char * dst_s, 1332 uint ne00, 1333 uint ne01, 1334 uchar mask_0F, 1335 uchar mask_F0 1336) { 1337 uint i00 = get_global_id(1); 1338 uint i01 = get_global_id(0); 1339 uint i02 = get_global_id(2); 1340 1341 if (i01 >= ne01) { 1342 return; 1343 } 1344 1345 uint ne00_blk = ne00 / QK_K; 1346 1347 uint src_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1348 uint dst_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 1349 1350 __global struct block_q6_K * b = src0 + src_blk_offset; 1351 1352 dst_d[dst_blk_offset] = b->d; 1353 1354 uint4 qlv[8]; 1355 uchar * qlv_bytes = (uchar *)qlv; 1356 for (int i = 0; i < 2; ++i) { 1357 for (int j = 0; j < 16; ++j) { 1358 uchar x0 = b->ql[i*64 + 2*j]; 1359 uchar x1 = b->ql[i*64 + 2*j + 1]; 1360 uchar x2 = b->ql[i*64 + 32 + 2*j]; 1361 uchar x3 = b->ql[i*64 + 32 + 2*j + 1]; 1362 qlv_bytes[i*64 + j ] = convert_uchar(x0 & mask_0F) | convert_uchar((x1 & mask_0F) << 4); 1363 qlv_bytes[i*64 + j + 16] = convert_uchar(x2 & mask_0F) | convert_uchar((x3 & mask_0F) << 4); 1364 qlv_bytes[i*64 + j + 32] = convert_uchar((x0 & mask_F0) >> 4) | convert_uchar(x1 & mask_F0); 1365 qlv_bytes[i*64 + j + 48] = convert_uchar((x2 & mask_F0) >> 4) | convert_uchar(x3 & mask_F0); 1366 } 1367 } 1368 1369 uint ql_base = i02 * ne00_blk * ne01 * 32 + i00 * ne01 * 32 + i01; 1370 1371 #pragma unroll 1372 for (int p = 0; p < 8; ++p) { 1373 uint4 v = qlv[p]; 1374 dst_ql[ql_base + (p * 4 + 0) * ne01] = v.x; 1375 dst_ql[ql_base + (p * 4 + 1) * ne01] = v.y; 1376 dst_ql[ql_base + (p * 4 + 2) * ne01] = v.z; 1377 dst_ql[ql_base + (p * 4 + 3) * ne01] = v.w; 1378 } 1379 1380 uint qhv[16] = {0}; 1381 1382 for (int n = 0; n < 2; ++n) { 1383 for (int l = 0; l < 32; ++l) { 1384 uchar h = b->qh[n*32 + l]; 1385 int u = l / 16; 1386 int bit_pos = (l % 16) * 2; 1387 qhv[(n*4 + 0)*2 + u] |= ((uint)((h >> 0) & 0x03)) << bit_pos; 1388 qhv[(n*4 + 1)*2 + u] |= ((uint)((h >> 2) & 0x03)) << bit_pos; 1389 qhv[(n*4 + 2)*2 + u] |= ((uint)((h >> 4) & 0x03)) << bit_pos; 1390 qhv[(n*4 + 3)*2 + u] |= ((uint)((h >> 6) & 0x03)) << bit_pos; 1391 } 1392 } 1393 1394 uint qh_base = i02 * ne00_blk * ne01 * 16 + i00 * ne01 * 16 + i01; 1395 1396 for (int p = 0; p < 16; ++p) { 1397 dst_qh[qh_base + p * ne01] = qhv[p]; 1398 } 1399 1400 __global char * s_dst = dst_s + (i02 * ne01 + i01) * ne00_blk * 16 + i00 * 16; 1401 #pragma unroll 1402 for (int i = 0; i < 16; ++i) { 1403 s_dst[i] = b->scales[i]; 1404 } 1405} 1406 1407kernel void kernel_restore_block_q6_k_trans4_ns( 1408 __global uint * src_ql, 1409 __global uint * src_qh, 1410 __global half * src_d, 1411 __global char * src_s, 1412 __global struct block_q6_K * dst0, 1413 uint ne00, 1414 uint ne01, 1415 uchar mask_0F, 1416 uchar mask_F0 1417) { 1418 uint i00 = get_global_id(1); // block index along K 1419 uint i01 = get_global_id(0); // row index 1420 uint i02 = get_global_id(2); // batch index 1421 1422 if (i01 >= ne01) { 1423 return; 1424 } 1425 1426 uint ne00_blk = ne00 / QK_K; 1427 1428 uint src_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 1429 uint dst_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1430 1431 __global struct block_q6_K * b = dst0 + dst_blk_offset; 1432 1433 b->d = src_d[src_blk_offset]; 1434 1435 uint ql_base = i02 * ne00_blk * ne01 * 32 + i00 * ne01 * 32 + i01; 1436 uint4 qlv[8]; 1437 for (int p = 0; p < 8; ++p) { 1438 qlv[p].x = src_ql[ql_base + (p * 4 + 0) * ne01]; 1439 qlv[p].y = src_ql[ql_base + (p * 4 + 1) * ne01]; 1440 qlv[p].z = src_ql[ql_base + (p * 4 + 2) * ne01]; 1441 qlv[p].w = src_ql[ql_base + (p * 4 + 3) * ne01]; 1442 } 1443 1444 uchar * qlv_bytes = (uchar *)qlv; 1445 for (int i = 0; i < 2; ++i) { 1446 for (int j = 0; j < 16; ++j) { 1447 uchar lo_02 = qlv_bytes[i*64 + j]; 1448 uchar lo_13 = qlv_bytes[i*64 + j + 16]; 1449 uchar hi_02 = qlv_bytes[i*64 + j + 32]; 1450 uchar hi_13 = qlv_bytes[i*64 + j + 48]; 1451 b->ql[i*64 + 2*j] = convert_uchar((lo_02 & mask_0F) | ((hi_02 & mask_0F) << 4)); 1452 b->ql[i*64 + 2*j + 1] = convert_uchar(((lo_02 & mask_F0) >> 4) | (hi_02 & mask_F0)); 1453 b->ql[i*64 + 32 + 2*j] = convert_uchar((lo_13 & mask_0F) | ((hi_13 & mask_0F) << 4)); 1454 b->ql[i*64 + 32 + 2*j + 1] = convert_uchar(((lo_13 & mask_F0) >> 4) | (hi_13 & mask_F0)); 1455 } 1456 } 1457 1458 uint qh_base = i02 * ne00_blk * ne01 * 16 + i00 * ne01 * 16 + i01; 1459 uint qhv[16]; 1460 for (int p = 0; p < 16; ++p) { 1461 qhv[p] = src_qh[qh_base + p * ne01]; 1462 } 1463 1464 for (int n = 0; n < 2; ++n) { 1465 for (int l = 0; l < 32; ++l) { 1466 int u = l / 16; 1467 int bit_pos = (l % 16) * 2; 1468 uchar v0 = (uchar)((qhv[(n*4 + 0)*2 + u] >> bit_pos) & 0x03); 1469 uchar v1 = (uchar)((qhv[(n*4 + 1)*2 + u] >> bit_pos) & 0x03); 1470 uchar v2 = (uchar)((qhv[(n*4 + 2)*2 + u] >> bit_pos) & 0x03); 1471 uchar v3 = (uchar)((qhv[(n*4 + 3)*2 + u] >> bit_pos) & 0x03); 1472 b->qh[n*32 + l] = v0 | (v1 << 2) | (v2 << 4) | (v3 << 6); 1473 } 1474 } 1475 1476 __global char * s_src = src_s + (i02 * ne01 + i01) * ne00_blk * 16 + i00 * 16; 1477 for (int i = 0; i < 16; ++i) { 1478 b->scales[i] = s_src[i]; 1479 } 1480} 1481 1482//------------------------------------------------------------------------------ 1483// block_mxfp4 1484//------------------------------------------------------------------------------ 1485#define QK_MXFP4 32 1486struct block_mxfp4 { 1487 uchar e; // E8M0 1488 uchar qs[QK_MXFP4 / 2]; 1489}; 1490 1491//------------------------------------------------------------------------------ 1492// kernel_convert_block_mxfp4 1493// Convert the block_mxfp4 format to 2 separate arrays (AOS -> SOA). 1494// This kernel does not deshuffle the bits. 1495//------------------------------------------------------------------------------ 1496kernel void kernel_convert_block_mxfp4( 1497 global struct block_mxfp4 * src0, 1498 global uchar * dst_q, 1499 global uchar * dst_e 1500) { 1501 global struct block_mxfp4 * b = (global struct block_mxfp4 *) src0 + get_global_id(0); 1502 global uchar * q = (global uchar *) dst_q + QK_MXFP4 / 2 * get_global_id(0); 1503 global uchar * e = (global uchar *) dst_e + get_global_id(0); 1504 1505 *e = b->e; 1506 1507 for (int i = 0; i < QK_MXFP4 / 2; ++i) { 1508 q[i] = b->qs[i]; 1509 } 1510} 1511 1512kernel void kernel_convert_block_mxfp4_trans( 1513 global struct block_mxfp4 * src0, 1514 __global uint4 * dst_q, 1515 __global uchar * dst_e, 1516 uint ne00, 1517 uint ne01 1518) { 1519 int i00 = get_global_id(1); 1520 uint i01 = get_global_id(0); 1521 uint i02 = get_global_id(2); 1522 1523 uint ne00_blk = ne00 / QK_MXFP4; 1524 uint src_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1525 uint dst_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 1526 1527 global struct block_mxfp4 * b = src0 + src_blk_offset; 1528 1529 dst_q[dst_blk_offset] = ((global uint4 *)(&(b->qs[0])))[0]; 1530 dst_e[dst_blk_offset] = b->e; 1531} 1532 1533kernel void kernel_restore_block_mxfp4( 1534 global uchar * src_q, 1535 global half * src_e, 1536 global struct block_mxfp4 * dst 1537) { 1538 global struct block_mxfp4 * b = (global struct block_mxfp4 *) dst + get_global_id(0); 1539 global uchar * q = (global uchar *) src_q + QK_MXFP4 / 2 * get_global_id(0); 1540 global uchar * e = (global uchar *) src_e + get_global_id(0); 1541 1542 b->e = *e; 1543 for (int i = 0; i < QK_MXFP4 / 2; ++i) { 1544 b->qs[i] = q[i]; 1545 } 1546} 1547 1548kernel void kernel_restore_block_mxfp4_trans( 1549 __global uint4 * src_q, 1550 __global uchar * src_e, 1551 global struct block_mxfp4 * dst, 1552 uint ne00, 1553 uint ne01 1554) { 1555 int i00 = get_global_id(1); 1556 uint i01 = get_global_id(0); 1557 uint i02 = get_global_id(2); 1558 1559 uint ne00_blk = ne00 / QK_MXFP4; 1560 uint src_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 1561 uint dst_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1562 1563 global struct block_mxfp4 * b = dst + dst_blk_offset; 1564 1565 ((global uint4 *)(&(b->qs[0])))[0] = src_q[src_blk_offset]; 1566 b->e = src_e[src_blk_offset]; 1567} 1568 1569//------------------------------------------------------------------------------ 1570// kernel_convert_block_q6_k_tiled_ns 1571// 1572// Tiled-wide layout for the long-vocab q6_K lm_head/embed GEMV (decode path). 1573// Unlike *_trans4_ns (which mirrors the bit-interleave the legacy 2-output GEMV 1574// consumes), this kernel is correct-by-construction against the CANONICAL ggml 1575// q6_K dequant: it recovers each weight's 6-bit code in element order e in 1576// [0,256), then re-packs low-4-bits into 32 uints (8 codes/uint) and high-2-bits 1577// into 16 uints (16 codes/uint). The matching GEMV (gemv_noshuffle_q6_k_f32_tiled) 1578// unpacks the same order, so both ends are owned here. 1579// 1580// Storage is TILED by 64 output rows so the GEMV's 64-thread tile coalesces: 1581// ql uint4 granule g of (row r, K-block sb): idx = ((rt*ne00_blk + sb)*8 + g)*64 + rit 1582// qh uint4 granule g: idx = ((rt*ne00_blk + sb)*4 + g)*64 + rit 1583// scales (char16) of (r, sb): idx = (rt*ne00_blk + sb)*64 + rit 1584// d (half) of (r, sb): idx = (rt*ne00_blk + sb)*64 + rit 1585// where rt = r/64, rit = r%64. Requires ne01 % 64 == 0 (gated host-side). 1586// Buffer sizes are byte-identical to the trans4_ns layout. 1587//------------------------------------------------------------------------------ 1588kernel void kernel_convert_block_q6_k_tiled_ns( 1589 __global struct block_q6_K * src0, 1590 __global uint * dst_ql, // 32 uints / superblock (low 4 bits, 8 codes/uint) 1591 __global uint * dst_qh, // 16 uints / superblock (high 2 bits, 16 codes/uint) 1592 __global half * dst_d, // 1 half / superblock 1593 __global char * dst_s, // 16 chars/ superblock 1594 uint ne00, 1595 uint ne01 1596) { 1597 uint i00 = get_global_id(1); // K-block index (superblock along ne00) 1598 uint i01 = get_global_id(0); // output row index (along ne01) 1599 uint i02 = get_global_id(2); // batch 1600 1601 uint ne00_blk = ne00 / QK_K; 1602 1603 // Source block: row-major over (i02, i01, i00). 1604 uint src_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1605 __global struct block_q6_K * b = src0 + src_blk_offset; 1606 1607 uint rt = i01 / 64; 1608 uint rit = i01 % 64; 1609 uint tile_blk = (i02 * (ne01 / 64) + rt) * ne00_blk + i00; // tile-major (row-tile, K-block) 1610 1611 // --- recover canonical 6-bit codes, pack into ql (4b) + qh (2b) in e-order --- 1612 // 32 ql-uints (8 low-nibbles each) + 16 qh-uints (16 2-bit slots each). 1613 uint qlw[32] = {0}; 1614 uint qhw[16] = {0}; 1615 1616 for (uint e = 0; e < 256; ++e) { 1617 uint n = (e >= 128) ? 1u : 0u; // which 128-half 1618 uint within = e - n * 128u; 1619 uint q = within / 32u; // quadrant 0..3 1620 uint l = within % 32u; // 0..31 1621 1622 uint off_ql = n * 64u; // raw ql byte base for this half 1623 uint off_qh = n * 32u; // raw qh byte base for this half 1624 1625 uchar low4; 1626 uchar qlb0 = b->ql[off_ql + l]; 1627 uchar qlb1 = b->ql[off_ql + l + 32]; 1628 if (q == 0) low4 = qlb0 & 0x0F; 1629 else if (q == 1) low4 = qlb1 & 0x0F; 1630 else if (q == 2) low4 = (qlb0 >> 4) & 0x0F; 1631 else low4 = (qlb1 >> 4) & 0x0F; 1632 1633 uchar hi2 = (b->qh[off_qh + l] >> (q * 2u)) & 0x03; 1634 1635 // pack low4 (e-order): uint e/8, nibble (e%8) 1636 qlw[e >> 3] |= ((uint)low4) << ((e & 7u) * 4u); 1637 // pack hi2 (e-order): uint e/16, 2-bit slot (e%16) 1638 qhw[e >> 4] |= ((uint)hi2) << ((e & 15u) * 2u); 1639 } 1640 1641 // --- write tiled --- 1642 for (uint g = 0; g < 8; ++g) { 1643 uint base = (tile_blk * 8u + g) * 64u + rit; // uint4 index 1644 dst_ql[base * 4u + 0u] = qlw[g * 4u + 0u]; 1645 dst_ql[base * 4u + 1u] = qlw[g * 4u + 1u]; 1646 dst_ql[base * 4u + 2u] = qlw[g * 4u + 2u]; 1647 dst_ql[base * 4u + 3u] = qlw[g * 4u + 3u]; 1648 } 1649 for (uint g = 0; g < 4; ++g) { 1650 uint base = (tile_blk * 4u + g) * 64u + rit; // uint4 index 1651 dst_qh[base * 4u + 0u] = qhw[g * 4u + 0u]; 1652 dst_qh[base * 4u + 1u] = qhw[g * 4u + 1u]; 1653 dst_qh[base * 4u + 2u] = qhw[g * 4u + 2u]; 1654 dst_qh[base * 4u + 3u] = qhw[g * 4u + 3u]; 1655 } 1656 1657 // scales: 16 chars contiguous per (row, block), tiled 1658 __global char * s_dst = dst_s + (tile_blk * 64u + rit) * 16u; 1659 #pragma unroll 1660 for (int i = 0; i < 16; ++i) { 1661 s_dst[i] = b->scales[i]; 1662 } 1663 1664 // super-block scale 1665 dst_d[tile_blk * 64u + rit] = b->d; 1666} 1667 1668kernel void kernel_convert_block_mxfp4_trans4_ns( 1669 global struct block_mxfp4 * src0, 1670 __global uint * dst_q, 1671 __global uchar * dst_e, 1672 uint ne00, 1673 uint ne01 1674) { 1675 uint i00 = get_global_id(1); 1676 uint i01 = get_global_id(0); 1677 uint i02 = get_global_id(2); 1678 1679 if (i01 >= ne01) { 1680 return; 1681 } 1682 1683 uint ne00_blk = ne00 / QK_MXFP4; 1684 uint src_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1685 uint dst_blk_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 1686 1687 global struct block_mxfp4 * b = src0 + src_blk_offset; 1688 dst_e[dst_blk_offset] = b->e; 1689 1690 // extract quantization and unshuffle 1691 ushort8 pre_block = ((global ushort8 *)(&(b->qs[0])))[0]; 1692 1693 ushort8 post_block = (ushort8)(0); 1694 1695 uchar * pre_block_ptr = (uchar *)(&pre_block); 1696 uchar * post_block_ptr = (uchar *)(&post_block); 1697 1698 for (int i = 0; i < QK_MXFP4 / 4; ++i) { 1699 uchar x0 = pre_block_ptr[2*i + 0]; 1700 uchar x1 = pre_block_ptr[2*i + 1]; 1701 1702 post_block_ptr[i + 0 ] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 1703 post_block_ptr[i + QK_MXFP4 / 4] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 1704 } 1705 1706 uint4 q_block = as_uint4(post_block); 1707 1708 uint offset = i02 * ne00_blk * ne01 * 4 + i00 * ne01 * 4 + i01; 1709 dst_q[offset] = q_block.x; 1710 dst_q[offset + ne01] = q_block.y; 1711 dst_q[offset + ne01 * 2] = q_block.z; 1712 dst_q[offset + ne01 * 3] = q_block.w; 1713} 1714 1715kernel void kernel_restore_block_mxfp4_trans4_ns( 1716 __global uint * src_q, 1717 __global uchar * src_e, 1718 __global struct block_mxfp4 * dst0, 1719 uint ne00, 1720 uint ne01 1721) { 1722 uint i00 = get_global_id(1); 1723 uint i01 = get_global_id(0); 1724 uint i02 = get_global_id(2); 1725 1726 if (i01 >= ne01) { 1727 return; 1728 } 1729 1730 uint ne00_blk = ne00 / QK_MXFP4; 1731 uint dst_blk_offset = i00 + i01 * ne00_blk + i02 * ne00_blk * ne01; 1732 uint src_d_offset = i01 + i00 * ne01 + i02 * ne00_blk * ne01; 1733 1734 __global struct block_mxfp4 * b = dst0 + dst_blk_offset; 1735 b->e = src_e[src_d_offset]; 1736 1737 // collect transposed quantization parts for a block 1738 uint src_q_offset = i02 * ne00_blk * ne01 * 4 + i00 * ne01 * 4 + i01; 1739 uint4 q_block; 1740 q_block.x = src_q[src_q_offset]; 1741 q_block.y = src_q[src_q_offset + ne01]; 1742 q_block.z = src_q[src_q_offset + ne01 * 2]; 1743 q_block.w = src_q[src_q_offset + ne01 * 3]; 1744 1745 ushort8 post_block = as_ushort8(q_block); 1746 ushort8 pre_block = (ushort8)(0); 1747 1748 uchar * pre_block_ptr = (uchar *)(&pre_block); 1749 uchar * post_block_ptr = (uchar *)(&post_block); 1750 1751 for (int i = 0; i < QK_MXFP4 / 4; ++i) { 1752 uchar x0 = post_block_ptr[i + 0]; 1753 uchar x1 = post_block_ptr[i + QK_MXFP4 / 4]; 1754 1755 pre_block_ptr[2 * i + 0] = convert_uchar(x0 & 0x0F) | convert_uchar((x1 & 0x0F) << 4); 1756 pre_block_ptr[2 * i + 1] = convert_uchar((x0 & 0xF0) >> 4) | convert_uchar(x1 & 0xF0); 1757 } 1758 1759 ((__global ushort8 *)(&(b->qs[0])))[0] = pre_block; 1760} 1761 1762 1763//------------------------------------------------------------------------------ 1764// block_q8_0 1765//------------------------------------------------------------------------------ 1766typedef struct { 1767 half d; // delta 1768 char qs[QK8_0]; // quants 1769} block_q8_0; 1770 1771kernel void kernel_convert_block_q8_0( 1772 global block_q8_0 * src0, 1773 global uchar * dst_q, 1774 global half * dst_d 1775) { 1776 global block_q8_0 * b = (global block_q8_0 *) src0 + get_global_id(0); 1777 global uchar * q = (global uchar *) dst_q + QK8_0*get_global_id(0); 1778 global half * d = (global half *) dst_d + get_global_id(0); 1779 1780 *d = b->d; 1781 1782 for (int i = 0; i < QK8_0; ++i) { 1783 q[i] = b->qs[i]; 1784 } 1785} 1786 1787kernel void kernel_restore_block_q8_0( 1788 global uchar * src_q, 1789 global half * src_d, 1790 global block_q8_0 * dst 1791) { 1792 global block_q8_0 * b = (global block_q8_0 *) dst + get_global_id(0); 1793 global uchar * q = (global uchar *) src_q + QK8_0*get_global_id(0); 1794 global half * d = (global half *) src_d + get_global_id(0); 1795 1796 b->d = *d; 1797 for (int i = 0; i < QK8_0; ++i) { 1798 b->qs[i] = q[i]; 1799 } 1800} 1801 1802// View-aware AoS q8_0 -> f32 dequant (f32/f32 FA path). 1803kernel void kernel_dequant_q8_0_f32_view_aos( 1804 global char * src, 1805 ulong src_offset, 1806 ulong src_nb1, 1807 ulong src_nb2, 1808 ulong src_nb3, 1809 int nblk0, 1810 int ne1, 1811 int ne2, 1812 int ne3, 1813 global float * dst 1814) { 1815 int blk_i0 = get_global_id(0); 1816 int i1 = get_global_id(1); 1817 int batch = get_global_id(2); 1818 1819 if (blk_i0 >= nblk0) return; 1820 if (i1 >= ne1) return; 1821 1822 int i2 = batch % ne2; 1823 int i3 = batch / ne2; 1824 if (i3 >= ne3) return; 1825 1826 global char * block = src + src_offset + (ulong)i3*src_nb3 + (ulong)i2*src_nb2 + (ulong)i1*src_nb1 + (ulong)blk_i0 * (2 + QK8_0); 1827 float d = vload_half(0, (global half *)block); 1828 global char * qs = block + 2; 1829 1830 ulong dst_row_base = ((ulong)i3 * ne2 * ne1 + (ulong)i2 * ne1 + (ulong)i1) * nblk0; 1831 global float * out = dst + (dst_row_base + blk_i0) * QK8_0; 1832 1833 for (int i = 0; i < QK8_0; ++i) { 1834 out[i] = d * (float)qs[i]; 1835 } 1836} 1837 1838// View-aware AoS q8_0 -> f16 dequant. Rows tight, batch strides may be gapped. 1839kernel void kernel_dequant_q8_0_f16_view_aos( 1840 global char * src, 1841 ulong src_offset, 1842 ulong src_nb1, 1843 ulong src_nb2, 1844 ulong src_nb3, 1845 int nblk0, 1846 int ne1, 1847 int ne2, 1848 int ne3, 1849 global half * dst 1850) { 1851 int blk_i0 = get_global_id(0); 1852 int i1 = get_global_id(1); 1853 int batch = get_global_id(2); 1854 1855 if (blk_i0 >= nblk0) return; 1856 if (i1 >= ne1) return; 1857 1858 int i2 = batch % ne2; 1859 int i3 = batch / ne2; 1860 if (i3 >= ne3) return; 1861 1862 global char * block = src + src_offset + (ulong)i3*src_nb3 + (ulong)i2*src_nb2 + (ulong)i1*src_nb1 + (ulong)blk_i0 * (2 + QK8_0); 1863 float d = vload_half(0, (global half *)block); 1864 global char * qs = block + 2; 1865 1866 ulong dst_row_base = ((ulong)i3 * ne2 * ne1 + (ulong)i2 * ne1 + (ulong)i1) * nblk0; 1867 global half * out = dst + (dst_row_base + blk_i0) * QK8_0; 1868 1869 for (int i = 0; i < QK8_0; ++i) { 1870 out[i] = (half)(d * (float)qs[i]); 1871 } 1872} 1873 1874// View-aware AoS q4_0 -> f32 dequant (mirrors the q8_0 view variant). 1875kernel void kernel_dequant_q4_0_f32_view_aos( 1876 global char * src, 1877 ulong src_offset, 1878 ulong src_nb1, 1879 ulong src_nb2, 1880 ulong src_nb3, 1881 int nblk0, 1882 int ne1, 1883 int ne2, 1884 int ne3, 1885 global float * dst 1886) { 1887 int blk_i0 = get_global_id(0); 1888 int i1 = get_global_id(1); 1889 int batch = get_global_id(2); 1890 1891 if (blk_i0 >= nblk0) return; 1892 if (i1 >= ne1) return; 1893 1894 int i2 = batch % ne2; 1895 int i3 = batch / ne2; 1896 if (i3 >= ne3) return; 1897 1898 global char * block = src + src_offset + (ulong)i3*src_nb3 + (ulong)i2*src_nb2 + (ulong)i1*src_nb1 + (ulong)blk_i0 * (2 + QK4_0/2); 1899 float d = vload_half(0, (global half *)block); 1900 global uchar * qs = (global uchar *)(block + 2); 1901 1902 ulong dst_row_base = ((ulong)i3 * ne2 * ne1 + (ulong)i2 * ne1 + (ulong)i1) * nblk0; 1903 global float * out = dst + (dst_row_base + blk_i0) * QK4_0; 1904 1905 for (int i = 0; i < QK4_0/2; ++i) { 1906 uchar byte = qs[i]; 1907 int q0 = (int)(byte & 0x0F) - 8; 1908 int q1 = (int)(byte >> 4) - 8; 1909 out[i] = d * (float)q0; 1910 out[i + QK4_0/2] = d * (float)q1; 1911 } 1912} 1913 1914// View-aware AoS q4_0 -> f16 dequant (mirrors the q8_0 view variant). 1915kernel void kernel_dequant_q4_0_f16_view_aos( 1916 global char * src, 1917 ulong src_offset, 1918 ulong src_nb1, 1919 ulong src_nb2, 1920 ulong src_nb3, 1921 int nblk0, 1922 int ne1, 1923 int ne2, 1924 int ne3, 1925 global half * dst 1926) { 1927 int blk_i0 = get_global_id(0); 1928 int i1 = get_global_id(1); 1929 int batch = get_global_id(2); 1930 1931 if (blk_i0 >= nblk0) return; 1932 if (i1 >= ne1) return; 1933 1934 int i2 = batch % ne2; 1935 int i3 = batch / ne2; 1936 if (i3 >= ne3) return; 1937 1938 global char * block = src + src_offset + (ulong)i3*src_nb3 + (ulong)i2*src_nb2 + (ulong)i1*src_nb1 + (ulong)blk_i0 * (2 + QK4_0/2); 1939 float d = vload_half(0, (global half *)block); 1940 global uchar * qs = (global uchar *)(block + 2); 1941 1942 ulong dst_row_base = ((ulong)i3 * ne2 * ne1 + (ulong)i2 * ne1 + (ulong)i1) * nblk0; 1943 global half * out = dst + (dst_row_base + blk_i0) * QK4_0; 1944 1945 for (int i = 0; i < QK4_0/2; ++i) { 1946 uchar byte = qs[i]; 1947 int q0 = (int)(byte & 0x0F) - 8; 1948 int q1 = (int)(byte >> 4) - 8; 1949 out[i] = (half)(d * (float)q0); 1950 out[i + QK4_0/2] = (half)(d * (float)q1); 1951 } 1952} 1953 1954kernel void kernel_restore_block_q8_0_trans( 1955 global uchar * src_q, 1956 global half * src_d, 1957 global block_q8_0 * dst, 1958 uint ne00, 1959 uint ne01 1960){ 1961 uint num_blk_per_row = ne00 / QK8_0; 1962 1963 global block_q8_0 * b = (global block_q8_0 *) dst + get_global_id(0) * num_blk_per_row; 1964 global uchar * q = (global uchar *) src_q + get_global_id(0) * 4; // 4 8-bit packed 1965 global half * d = (global half *) src_d + get_global_id(0); 1966 1967 for (uint blk = 0; blk < num_blk_per_row; blk++) { 1968 b->d = *d; 1969 1970 for (uint i = 0; i < QK8_0; i+=4) { 1971 b->qs[i] = q[0]; 1972 b->qs[i+1] = q[1]; 1973 b->qs[i+2] = q[2]; 1974 b->qs[i+3] = q[3]; 1975 1976 q += 4 * ne01; // M stride 1977 } 1978 1979 d += ne01; 1980 1981 b++; 1982 } 1983} 1984 1985//------------------------------------------------------------------------------ 1986// kernel_convert_block_q4_K 1987// Convert the block_q4_K format to 4 separate arrays (AOS -> SOA). 1988// This kernel does not deshuffle the bits. 1989// Each thread processes a super block. 1990// Mask args are just to keep the signature consistent with the no-shuffle 1991// version and they are not used in this kernel. 1992//------------------------------------------------------------------------------ 1993kernel void kernel_convert_block_q4_K( 1994 global struct block_q4_K * src0, 1995 global uchar * dst_q, 1996 global uchar * dst_s, 1997 global half * dst_d, 1998 global half * dst_dm, 1999 uchar mask_0F, 2000 uchar mask_F0 2001) { 2002 global struct block_q4_K * b = (global struct block_q4_K *) src0 + get_global_id(0); 2003 global uchar * q = (global uchar *) dst_q + QK_K/2*get_global_id(0); 2004 global uchar * s = (global uchar *) dst_s + K_SCALE_SIZE*get_global_id(0); 2005 global half * d = (global half *) dst_d + get_global_id(0); 2006 global half * dm = (global half *) dst_dm + get_global_id(0); 2007 2008 *d = b->d; 2009 *dm = b->dm; 2010 2011 for (int i = 0; i < QK_K/2; ++i) { 2012 q[i] = b->q[i]; 2013 } 2014 for (int i = 0; i < K_SCALE_SIZE; ++i) { 2015 s[i] = b->s[i]; 2016 } 2017} 2018 2019// Restore block_q4_K from flattened arrays. 2020// Each thread processes a super block. 2021// Mask args are just to keep the signature consistent with the no-shuffle ones. 2022kernel void kernel_restore_block_q4_K( 2023 global uchar * src_q, 2024 global uchar * src_s, 2025 global half * src_d, 2026 global half * src_dm, 2027 global struct block_q4_K * dst, 2028 uchar mask_0F, 2029 uchar mask_F0 2030) { 2031 global struct block_q4_K * b = (global struct block_q4_K *) dst + get_global_id(0); 2032 global uchar * q = (global uchar *) src_q + QK_K/2*get_global_id(0); 2033 global uchar * s = (global uchar *) src_s + K_SCALE_SIZE*get_global_id(0); 2034 global half * d = (global half *) src_d + get_global_id(0); 2035 global half * dm = (global half *) src_dm + get_global_id(0); 2036 2037 b->d = *d; 2038 b->dm = *dm; 2039 2040 for (int i = 0; i < QK_K/2; ++i) { 2041 b->q[i] = q[i]; 2042 } 2043 for (int i = 0; i < K_SCALE_SIZE; ++i) { 2044 b->s[i] = s[i]; 2045 } 2046} 2047 2048kernel void kernel_convert_block_q4_K_noshuffle( 2049 global struct block_q4_K * src0, 2050 global uchar * dst_q, 2051 global uchar * dst_s, 2052 global half * dst_d, 2053 global half * dst_dm, 2054 uchar mask_0F, 2055 uchar mask_F0 2056) { 2057 global struct block_q4_K * b = (global struct block_q4_K *) src0 + get_global_id(0); 2058 global uchar * q = (global uchar *) dst_q + QK_K/2 * get_global_id(0); 2059 global uchar * s = (global uchar *) dst_s + K_SCALE_SIZE * get_global_id(0); 2060 global half * d = (global half *) dst_d + get_global_id(0); 2061 global half * dm = (global half *) dst_dm + get_global_id(0); 2062 2063 *d = b->d; 2064 *dm = b->dm; 2065 2066 for (int i = 0; i < QK_K / 64; ++i) { 2067 for (int j = 0; j < 16; ++j) { 2068 uchar x0 = b->q[i*32 + 2*j]; 2069 uchar x1 = b->q[i*32 + 2*j + 1]; 2070 q[i*32 + j] = convert_uchar(x0 & mask_0F) | convert_uchar((x1 & mask_0F) << 4); 2071 q[i*32 + j + 16] = convert_uchar((x0 & mask_F0) >> 4) | convert_uchar(x1 & mask_F0); 2072 } 2073 } 2074 2075 for (int i = 0; i < K_SCALE_SIZE; ++i) { 2076 s[i] = b->s[i]; 2077 } 2078} 2079 2080kernel void kernel_restore_block_q4_K_noshuffle( 2081 global uchar * src_q, 2082 global uchar * src_s, 2083 global half * src_d, 2084 global half * src_dm, 2085 global struct block_q4_K * dst, 2086 uchar mask_0F, 2087 uchar mask_F0 2088) { 2089 global struct block_q4_K * b = (global struct block_q4_K *) dst + get_global_id(0); 2090 global uchar * q = (global uchar *) src_q + QK_K/2 * get_global_id(0); 2091 global uchar * s = (global uchar *) src_s + K_SCALE_SIZE * get_global_id(0); 2092 global half * d = (global half *) src_d + get_global_id(0); 2093 global half * dm = (global half *) src_dm + get_global_id(0); 2094 2095 b->d = *d; 2096 b->dm = *dm; 2097 2098 for (int i = 0; i < QK_K / 64; ++i) { 2099 for (int j = 0; j < 16; ++j) { 2100 uchar lo = q[i*32 + j]; 2101 uchar hi = q[i*32 + j + 16]; 2102 b->q[i*32 + 2*j] = convert_uchar((lo & mask_0F) | ((hi & mask_0F) << 4)); 2103 b->q[i*32 + 2*j + 1] = convert_uchar(((lo & mask_F0) >> 4) | (hi & mask_F0)); 2104 } 2105 } 2106 2107 for (int i = 0; i < K_SCALE_SIZE; ++i) { 2108 b->s[i] = s[i]; 2109 } 2110} 2111 2112//------------------------------------------------------------------------------ 2113// kernel_convert_block_q5_K 2114// Convert the block_q5_K format to 5 separate arrays (AOS -> SOA). 2115// Each thread processes a super block. 2116//------------------------------------------------------------------------------ 2117kernel void kernel_convert_block_q5_K( 2118 global struct block_q5_K * src0, 2119 global uchar * dst_q, 2120 global uchar * dst_qh, 2121 global uchar * dst_s, 2122 global half * dst_d, 2123 global half * dst_dm, 2124 uchar mask_0F, 2125 uchar mask_F0 2126) { 2127 global struct block_q5_K * b = (global struct block_q5_K *) src0 + get_global_id(0); 2128 global uchar * q = (global uchar *) dst_q + QK_K/2*get_global_id(0); 2129 global uchar * qh = (global uchar *) dst_qh + QK_K/8*get_global_id(0); 2130 global uchar * s = (global uchar *) dst_s + K_SCALE_SIZE*get_global_id(0); 2131 global half * d = (global half *) dst_d + get_global_id(0); 2132 global half * dm = (global half *) dst_dm + get_global_id(0); 2133 2134 *d = b->d; 2135 *dm = b->dm; 2136 2137 for (int i = 0; i < QK_K/2; ++i) { 2138 q[i] = b->qs[i]; 2139 } 2140 for (int i = 0; i < QK_K/8; ++i) { 2141 qh[i] = b->qh[i]; 2142 } 2143 for (int i = 0; i < K_SCALE_SIZE; ++i) { 2144 s[i] = b->s[i]; 2145 } 2146} 2147 2148// Restore block_q5_K from flattened arrays. 2149// Each thread processes a super block. 2150kernel void kernel_restore_block_q5_K( 2151 global uchar * src_q, 2152 global uchar * src_qh, 2153 global uchar * src_s, 2154 global half * src_d, 2155 global half * src_dm, 2156 global struct block_q5_K * dst, 2157 uchar mask_0F, 2158 uchar mask_F0 2159) { 2160 global struct block_q5_K * b = (global struct block_q5_K *) dst + get_global_id(0); 2161 global uchar * q = (global uchar *) src_q + QK_K/2*get_global_id(0); 2162 global uchar * qh = (global uchar *) src_qh + QK_K/8*get_global_id(0); 2163 global uchar * s = (global uchar *) src_s + K_SCALE_SIZE*get_global_id(0); 2164 global half * d = (global half *) src_d + get_global_id(0); 2165 global half * dm = (global half *) src_dm + get_global_id(0); 2166 2167 b->d = *d; 2168 b->dm = *dm; 2169 2170 for (int i = 0; i < QK_K/2; ++i) { 2171 b->qs[i] = q[i]; 2172 } 2173 for (int i = 0; i < QK_K/8; ++i) { 2174 b->qh[i] = qh[i]; 2175 } 2176 for (int i = 0; i < K_SCALE_SIZE; ++i) { 2177 b->s[i] = s[i]; 2178 } 2179} 2180 2181kernel void kernel_convert_block_q5_K_noshuffle( 2182 global struct block_q5_K * src0, 2183 global uchar * dst_q, 2184 global uchar * dst_qh, 2185 global uchar * dst_s, 2186 global half * dst_d, 2187 global half * dst_dm, 2188 uchar mask_0F, 2189 uchar mask_F0 2190) { 2191 global struct block_q5_K * b = (global struct block_q5_K *) src0 + get_global_id(0); 2192 global uchar * q = (global uchar *) dst_q + QK_K/2 * get_global_id(0); 2193 global uchar * qh = (global uchar *) dst_qh + QK_K/8 * get_global_id(0); 2194 global uchar * s = (global uchar *) dst_s + K_SCALE_SIZE * get_global_id(0); 2195 global half * d = (global half *) dst_d + get_global_id(0); 2196 global half * dm = (global half *) dst_dm + get_global_id(0); 2197 2198 *d = b->d; 2199 *dm = b->dm; 2200 2201 for (int i = 0; i < QK_K / 64; ++i) { 2202 for (int j = 0; j < 16; ++j) { 2203 uchar x0 = b->qs[i*32 + 2*j]; 2204 uchar x1 = b->qs[i*32 + 2*j + 1]; 2205 q[i*32 + j] = convert_uchar(x0 & mask_0F) | convert_uchar((x1 & mask_0F) << 4); 2206 q[i*32 + j + 16] = convert_uchar((x0 & mask_F0) >> 4) | convert_uchar(x1 & mask_F0); 2207 } 2208 } 2209 2210 for (int l = 0; l < QK_K/8; ++l) { 2211 uchar x0 = 0; 2212 for (int i = 0; i < 8; ++i) { 2213 x0 |= ((b->qh[(l%4)*8+i] >> (l/4)) & 0x01) << i; 2214 } 2215 qh[l] = x0; 2216 } 2217 2218 for (int i = 0; i < K_SCALE_SIZE; ++i) { 2219 s[i] = b->s[i]; 2220 } 2221} 2222 2223kernel void kernel_restore_block_q5_K_noshuffle( 2224 global uchar * src_q, 2225 global uchar * src_qh, 2226 global uchar * src_s, 2227 global half * src_d, 2228 global half * src_dm, 2229 global struct block_q5_K * dst, 2230 uchar mask_0F, 2231 uchar mask_F0 2232) { 2233 global struct block_q5_K * b = (global struct block_q5_K *) dst + get_global_id(0); 2234 global uchar * q = (global uchar *) src_q + QK_K/2 * get_global_id(0); 2235 global uchar * qh = (global uchar *) src_qh + QK_K/8 * get_global_id(0); 2236 global uchar * s = (global uchar *) src_s + K_SCALE_SIZE * get_global_id(0); 2237 global half * d = (global half *) src_d + get_global_id(0); 2238 global half * dm = (global half *) src_dm + get_global_id(0); 2239 2240 b->d = *d; 2241 b->dm = *dm; 2242 2243 for (int i = 0; i < QK_K / 64; ++i) { 2244 for (int j = 0; j < 16; ++j) { 2245 uchar lo = q[i*32 + j]; 2246 uchar hi = q[i*32 + j + 16]; 2247 b->qs[i*32 + 2*j] = convert_uchar((lo & mask_0F) | ((hi & mask_0F) << 4)); 2248 b->qs[i*32 + 2*j + 1] = convert_uchar(((lo & mask_F0) >> 4) | (hi & mask_F0)); 2249 } 2250 } 2251 2252 for (int g = 0; g < 4; ++g) { 2253 for (int i = 0; i < 8; ++i) { 2254 uchar x0 = 0; 2255 for (int k = 0; k < 8; ++k) { 2256 x0 |= ((qh[4*k+g] >> i) & 0x01) << k; 2257 } 2258 b->qh[g*8+i] = x0; 2259 } 2260 } 2261 2262 for (int i = 0; i < K_SCALE_SIZE; ++i) { 2263 b->s[i] = s[i]; 2264 } 2265} 2266 2267//------------------------------------------------------------------------------ 2268// kernel_convert_block_q6_K 2269// Convert the block_q6_K format to 3 separate arrays (AOS -> SOA). 2270// This kernel does not deshuffle the bits. 2271// Each thread processes a super block. 2272//------------------------------------------------------------------------------ 2273kernel void kernel_convert_block_q6_K( 2274 global struct block_q6_K * src0, 2275 global uchar * dst_ql, 2276 global uchar * dst_qh, 2277 global char * dst_s, 2278 global half * dst_d, 2279 uchar mask_lsb_8, 2280 ulong n_blk 2281) { 2282 if (get_global_id(0) >= n_blk) { 2283 return; 2284 } 2285 global struct block_q6_K * b = (global struct block_q6_K *) src0 + get_global_id(0); 2286 global uchar * ql = (global uchar *) dst_ql + QK_K/2*get_global_id(0); 2287 global uchar * qh = (global uchar *) dst_qh + QK_K/4*get_global_id(0); 2288 global char * s = (global char *) dst_s + QK_K/16*get_global_id(0); 2289 global half * d = (global half *) dst_d + get_global_id(0); 2290 2291 *d = b->d; 2292 2293 for (int i = 0; i < QK_K/2; ++i) { 2294 ql[i] = b->ql[i]; 2295 } 2296 for (int i = 0; i < QK_K/4; ++i) { 2297 qh[i] = b->qh[i]; 2298 } 2299 for (int i = 0; i < QK_K/16; ++i) { 2300 s[i] = b->scales[i]; 2301 } 2302} 2303 2304// Restore block_q6_K from flattened arrays. 2305// Each thread processes a super block. 2306kernel void kernel_restore_block_q6_K( 2307 global uchar * dst_ql, 2308 global uchar * dst_qh, 2309 global char * dst_s, 2310 global half * dst_d, 2311 global struct block_q6_K * dst, 2312 uchar mask_lsb_8, 2313 ulong n_blk 2314) { 2315 if (get_global_id(0) >= n_blk) { 2316 return; 2317 } 2318 global struct block_q6_K * b = (global struct block_q6_K *) dst + get_global_id(0); 2319 global uchar * ql = (global uchar *) dst_ql + QK_K/2*get_global_id(0); 2320 global uchar * qh = (global uchar *) dst_qh + QK_K/4*get_global_id(0); 2321 global char * s = (global char *) dst_s + QK_K/16*get_global_id(0); 2322 global half * d = (global half *) dst_d + get_global_id(0); 2323 2324 b->d = *d; 2325 2326 for (int i = 0; i < QK_K/2; ++i) { 2327 b->ql[i] = ql[i]; 2328 } 2329 for (int i = 0; i < QK_K/4; ++i) { 2330 b->qh[i] = qh[i]; 2331 } 2332 for (int i = 0; i < QK_K/16; ++i) { 2333 b->scales[i] = s[i]; 2334 } 2335} 2336 2337kernel void kernel_convert_block_q6_K_noshuffle( 2338 global struct block_q6_K * src0, 2339 global uchar * dst_ql, 2340 global uchar * dst_qh, 2341 global char * dst_s, 2342 global half * dst_d, 2343 uchar mask_lsb_8, 2344 ulong n_blk 2345) { 2346 if (get_global_id(0) >= n_blk) { 2347 return; 2348 } 2349 global struct block_q6_K * b = (global struct block_q6_K *) src0 + get_global_id(0); 2350 global uchar * ql = (global uchar *) dst_ql + QK_K/2*get_global_id(0); 2351 global uchar * qh = (global uchar *) dst_qh + QK_K/4*get_global_id(0); 2352 global char * s = (global char *) dst_s + QK_K/16*get_global_id(0); 2353 global half * d = (global half *) dst_d + get_global_id(0); 2354 2355 *d = b->d; 2356 2357 for (int i = 0; i < QK_K/2/4; ++i) { 2358 uchar x0 = b->ql[i*2 + 0] & mask_lsb_8; 2359 uchar x1 = b->ql[i*2 + 1] & mask_lsb_8; 2360 ql[i + 0] = (x0 & 0x0F) | ((x1 & 0x0F) << 4); 2361 ql[i + 32] = ((x0 & 0xF0) >> 4) | (x1 & 0xF0); 2362 2363 uchar x2 = b->ql[i*2 + 0 + 64] & mask_lsb_8; 2364 uchar x3 = b->ql[i*2 + 1 + 64] & mask_lsb_8; 2365 ql[i + 64] = (x2 & 0x0F) | ((x3 & 0x0F) << 4); 2366 ql[i + 96] = ((x2 & 0xF0) >> 4) | (x3 & 0xF0); 2367 } 2368 2369 for (int i = 0; i < QK_K/4/8; ++i) { 2370 uchar x0 = b->qh[i*4 + 0] & mask_lsb_8; 2371 uchar x1 = b->qh[i*4 + 1] & mask_lsb_8; 2372 uchar x2 = b->qh[i*4 + 2] & mask_lsb_8; 2373 uchar x3 = b->qh[i*4 + 3] & mask_lsb_8; 2374 qh[i + 0] = (x0 & 0x03) | ((x1 & 0x03) << 2) | ((x2 & 0x03) << 4) | ((x3 & 0x03) << 6); 2375 qh[i + 8] = ((x0 & 0x0C) >> 2) | (x1 & 0x0C) | ((x2 & 0x0C) << 2) | ((x3 & 0x0C) << 4); 2376 qh[i + 16] = ((x0 & 0x30) >> 4) | ((x1 & 0x30) >> 2) | (x2 & 0x30) | ((x3 & 0x30) << 2); 2377 qh[i + 24] = ((x0 & 0xC0) >> 6) | ((x1 & 0xC0) >> 4) | ((x2 & 0xC0) >> 2) | (x3 & 0xC0); 2378 2379 uchar x4 = b->qh[i*4 + 0 + 32] & mask_lsb_8; 2380 uchar x5 = b->qh[i*4 + 1 + 32] & mask_lsb_8; 2381 uchar x6 = b->qh[i*4 + 2 + 32] & mask_lsb_8; 2382 uchar x7 = b->qh[i*4 + 3 + 32] & mask_lsb_8; 2383 qh[i + 32] = (x4 & 0x03) | ((x5 & 0x03) << 2) | ((x6 & 0x03) << 4) | ((x7 & 0x03) << 6); 2384 qh[i + 40] = ((x4 & 0x0C) >> 2) | (x5 & 0x0C) | ((x6 & 0x0C) << 2) | ((x7 & 0x0C) << 4); 2385 qh[i + 48] = ((x4 & 0x30) >> 4) | ((x5 & 0x30) >> 2) | (x6 & 0x30) | ((x7 & 0x30) << 2); 2386 qh[i + 56] = ((x4 & 0xC0) >> 6) | ((x5 & 0xC0) >> 4) | ((x6 & 0xC0) >> 2) | (x7 & 0xC0); 2387 } 2388 2389 for (int i = 0; i < QK_K/16; ++i) { 2390 s[i] = b->scales[i]; 2391 } 2392} 2393 2394kernel void kernel_restore_block_q6_K_noshuffle( 2395 global uchar * src_ql, 2396 global uchar * src_qh, 2397 global char * src_s, 2398 global half * src_d, 2399 global struct block_q6_K * dst, 2400 uchar mask_lsb_8, 2401 ulong n_blk 2402) { 2403 if (get_global_id(0) >= n_blk) { 2404 return; 2405 } 2406 global struct block_q6_K * b = (global struct block_q6_K *) dst + get_global_id(0); 2407 global uchar * ql = (global uchar *) src_ql + QK_K/2*get_global_id(0); 2408 global uchar * qh = (global uchar *) src_qh + QK_K/4*get_global_id(0); 2409 global char * s = (global char *) src_s + QK_K/16*get_global_id(0); 2410 global half * d = (global half *) src_d + get_global_id(0); 2411 2412 b->d = *d; 2413 2414 for (int i = 0; i < QK_K/2/4; ++i) { 2415 uchar x0 = ql[i + 0] & mask_lsb_8; 2416 uchar x1 = ql[i + 32] & mask_lsb_8; 2417 b->ql[i*2 + 0] = (x0 & 0x0F) | ((x1 & 0x0F) << 4); 2418 b->ql[i*2 + 1] = ((x0 & 0xF0) >> 4) | (x1 & 0xF0); 2419 2420 uchar x2 = ql[i + 64] & mask_lsb_8; 2421 uchar x3 = ql[i + 96] & mask_lsb_8; 2422 b->ql[i*2 + 0 + 64] = (x2 & 0x0F) | ((x3 & 0x0F) << 4); 2423 b->ql[i*2 + 1 + 64] = ((x2 & 0xF0) >> 4) | (x3 & 0xF0); 2424 } 2425 2426 for (int i = 0; i < QK_K/4/8; ++i) { 2427 uchar x0 = qh[i + 0] & mask_lsb_8; 2428 uchar x1 = qh[i + 8] & mask_lsb_8; 2429 uchar x2 = qh[i + 16] & mask_lsb_8; 2430 uchar x3 = qh[i + 24] & mask_lsb_8; 2431 b->qh[i*4 + 0] = (x0 & 0x03) | ((x1 & 0x03) << 2) | ((x2 & 0x03) << 4) | ((x3 & 0x03) << 6); 2432 b->qh[i*4 + 1] = ((x0 & 0x0C) >> 2) | (x1 & 0x0C) | ((x2 & 0x0C) << 2) | ((x3 & 0x0C) << 4); 2433 b->qh[i*4 + 2] = ((x0 & 0x30) >> 4) | ((x1 & 0x30) >> 2) | (x2 & 0x30) | ((x3 & 0x30) << 2); 2434 b->qh[i*4 + 3] = ((x0 & 0xC0) >> 6) | ((x1 & 0xC0) >> 4) | ((x2 & 0xC0) >> 2) | (x3 & 0xC0); 2435 2436 uchar x4 = qh[i + 0 + 32] & mask_lsb_8; 2437 uchar x5 = qh[i + 8 + 32] & mask_lsb_8; 2438 uchar x6 = qh[i + 16 + 32] & mask_lsb_8; 2439 uchar x7 = qh[i + 24 + 32] & mask_lsb_8; 2440 b->qh[i*4 + 0 + 32] = (x4 & 0x03) | ((x5 & 0x03) << 2) | ((x6 & 0x03) << 4) | ((x7 & 0x03) << 6); 2441 b->qh[i*4 + 1 + 32] = ((x4 & 0x0C) >> 2) | (x5 & 0x0C) | ((x6 & 0x0C) << 2) | ((x7 & 0x0C) << 4); 2442 b->qh[i*4 + 2 + 32] = ((x4 & 0x30) >> 4) | ((x5 & 0x30) >> 2) | (x6 & 0x30) | ((x7 & 0x30) << 2); 2443 b->qh[i*4 + 3 + 32] = ((x4 & 0xC0) >> 6) | ((x5 & 0xC0) >> 4) | ((x6 & 0xC0) >> 2) | (x7 & 0xC0); 2444 } 2445 2446 for (int i = 0; i < QK_K/16; ++i) { 2447 b->scales[i] = s[i]; 2448 } 2449} 2450 2451//------------------------------------------------------------------------------ 2452// kernel_convert_block_iq4_nl 2453// Convert the block_iq4_nl format to 2 separate arrays (AOS -> SOA). 2454//------------------------------------------------------------------------------ 2455kernel void kernel_convert_block_iq4_nl( 2456 global struct block_iq4_nl * src0, 2457 global uchar * dst_q, 2458 global half * dst_d, 2459 uchar mask_0F, 2460 uchar mask_F0, 2461 ulong n_blk 2462) { 2463 if (get_global_id(0) >= n_blk) { 2464 return; 2465 } 2466 global struct block_iq4_nl * b = (global struct block_iq4_nl *) src0 + get_global_id(0); 2467 global uchar * q = (global uchar *) dst_q + QK4_NL/2*get_global_id(0); 2468 global half * d = (global half *) dst_d + get_global_id(0); 2469 2470 *d = b->d; 2471 2472 for (int i = 0; i < QK4_NL/2; ++i) { 2473 q[i] = b->qs[i]; 2474 } 2475} 2476 2477kernel void kernel_restore_block_iq4_nl( 2478 global uchar * src_q, 2479 global half * src_d, 2480 global struct block_iq4_nl * dst, 2481 ulong n_blk 2482) { 2483 if (get_global_id(0) >= n_blk) { 2484 return; 2485 } 2486 global struct block_iq4_nl * b = (global struct block_iq4_nl *) dst + get_global_id(0); 2487 global uchar * q = (global uchar *) src_q + QK4_NL/2*get_global_id(0); 2488 global half * d = (global half *) src_d + get_global_id(0); 2489 2490 b->d = *d; 2491 2492 for (int i = 0; i < QK4_NL/2; ++i) { 2493 b->qs[i] = q[i]; 2494 } 2495} 2496 2497kernel void kernel_convert_block_iq4_nl_noshuffle( 2498 global struct block_iq4_nl * src0, 2499 global uchar * dst_q, 2500 global half * dst_d, 2501 uchar mask_0F, 2502 uchar mask_F0, 2503 ulong n_blk 2504) { 2505 if (get_global_id(0) >= n_blk) { 2506 return; 2507 } 2508 global struct block_iq4_nl * b = (global struct block_iq4_nl *) src0 + get_global_id(0); 2509 global uchar * q = (global uchar *) dst_q + QK4_NL/2*get_global_id(0); 2510 global half * d = (global half *) dst_d + get_global_id(0); 2511 2512 *d = b->d; 2513 for (int i = 0; i < QK4_NL/4; ++i) { 2514 uchar x0 = b->qs[2*i + 0]; 2515 uchar x1 = b->qs[2*i + 1]; 2516 2517 q[i + 0 ] = convert_uchar(x0 & mask_0F) | convert_uchar((x1 & mask_0F) << 4); 2518 q[i + QK4_NL/4] = convert_uchar((x0 & mask_F0) >> 4) | convert_uchar(x1 & mask_F0); 2519 } 2520} 2521 2522kernel void kernel_restore_block_iq4_nl_noshuffle( 2523 global uchar * src_q, 2524 global half * src_d, 2525 global struct block_iq4_nl * dst, 2526 uchar mask_0F, 2527 uchar mask_F0, 2528 ulong n_blk 2529) { 2530 if (get_global_id(0) >= n_blk) { 2531 return; 2532 } 2533 global struct block_iq4_nl * b = (global struct block_iq4_nl *) dst + get_global_id(0); 2534 global uchar * q = (global uchar *) src_q + QK4_NL/2*get_global_id(0); 2535 global half * d = (global half *) src_d + get_global_id(0); 2536 2537 b->d = *d; 2538 for (int i = 0; i < QK4_NL/4; ++i) { 2539 uchar x0 = q[i + 0 ]; 2540 uchar x1 = q[i + QK4_NL/4]; 2541 2542 b->qs[2*i + 0] = convert_uchar((x0 & mask_0F) | ((x1 & mask_0F) << 4)); 2543 b->qs[2*i + 1] = convert_uchar(((x0 & mask_F0) >> 4) | (x1 & mask_F0)); 2544 } 2545} 2546 2547// --------------------------------------------------------------------------- 2548// kernel_moe_expand_scale_q8_0 2549// 2550// Expand the q8_0 per-32-block scale d (one half/block, [expert][row][block]) into 2551// the UNIFORM scale[16] format the generic dp4a MoE GEMM (kernel_gemm_moe_q8_1_dp4a, 2552// MOE_QT=80) consumes: 16 f16 per 256-superblock (per-16-element segment), where the 2553// two segments of each 32-block share the block's d. q8_0 is symmetric -> no min 2554// buffer (the GEMM runs with has_min=0). The int8 weight codes are reused verbatim 2555// from the existing flat q8_0 weight buffer (extra0_q8_0->q), so only the scale is 2556// rebuilt here. One work-item per (row, superblock, expert). 2557// --------------------------------------------------------------------------- 2558kernel void kernel_moe_expand_scale_q8_0( 2559 global const half * src_d, // [expert][row][block], one scale per 32-block 2560 global half * dst_scale, // [expert][row][block][2] (FLAT per-32-block) 2561 int ne00, 2562 int ne01 2563) { 2564 int row = get_global_id(0); 2565 int blk = get_global_id(1); // 32-block index along K 2566 int e = get_global_id(2); 2567 if (row >= ne01) { return; } 2568 2569 long nb = ne00 / 32; // 32-blocks per row (K only needs % 32 == 0) 2570 half d = src_d[((long)e*ne01 + row)*nb + blk]; 2571 long b = (((long)e*ne01 + row)*nb + blk) * 2; 2572 dst_scale[b + 0] = d; 2573 dst_scale[b + 1] = d; 2574} 2575 2576// --------------------------------------------------------------------------- 2577// kernel_moe_expand_scale_q5_0 2578// 2579// q5_0 = symmetric, value = d*(code-16), code = nibble | (hi<<4) in 0..31. The 2580// generic dp4a MoE GEMM keeps the unsigned code and centers via the min term: 2581// scale*dp4a(code,a) - min*sum(a), scale = d, min = d*16. 2582// Reads the existing q5_0 d ([expert][block][row], one half/32-block, from the 2583// trans4 convert) and writes the FLAT per-32-block uniform scale[2]/min[1] in 2584// [expert][row][block] order (a transpose). One work-item per (row, block, expert). 2585// --------------------------------------------------------------------------- 2586kernel void kernel_moe_expand_scale_q5_0( 2587 global const half * src_d, // [expert][block][row] 2588 global half * dst_scale, // [expert][row][block][2] 2589 global half * dst_min, // [expert][row][block] 2590 int ne00, 2591 int ne01 2592) { 2593 int row = get_global_id(0); 2594 int blk = get_global_id(1); 2595 int e = get_global_id(2); 2596 if (row >= ne01) { return; } 2597 2598 long nb = ne00 / 32; 2599 half d = src_d[(long)e*nb*ne01 + (long)blk*ne01 + row]; // [expert][block][row] 2600 long sb = (((long)e*ne01 + row)*nb + blk) * 2; 2601 long mb = ((long)e*ne01 + row)*nb + blk; 2602 dst_scale[sb + 0] = d; 2603 dst_scale[sb + 1] = d; 2604 dst_min[mb] = (half)((float)d * 16.0f); 2605} 2606 2607// --------------------------------------------------------------------------- 2608// kernel_moe_expand_scale_q5_K 2609// 2610// q5_K value = d*sv*code + (-dm*mn), with the 6-bit packed per-sub-block scale sv 2611// and min mn (8 sub-blocks of 32 per 256-superblock, decoded by get_scale_min_k4 2612// from the 12-byte s[]). The generic dp4a MoE GEMM (kernel_gemm_moe_q8_1_dp4a, 2613// MOE_QT=5) keeps the unsigned 5-bit code and applies scale/min via the uniform 2614// per-32-block buffers: 2615// acc += sc0*a_d*raw1 + sc1*a_d*raw2 - mn_u*a_s, 2616// sc0 = sc1 = d*sv (both per-16 segments of a 32-block share the sub-block scale), 2617// mn_u = dm*mn (positive; the GEMM subtracts it -> the -dm*mn min term). 2618// q5_K's q_img (low nibbles) + qh (hi-bit plane) are already in the layout the GEMM 2619// reads (same trans4_ns convert that feeds gemm_moe_q5_k_f32_ns), so only the scale 2620// is rebuilt here. 2621// 2622// One work-item per (row, superblock, expert); each emits 8 sub-blocks. 2623// --------------------------------------------------------------------------- 2624kernel void kernel_moe_expand_scale_q5_K( 2625 global const uchar * src_s, // [expert][row][superblock][12] 2626 global const half * src_d, // [expert][superblock][row] 2627 global const half * src_dm, // [expert][superblock][row] 2628 global half * dst_scale, // [expert][row][32block][2] 2629 global half * dst_min, // [expert][row][32block] 2630 int ne00, 2631 int ne01 2632) { 2633 int row = get_global_id(0); 2634 int sb = get_global_id(1); // superblock index along K 2635 int e = get_global_id(2); 2636 if (row >= ne01) { return; } 2637 2638 long nsb = ne00 / 256; // superblocks per row 2639 long nblk32 = ne00 / 32; // 32-blocks per row 2640 2641 float d = (float)src_d [((long)e*nsb + sb)*ne01 + row]; 2642 float dm = (float)src_dm[((long)e*nsb + sb)*ne01 + row]; 2643 2644 __global const uchar * sc = src_s + ((long)e*ne01 + row)*nsb*12 + (long)sb*12; 2645 2646 for (int j = 0; j < 8; ++j) { 2647 uchar sv, mn; 2648 // get_scale_min_k4 (6-bit packed scale/min for sub-block j of 8) 2649 if (j < 4) { 2650 sv = sc[j] & 63; 2651 mn = sc[j+4] & 63; 2652 } else { 2653 sv = (sc[j+4] & 0x0F) | ((sc[j-4] & 0xC0) >> 2); 2654 mn = ((sc[j+4] >> 4) & 0x0F) | ((sc[j] & 0xC0) >> 2); 2655 } 2656 long sub = (long)sb*8 + j; 2657 long sbase = (((long)e*ne01 + row)*nblk32 + sub) * 2; 2658 half s_val = (half)(d * (float)sv); 2659 dst_scale[sbase + 0] = s_val; 2660 dst_scale[sbase + 1] = s_val; 2661 dst_min[((long)e*ne01 + row)*nblk32 + sub] = (half)(dm * (float)mn); 2662 } 2663}