char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
867229003
char/aliceai-t5-moe
1#ifndef GGML_SYCL_ESIMD_HPP 2#define GGML_SYCL_ESIMD_HPP 3 4#include <sycl/ext/intel/esimd.hpp> 5 6#include "common.hpp" 7 8namespace ggml_sycl_esimd { 9 10constexpr int GGML_SYCL_DMMV_ESIMD_WG_SIZE = 4 ; 11 12// 13// Shared ESIMD building blocks for the reordered K-quant dequantize-matvec 14// kernels. 15// 16// The reordered K-quant ESIMD matvec kernels share one skeleton: per super-block, 17// load a 256-float activation slice, load one weight block, dequantize it into 8 18// chunks of 32 and MAC each chunk against the matching activation slice, then 19// reduce and run a lane-0 epilogue. 20// 21// Each K-quant kernel emits exactly 8 chunks of 32 mapping to activation slices 22// 0..7, so the per-block work is captured by esimd_reorder_q_traits<T>::mac_pair, 23// which dequantizes two weight blocks and MACs both against a shared activation 24// vector with the two FMA chains interleaved (co-scheduled to hide FMA latency). 25// The "pair" is the (row0,row1) row pair owned by one work-group, so the 26// layout+dequant is written once per quant type here. 27// 28 29template < ggml_type T > struct esimd_reorder_q_traits ; 30 31// build a 32-lane vector whose low 16 lanes are `lo` and high 16 are `hi` 32// (a super-chunk splits into two 16-wide halves with distinct scale/min codes). 33static ESIMD_INLINE sycl::ext::intel::esimd::simd < float ,32 > splat_lo_hi (float lo ,float hi ) { 34using namespace sycl::ext::intel::esimd ; 35simd < float ,32 > v ; 36v .select < 16 ,1 > (0 )= lo ; 37v .select < 16 ,1 > (16 )= hi ; 38return v ; 39} 40 41// unpack one block of Q4_K/Q5_K scale/min codes (get_scale_min_k4 layout) into 8 42// float scales (dall * sc) and 8 float mins (-dmin * m); the min carries the 43// negation so the dequant epilogue adds. 44static ESIMD_INLINE void unpack_scale_min_k4 ( 45 sycl::ext::intel::esimd::simd < uint8_t ,12 > scales ,float dall ,float dmin , 46 sycl::ext::intel::esimd::simd < float ,8 > & scale_f , 47 sycl::ext::intel::esimd::simd < float ,8 > & min_f ) { 48using namespace sycl::ext::intel::esimd ; 49simd < uint8_t ,8 > sc = 0 ; 50simd < uint8_t ,8 > m = 0 ; 51simd < uint8_t ,4 > scale_lo = scales .select < 4 ,1 > (0 ); 52simd < uint8_t ,4 > min_lo = scales .select < 4 ,1 > (4 ); 53simd < uint8_t ,4 > hi_bits = scales .select < 4 ,1 > (8 ); 54sc .select < 4 ,1 > (0 )= scale_lo & simd < uint8_t ,4 > (0x3F ); 55sc .select < 4 ,1 > (4 )= (hi_bits & simd < uint8_t ,4 > (0x0F )) | 56 ((scale_lo >>simd < uint8_t ,4 > (6 )) <<simd < uint8_t ,4 > (4 )); 57m .select < 4 ,1 > (0 )= min_lo & simd < uint8_t ,4 > (0x3F ); 58m .select < 4 ,1 > (4 )= (hi_bits >>simd < uint8_t ,4 > (4 )) | 59 ((min_lo >>simd < uint8_t ,4 > (6 )) <<simd < uint8_t ,4 > (4 )); 60scale_f = convert < float > (sc )* dall ; 61min_f = convert < float > (m )* (- dmin ); 62} 63 64// --------------------------------------------------------------------------- 65// Q2_K, SOA reorder layout produced by reorder_qw_q2_k: 66// [qs: nb*(QK_K/4)] [scales: nb*(QK_K/16)] [dm: nb*sizeof(half2)] 67// with nb = nrows*num_blocks_per_row. 68// 69// 2 bits per weight. The 8 output chunks of 32 (matching dequantize_row_q2_K) 70// map to super-chunk s (0..7): byte base 32*(s/4) into the 64-byte qs array, 71// bit shift 2*(s%4); the low 16 lanes use scales[2s], the high 16 use 72// scales[2s+1], with dl = d*(sc & 0xF), ml = dmin*(sc >> 4), deq = dl*q - ml. 73// --------------------------------------------------------------------------- 74template <> struct esimd_reorder_q_traits < GGML_TYPE_Q2_K > { 75struct ptrs { 76const uint8_t * qs ; 77const uint8_t * scales ; 78const sycl::half * dm ; 79 }; 80 81static ESIMD_INLINE ptrs make_ptrs (const void * vx ,size_t nb ) { 82const uint8_t * qs = (const uint8_t * )vx ; 83const uint8_t * scales = qs + nb * (QK_K /4 ); 84const sycl::half * dm = (const sycl::half * ) (scales + nb * (QK_K /16 )); 85return {qs ,scales ,dm }; 86 } 87 88static ESIMD_INLINE void mac_pair ( 89const ptrs & pa ,size_t bia , 90const ptrs & pb ,size_t bib ,bool has_b , 91 sycl::ext::intel::esimd::simd < float ,256 > & y_vec , 92 sycl::ext::intel::esimd::simd < float ,32 > & acc_a , 93 sycl::ext::intel::esimd::simd < float ,32 > & acc_b ) { 94using namespace sycl::ext::intel::esimd ; 95 96simd < uint8_t ,64 > qs_a = block_load < uint8_t ,64 > (pa .qs + bia * (QK_K /4 )); 97simd < uint8_t ,64 > qs_b = 0 ; 98simd < uint8_t ,16 > scales_a = block_load < uint8_t ,16 > (pa .scales + bia * (QK_K /16 )); 99simd < uint8_t ,16 > scales_b = 0 ; 100 101const float dall_a = (float )pa .dm [bia * 2 + 0 ]; 102const float dmin_a = (float )pa .dm [bia * 2 + 1 ]; 103float dall_b = 0.0f ; 104float dmin_b = 0.0f ; 105if (has_b ) { 106qs_b = block_load < uint8_t ,64 > (pb .qs + bib * (QK_K /4 )); 107scales_b = block_load < uint8_t ,16 > (pb .scales + bib * (QK_K /16 )); 108dall_b = (float )pb .dm [bib * 2 + 0 ]; 109dmin_b = (float )pb .dm [bib * 2 + 1 ]; 110 } 111 112// per-chunk scale (d * (sc & 0xF)) and min (-dmin * (sc >> 4)), all 16 codes; 113// min carries the negation so the dequant epilogue adds (matches Q4_K/Q5_K) 114simd < float ,16 > scale_f_a = convert < float > (scales_a & simd < uint8_t ,16 > (0x0F ))* dall_a ; 115simd < float ,16 > min_f_a = convert < float > (scales_a >>simd < uint8_t ,16 > (4 ))* (- dmin_a ); 116simd < float ,16 > scale_f_b = convert < float > (scales_b & simd < uint8_t ,16 > (0x0F ))* dall_b ; 117simd < float ,16 > min_f_b = convert < float > (scales_b >>simd < uint8_t ,16 > (4 ))* (- dmin_b ); 118 119#pragma unroll 120for (int s = 0 ;s < 8 ;++ s ) { 121const int byte_base = 32 * (s /4 ); 122const uint8_t shift = (uint8_t ) (2 * (s %4 )); 123simd < float ,32 > y_s = y_vec .select < 32 ,1 > (s * 32 ); 124 125simd < uint8_t ,32 > qa = (qs_a .select < 32 ,1 > (byte_base ) >>shift )& simd < uint8_t ,32 > (3 ); 126simd < uint8_t ,32 > qb = (qs_b .select < 32 ,1 > (byte_base ) >>shift )& simd < uint8_t ,32 > (3 ); 127 128const float scale_a_lo = scale_f_a [2 * s + 0 ]; 129const float scale_a_hi = scale_f_a [2 * s + 1 ]; 130const float min_a_lo = min_f_a [2 * s + 0 ]; 131const float min_a_hi = min_f_a [2 * s + 1 ]; 132const float scale_b_lo = scale_f_b [2 * s + 0 ]; 133const float scale_b_hi = scale_f_b [2 * s + 1 ]; 134const float min_b_lo = min_f_b [2 * s + 0 ]; 135const float min_b_hi = min_f_b [2 * s + 1 ]; 136 137simd < float ,32 > scale_vec_a = splat_lo_hi (scale_a_lo ,scale_a_hi ); 138simd < float ,32 > min_vec_a = splat_lo_hi (min_a_lo ,min_a_hi ); 139simd < float ,32 > scale_vec_b = splat_lo_hi (scale_b_lo ,scale_b_hi ); 140simd < float ,32 > min_vec_b = splat_lo_hi (min_b_lo ,min_b_hi ); 141 142simd < float ,32 > deq_a = convert < float > (qa )* scale_vec_a + min_vec_a ; 143simd < float ,32 > deq_b = convert < float > (qb )* scale_vec_b + min_vec_b ; 144 145acc_a += y_s * deq_a ; 146acc_b += y_s * deq_b ; 147 } 148 } 149}; 150 151// --------------------------------------------------------------------------- 152// Q3_K, SOA reorder layout produced by reorder_qw_q3_k: 153// [qs: nb*(QK_K/4)] [hmask: nb*(QK_K/8)] [scales: nb*12] [d: nb*sizeof(half)] 154// with nb = nrows*num_blocks_per_row. Single super-block scale d, no dmin. 155// 156// 3 bits per weight: 2 low bits in qs, 1 high bit in hmask. The 8 output chunks 157// of 32 (matching dequantize_row_q3_K) map to super-chunk s (0..7): byte base 158// 32*(s/4) into the 64-byte qs array, bit shift 2*(s%4); the low 16 lanes use 159// scale code 2s, the high 16 use 2s+1. hmask is a 32-byte array (like Q5_K's 160// qh) where chunk s uses bit s of the same 32 bytes, but INVERTED: the value is 161// (q & 3) - (hmask_bit_set ? 0 : 4), i.e. (q & 3) + 4*bit - 4. 162// 163// The 16 6-bit scale codes are packed into 12 bytes (get_scale_min layout for 164// Q3_K): low nibbles from bytes 0..7, high 2 bits from bytes 8..11 shifted by 165// 0/2/4/6; the dequant scale is d * (code - 32). 166// --------------------------------------------------------------------------- 167template <> struct esimd_reorder_q_traits < GGML_TYPE_Q3_K > { 168struct ptrs { 169const uint8_t * qs ; 170const uint8_t * hmask ; 171const uint8_t * scales ; 172const sycl::half * d ; 173 }; 174 175static ESIMD_INLINE ptrs make_ptrs (const void * vx ,size_t nb ) { 176const uint8_t * qs = (const uint8_t * )vx ; 177const uint8_t * hmask = qs + nb * (QK_K /4 ); 178const uint8_t * scales = hmask + nb * (QK_K /8 ); 179const sycl::half * d = (const sycl::half * ) (scales + nb * 12 ); 180return {qs ,hmask ,scales ,d }; 181 } 182 183// unpack the 12 packed bytes into 16 6-bit scale codes (dequantize_row_q3_K 184// aux layout), returned as float scale = d * (code - 32). 185// done with wide (8/16-lane) ops rather than four 4-lane groups. 186static ESIMD_INLINE sycl ::ext::intel::esimd::simd < float ,16 > unpack_scales ( 187 sycl::ext::intel::esimd::simd < uint8_t ,12 > in ,float d ) { 188using namespace sycl::ext::intel::esimd ; 189 190// low 6-bit part: codes 0..7 = low nibble of bytes 0..7, 191// codes 8..15 = high nibble of bytes 0..7 192simd < uint8_t ,8 > lo8 = in .select < 8 ,1 > (0 ); 193simd < uint8_t ,16 > code ; 194code .select < 8 ,1 > (0 )= lo8 & simd < uint8_t ,8 > (0x0F ); 195code .select < 8 ,1 > (8 )= lo8 >>simd < uint8_t ,8 > (4 ); 196 197// high 2-bit part: bytes 8..11 replicated 4x, group g (0..3) shifted 2*g 198simd < uint8_t ,16 > hib ; 199hib .select < 4 ,1 > (0 )= in .select < 4 ,1 > (8 ); 200hib .select < 4 ,1 > (4 )= in .select < 4 ,1 > (8 ); 201hib .select < 4 ,1 > (8 )= in .select < 4 ,1 > (8 ); 202hib .select < 4 ,1 > (12 )= in .select < 4 ,1 > (8 ); 203simd < uint8_t ,16 > hshift ; 204hshift .select < 4 ,1 > (0 )= 0 ; 205hshift .select < 4 ,1 > (4 )= 2 ; 206hshift .select < 4 ,1 > (8 )= 4 ; 207hshift .select < 4 ,1 > (12 )= 6 ; 208hib = (hib >>hshift )& simd < uint8_t ,16 > (0x03 ); 209 210code = code | (hib <<simd < uint8_t ,16 > (4 )); 211return (convert < float > (code )- 32.0f )* d ; 212 } 213 214static ESIMD_INLINE void mac_pair ( 215const ptrs & pa ,size_t bia , 216const ptrs & pb ,size_t bib ,bool has_b , 217 sycl::ext::intel::esimd::simd < float ,256 > & y_vec , 218 sycl::ext::intel::esimd::simd < float ,32 > & acc_a , 219 sycl::ext::intel::esimd::simd < float ,32 > & acc_b ) { 220using namespace sycl::ext::intel::esimd ; 221 222simd < uint8_t ,64 > qs_a = block_load < uint8_t ,64 > (pa .qs + bia * (QK_K /4 )); 223simd < uint8_t ,64 > qs_b = 0 ; 224simd < uint8_t ,32 > hmask_a = block_load < uint8_t ,32 > (pa .hmask + bia * (QK_K /8 )); 225simd < uint8_t ,32 > hmask_b = 0 ; 226simd < uint8_t ,12 > scales_a = block_load < uint8_t ,12 > (pa .scales + bia * 12 ); 227simd < uint8_t ,12 > scales_b = 0 ; 228 229const float d_a = (float )pa .d [bia ]; 230float d_b = 0.0f ; 231if (has_b ) { 232qs_b = block_load < uint8_t ,64 > (pb .qs + bib * (QK_K /4 )); 233hmask_b = block_load < uint8_t ,32 > (pb .hmask + bib * (QK_K /8 )); 234scales_b = block_load < uint8_t ,12 > (pb .scales + bib * 12 ); 235d_b = (float )pb .d [bib ]; 236 } 237 238simd < float ,16 > scale_f_a = unpack_scales (scales_a ,d_a ); 239simd < float ,16 > scale_f_b = unpack_scales (scales_b ,d_b ); 240 241#pragma unroll 242for (int s = 0 ;s < 8 ;++ s ) { 243const int byte_base = 32 * (s /4 ); 244const uint8_t shift = (uint8_t ) (2 * (s %4 )); 245simd < float ,32 > y_s = y_vec .select < 32 ,1 > (s * 32 ); 246 247// 2 low bits from qs, high bit from hmask (bit s of the same 32 bytes); 248// value = (q & 3) + 4*bit - 4 (inverted hmask: subtract 4 when bit clear). 249// merge in the integer domain: q3 = (q & 3) | (bit << 2) in {0..7}, 250// then a single convert + subtract yields q3 - 4 (one convert, not two) 251simd < uint16_t ,32 > q3_a = convert < uint16_t > ( 252 (qs_a .select < 32 ,1 > (byte_base ) >>shift )& simd < uint8_t ,32 > (3 )); 253q3_a |=convert < uint16_t > ( 254 ((hmask_a >>simd < uint8_t ,32 > ((uint8_t )s ))& simd < uint8_t ,32 > (1 )) <<simd < uint8_t ,32 > (2 )); 255simd < uint16_t ,32 > q3_b = convert < uint16_t > ( 256 (qs_b .select < 32 ,1 > (byte_base ) >>shift )& simd < uint8_t ,32 > (3 )); 257q3_b |=convert < uint16_t > ( 258 ((hmask_b >>simd < uint8_t ,32 > ((uint8_t )s ))& simd < uint8_t ,32 > (1 )) <<simd < uint8_t ,32 > (2 )); 259 260simd < float ,32 > qf_a = convert < float > (q3_a )- 4.0f ; 261simd < float ,32 > qf_b = convert < float > (q3_b )- 4.0f ; 262 263const float scale_a_lo = scale_f_a [2 * s + 0 ]; 264const float scale_a_hi = scale_f_a [2 * s + 1 ]; 265const float scale_b_lo = scale_f_b [2 * s + 0 ]; 266const float scale_b_hi = scale_f_b [2 * s + 1 ]; 267 268simd < float ,32 > scale_vec_a = splat_lo_hi (scale_a_lo ,scale_a_hi ); 269simd < float ,32 > scale_vec_b = splat_lo_hi (scale_b_lo ,scale_b_hi ); 270 271simd < float ,32 > deq_a = qf_a * scale_vec_a ; 272simd < float ,32 > deq_b = qf_b * scale_vec_b ; 273 274acc_a += y_s * deq_a ; 275acc_b += y_s * deq_b ; 276 } 277 } 278}; 279 280// --------------------------------------------------------------------------- 281// Q4_K, SOA reorder layout produced by reorder_qw_q4_k: 282// [qs: nb*(QK_K/2)] [scales: nb*K_SCALE_SIZE] [dm: nb*sizeof(half2)] 283// with nb = nrows*num_blocks_per_row. 284// --------------------------------------------------------------------------- 285template <> struct esimd_reorder_q_traits < GGML_TYPE_Q4_K > { 286struct ptrs { 287const uint8_t * qs ; 288const uint8_t * scales ; 289const sycl::half * dm ; 290 }; 291 292static ESIMD_INLINE ptrs make_ptrs (const void * vx ,size_t nb ) { 293const uint8_t * qs = (const uint8_t * )vx ; 294const uint8_t * scales = qs + nb * (QK_K /2 ); 295const sycl::half * dm = (const sycl::half * ) (scales + nb * K_SCALE_SIZE ); 296return {qs ,scales ,dm }; 297 } 298 299static ESIMD_INLINE void mac_pair ( 300const ptrs & pa ,size_t bia , 301const ptrs & pb ,size_t bib ,bool has_b , 302 sycl::ext::intel::esimd::simd < float ,256 > & y_vec , 303 sycl::ext::intel::esimd::simd < float ,32 > & acc_a , 304 sycl::ext::intel::esimd::simd < float ,32 > & acc_b ) { 305using namespace sycl::ext::intel::esimd ; 306 307simd < uint8_t ,128 > qs_a = block_load < uint8_t ,128 > (pa .qs + bia * (QK_K /2 )); 308simd < uint8_t ,128 > qs_b = 0 ; 309simd < uint8_t ,12 > scales_a = block_load < uint8_t ,12 > (pa .scales + bia * K_SCALE_SIZE ); 310simd < uint8_t ,12 > scales_b = 0 ; 311 312const float dall_a = (float )pa .dm [bia * 2 + 0 ]; 313const float dmin_a = (float )pa .dm [bia * 2 + 1 ]; 314float dall_b = 0.0f ; 315float dmin_b = 0.0f ; 316if (has_b ) { 317qs_b = block_load < uint8_t ,128 > (pb .qs + bib * (QK_K /2 )); 318scales_b = block_load < uint8_t ,12 > (pb .scales + bib * K_SCALE_SIZE ); 319dall_b = (float )pb .dm [bib * 2 + 0 ]; 320dmin_b = (float )pb .dm [bib * 2 + 1 ]; 321 } 322 323simd < float ,8 > scale_f_a ,min_f_a ,scale_f_b ,min_f_b ; 324unpack_scale_min_k4 (scales_a ,dall_a ,dmin_a ,scale_f_a ,min_f_a ); 325unpack_scale_min_k4 (scales_b ,dall_b ,dmin_b ,scale_f_b ,min_f_b ); 326 327simd < uint8_t ,128 > qs_lo_a = qs_a & simd < uint8_t ,128 > (0x0F ); 328simd < uint8_t ,128 > qs_hi_a = qs_a >>simd < uint8_t ,128 > (4 ); 329simd < uint8_t ,128 > qs_lo_b = qs_b & simd < uint8_t ,128 > (0x0F ); 330simd < uint8_t ,128 > qs_hi_b = qs_b >>simd < uint8_t ,128 > (4 ); 331 332#pragma unroll 333for (int sb = 0 ;sb < 8 ;sb += 2 ) { 334const int q_offset = sb * 16 ; 335simd < float ,32 > y_lo = y_vec .select < 32 ,1 > (sb * 32 ); 336simd < float ,32 > y_hi = y_vec .select < 32 ,1 > ((sb + 1 )* 32 ); 337 338const float scale_a_lo = scale_f_a [sb ]; 339const float scale_a_hi = scale_f_a [sb + 1 ]; 340const float min_a_lo = min_f_a [sb ]; 341const float min_a_hi = min_f_a [sb + 1 ]; 342const float scale_b_lo = scale_f_b [sb ]; 343const float scale_b_hi = scale_f_b [sb + 1 ]; 344const float min_b_lo = min_f_b [sb ]; 345const float min_b_hi = min_f_b [sb + 1 ]; 346 347simd < uint8_t ,32 > qa_lo = qs_lo_a .select < 32 ,1 > (q_offset ); 348simd < uint8_t ,32 > qa_hi = qs_hi_a .select < 32 ,1 > (q_offset ); 349simd < uint8_t ,32 > qb_lo = qs_lo_b .select < 32 ,1 > (q_offset ); 350simd < uint8_t ,32 > qb_hi = qs_hi_b .select < 32 ,1 > (q_offset ); 351 352simd < float ,32 > deq_a_lo = convert < float > (qa_lo )* scale_a_lo + min_a_lo ; 353simd < float ,32 > deq_a_hi = convert < float > (qa_hi )* scale_a_hi + min_a_hi ; 354simd < float ,32 > deq_b_lo = convert < float > (qb_lo )* scale_b_lo + min_b_lo ; 355simd < float ,32 > deq_b_hi = convert < float > (qb_hi )* scale_b_hi + min_b_hi ; 356 357acc_a += y_lo * deq_a_lo ; 358acc_b += y_lo * deq_b_lo ; 359acc_a += y_hi * deq_a_hi ; 360acc_b += y_hi * deq_b_hi ; 361 } 362 } 363}; 364 365// --------------------------------------------------------------------------- 366// Q5_K, SOA reorder layout produced by reorder_qw_q5_k: 367// [qs: nb*(QK_K/2)] [qh: nb*(QK_K/8)] [scales: nb*K_SCALE_SIZE] [dm: nb*sizeof(half2)] 368// with nb = nrows*num_blocks_per_row. 369// 370// Identical to Q4_K except each 4-bit quant gains a 5th (high) bit from qh: 371// output chunk c (0..7) adds 16 when bit c of qh[l] is set, where qh[l] indexes 372// the same 32 bytes for every chunk (matches dequantize_row_q5_K). 373// --------------------------------------------------------------------------- 374template <> struct esimd_reorder_q_traits < GGML_TYPE_Q5_K > { 375struct ptrs { 376const uint8_t * qs ; 377const uint8_t * qh ; 378const uint8_t * scales ; 379const sycl::half * dm ; 380 }; 381 382static ESIMD_INLINE ptrs make_ptrs (const void * vx ,size_t nb ) { 383const uint8_t * qs = (const uint8_t * )vx ; 384const uint8_t * qh = qs + nb * (QK_K /2 ); 385const uint8_t * scales = qh + nb * (QK_K /8 ); 386const sycl::half * dm = (const sycl::half * ) (scales + nb * K_SCALE_SIZE ); 387return {qs ,qh ,scales ,dm }; 388 } 389 390// extract bit `bit` (0..7) of each lane and move it to bit position 4, 391// e.g. for the 4-bit base quant's 5th (high) bit. `bit` is always a 392// compile-time-known unrolled loop constant at call sites, so this folds 393// to a single mask (bit==4), mask+left-shift (bit<4), or mask+right-shift 394// (bit>4) instead of the shift+mask+shift a naive `(qh>>bit & 1) << 4` emits. 395static ESIMD_INLINE sycl ::ext::intel::esimd::simd < uint16_t ,32 > extract_bit_to_pos4 ( 396 sycl::ext::intel::esimd::simd < uint8_t ,32 > qh ,int bit ) { 397using namespace sycl::ext::intel::esimd ; 398simd < uint16_t ,32 > masked = convert < uint16_t > (qh & simd < uint8_t ,32 > ((uint8_t ) (1u <<bit ))); 399if (bit < 4 ) { 400return masked <<simd < uint16_t ,32 > ((uint16_t ) (4 - bit )); 401 }else if (bit > 4 ) { 402return masked >>simd < uint16_t ,32 > ((uint16_t ) (bit - 4 )); 403 } 404return masked ; 405 } 406 407static ESIMD_INLINE void mac_pair ( 408const ptrs & pa ,size_t bia , 409const ptrs & pb ,size_t bib ,bool has_b , 410 sycl::ext::intel::esimd::simd < float ,256 > & y_vec , 411 sycl::ext::intel::esimd::simd < float ,32 > & acc_a , 412 sycl::ext::intel::esimd::simd < float ,32 > & acc_b ) { 413using namespace sycl::ext::intel::esimd ; 414 415simd < uint8_t ,128 > qs_a = block_load < uint8_t ,128 > (pa .qs + bia * (QK_K /2 )); 416simd < uint8_t ,128 > qs_b = 0 ; 417simd < uint8_t ,32 > qh_a = block_load < uint8_t ,32 > (pa .qh + bia * (QK_K /8 )); 418simd < uint8_t ,32 > qh_b = 0 ; 419simd < uint8_t ,12 > scales_a = block_load < uint8_t ,12 > (pa .scales + bia * K_SCALE_SIZE ); 420simd < uint8_t ,12 > scales_b = 0 ; 421 422const float dall_a = (float )pa .dm [bia * 2 + 0 ]; 423const float dmin_a = (float )pa .dm [bia * 2 + 1 ]; 424float dall_b = 0.0f ; 425float dmin_b = 0.0f ; 426if (has_b ) { 427qs_b = block_load < uint8_t ,128 > (pb .qs + bib * (QK_K /2 )); 428qh_b = block_load < uint8_t ,32 > (pb .qh + bib * (QK_K /8 )); 429scales_b = block_load < uint8_t ,12 > (pb .scales + bib * K_SCALE_SIZE ); 430dall_b = (float )pb .dm [bib * 2 + 0 ]; 431dmin_b = (float )pb .dm [bib * 2 + 1 ]; 432 } 433 434simd < float ,8 > scale_f_a ,min_f_a ,scale_f_b ,min_f_b ; 435unpack_scale_min_k4 (scales_a ,dall_a ,dmin_a ,scale_f_a ,min_f_a ); 436unpack_scale_min_k4 (scales_b ,dall_b ,dmin_b ,scale_f_b ,min_f_b ); 437 438simd < uint8_t ,128 > qs_lo_a = qs_a & simd < uint8_t ,128 > (0x0F ); 439simd < uint8_t ,128 > qs_hi_a = qs_a >>simd < uint8_t ,128 > (4 ); 440simd < uint8_t ,128 > qs_lo_b = qs_b & simd < uint8_t ,128 > (0x0F ); 441simd < uint8_t ,128 > qs_hi_b = qs_b >>simd < uint8_t ,128 > (4 ); 442 443#pragma unroll 444for (int sb = 0 ;sb < 8 ;sb += 2 ) { 445const int q_offset = sb * 16 ; 446simd < float ,32 > y_lo = y_vec .select < 32 ,1 > (sb * 32 ); 447simd < float ,32 > y_hi = y_vec .select < 32 ,1 > ((sb + 1 )* 32 ); 448 449const float scale_a_lo = scale_f_a [sb ]; 450const float scale_a_hi = scale_f_a [sb + 1 ]; 451const float min_a_lo = min_f_a [sb ]; 452const float min_a_hi = min_f_a [sb + 1 ]; 453const float scale_b_lo = scale_f_b [sb ]; 454const float scale_b_hi = scale_f_b [sb + 1 ]; 455const float min_b_lo = min_f_b [sb ]; 456const float min_b_hi = min_f_b [sb + 1 ]; 457 458simd < uint8_t ,32 > qa_lo_u8 = qs_lo_a .select < 32 ,1 > (q_offset ); 459simd < uint8_t ,32 > qa_hi_u8 = qs_hi_a .select < 32 ,1 > (q_offset ); 460simd < uint8_t ,32 > qb_lo_u8 = qs_lo_b .select < 32 ,1 > (q_offset ); 461simd < uint8_t ,32 > qb_hi_u8 = qs_hi_b .select < 32 ,1 > (q_offset ); 462simd < uint16_t ,32 > qa_lo = convert < uint16_t > (qa_lo_u8 ); 463simd < uint16_t ,32 > qa_hi = convert < uint16_t > (qa_hi_u8 ); 464simd < uint16_t ,32 > qb_lo = convert < uint16_t > (qb_lo_u8 ); 465simd < uint16_t ,32 > qb_hi = convert < uint16_t > (qb_hi_u8 ); 466 467// add the 5th bit: chunk sb uses qh bit sb, chunk sb+1 uses qh bit sb+1; 468// qh always indexes the same 32 bytes regardless of chunk 469qa_lo += extract_bit_to_pos4 (qh_a ,sb ); 470qa_hi += extract_bit_to_pos4 (qh_a ,sb + 1 ); 471qb_lo += extract_bit_to_pos4 (qh_b ,sb ); 472qb_hi += extract_bit_to_pos4 (qh_b ,sb + 1 ); 473 474simd < float ,32 > deq_a_lo = convert < float > (qa_lo )* scale_a_lo + min_a_lo ; 475simd < float ,32 > deq_a_hi = convert < float > (qa_hi )* scale_a_hi + min_a_hi ; 476simd < float ,32 > deq_b_lo = convert < float > (qb_lo )* scale_b_lo + min_b_lo ; 477simd < float ,32 > deq_b_hi = convert < float > (qb_hi )* scale_b_hi + min_b_hi ; 478 479acc_a += y_lo * deq_a_lo ; 480acc_b += y_lo * deq_b_lo ; 481acc_a += y_hi * deq_a_hi ; 482acc_b += y_hi * deq_b_hi ; 483 } 484 } 485}; 486 487// --------------------------------------------------------------------------- 488// Q6_K, SOA reorder layout: 489// [ql: nb*(QK_K/2)] [qh: nb*(QK_K/4)] [scales(int8): nb*(QK_K/16)] [d: nb*half] 490// --------------------------------------------------------------------------- 491template <> struct esimd_reorder_q_traits < GGML_TYPE_Q6_K > { 492struct ptrs { 493const uint8_t * ql ; 494const uint8_t * qh ; 495const int8_t * scales ; 496const sycl::half * d ; 497 }; 498 499static ESIMD_INLINE ptrs make_ptrs (const void * vx ,size_t nb ) { 500const uint8_t * ql = (const uint8_t * )vx ; 501const uint8_t * qh = ql + nb * (QK_K /2 ); 502const int8_t * scales = (const int8_t * ) (qh + nb * (QK_K /4 )); 503const sycl::half * d = (const sycl::half * ) (scales + nb * (QK_K /16 )); 504return {ql ,qh ,scales ,d }; 505 } 506 507static ESIMD_INLINE void mac_pair ( 508const ptrs & pa ,size_t bia , 509const ptrs & pb ,size_t bib ,bool has_b , 510 sycl::ext::intel::esimd::simd < float ,256 > & y_vec , 511 sycl::ext::intel::esimd::simd < float ,32 > & acc_a , 512 sycl::ext::intel::esimd::simd < float ,32 > & acc_b ) { 513using namespace sycl::ext::intel::esimd ; 514 515simd < uint8_t ,128 > ql_a = block_load < uint8_t ,128 > (pa .ql + bia * (QK_K /2 )); 516simd < uint8_t ,128 > ql_b = 0 ; 517simd < uint8_t ,64 > qh_a = block_load < uint8_t ,64 > (pa .qh + bia * (QK_K /4 )); 518simd < uint8_t ,64 > qh_b = 0 ; 519simd < int8_t ,16 > scales_a = block_load < int8_t ,16 > (pa .scales + bia * (QK_K /16 )); 520simd < int8_t ,16 > scales_b = 0 ; 521 522const float d_a = (float )pa .d [bia ]; 523float d_b = 0.0f ; 524if (has_b ) { 525ql_b = block_load < uint8_t ,128 > (pb .ql + bib * (QK_K /2 )); 526qh_b = block_load < uint8_t ,64 > (pb .qh + bib * (QK_K /4 )); 527scales_b = block_load < int8_t ,16 > (pb .scales + bib * (QK_K /16 )); 528d_b = (float )pb .d [bib ]; 529 } 530 531simd < float ,16 > sc_a = convert < float > (scales_a ); 532simd < float ,16 > sc_b = convert < float > (scales_b ); 533 534#pragma unroll 535for (int im = 0 ;im < 2 ;++ im ) { 536simd < uint8_t ,32 > ql_lo_a = ql_a .select < 32 ,1 > (64 * im ); 537simd < uint8_t ,32 > ql_hi_a = ql_a .select < 32 ,1 > (64 * im + 32 ); 538simd < uint8_t ,32 > qh_bits_a = qh_a .select < 32 ,1 > (32 * im ); 539simd < uint8_t ,32 > ql_lo_b = ql_b .select < 32 ,1 > (64 * im ); 540simd < uint8_t ,32 > ql_hi_b = ql_b .select < 32 ,1 > (64 * im + 32 ); 541simd < uint8_t ,32 > qh_bits_b = qh_b .select < 32 ,1 > (32 * im ); 542 543// reconstruct each 32-wide 6-bit group (matches dequantize_row_q6_K) 544#pragma unroll 545for (int g = 0 ;g < 4 ;++ g ) { 546simd < float ,32 > y_g = y_vec .select < 32 ,1 > (32 * (4 * im + g )); 547 548const float scale_a_lo = sc_a [8 * im + 2 * g + 0 ]* d_a ; 549const float scale_a_hi = sc_a [8 * im + 2 * g + 1 ]* d_a ; 550const float scale_b_lo = sc_b [8 * im + 2 * g + 0 ]* d_b ; 551const float scale_b_hi = sc_b [8 * im + 2 * g + 1 ]* d_b ; 552 553simd < float ,32 > scale_vec_a = splat_lo_hi (scale_a_lo ,scale_a_hi ); 554simd < float ,32 > scale_vec_b = splat_lo_hi (scale_b_lo ,scale_b_hi ); 555 556simd < uint8_t ,32 > qa ; 557simd < uint8_t ,32 > qb ; 558switch (g ) { 559case 0 : 560qa = (ql_lo_a & simd < uint8_t ,32 > (0x0F )) | ((qh_bits_a & simd < uint8_t ,32 > (0x03 )) <<simd < uint8_t ,32 > (4 )); 561qb = (ql_lo_b & simd < uint8_t ,32 > (0x0F )) | ((qh_bits_b & simd < uint8_t ,32 > (0x03 )) <<simd < uint8_t ,32 > (4 )); 562break ; 563case 1 : 564qa = (ql_hi_a & simd < uint8_t ,32 > (0x0F )) | ((qh_bits_a & simd < uint8_t ,32 > (0x0C )) <<simd < uint8_t ,32 > (2 )); 565qb = (ql_hi_b & simd < uint8_t ,32 > (0x0F )) | ((qh_bits_b & simd < uint8_t ,32 > (0x0C )) <<simd < uint8_t ,32 > (2 )); 566break ; 567case 2 : 568qa = (ql_lo_a >>simd < uint8_t ,32 > (4 )) | (qh_bits_a & simd < uint8_t ,32 > (0x30 )); 569qb = (ql_lo_b >>simd < uint8_t ,32 > (4 )) | (qh_bits_b & simd < uint8_t ,32 > (0x30 )); 570break ; 571default : 572qa = (ql_hi_a >>simd < uint8_t ,32 > (4 )) | ((qh_bits_a & simd < uint8_t ,32 > (0xC0 )) >>simd < uint8_t ,32 > (2 )); 573qb = (ql_hi_b >>simd < uint8_t ,32 > (4 )) | ((qh_bits_b & simd < uint8_t ,32 > (0xC0 )) >>simd < uint8_t ,32 > (2 )); 574break ; 575 } 576 577simd < float ,32 > deq_a = (convert < float > (qa )- 32.0f )* scale_vec_a ; 578simd < float ,32 > deq_b = (convert < float > (qb )- 32.0f )* scale_vec_b ; 579 580acc_a += y_g * deq_a ; 581acc_b += y_g * deq_b ; 582 } 583 } 584 } 585}; 586 587}// namespace ggml_sycl_esimd 588 589#endif // GGML_SYCL_ESIMD_HPP