41#if defined(__AVX512F__) || defined(__AVX2__) || defined(__AVX__) || defined(__SSE4_1__) || defined(__SSSE3__)
44#if defined(__ARM_NEON) || defined(__aarch64__)
54_Static_assert(
sizeof(block_q6_K_prepared) == 274,
55 "Q6_K prepared-size contract changed");
59 return sizeof(block_q6_K_prepared);
64#if defined(__AVX512F__) && defined(__AVX512BW__) && \
65 defined(__AVX512VNNI__)
66 return "q6_k_prepared_avx512_vnni_exact";
67#elif defined(__AVX2__)
68 return "q6_k_prepared_avx2_exact";
70 return "q6_k_prepared_unavailable";
76 if (!src || !dst || N <= 0 || K <= 0 || (K %
QK_K) != 0)
return;
78 block_q6_K_prepared *output = (block_q6_K_prepared *)dst;
79 const size_t blocks = (size_t)N * (
size_t)(K /
QK_K);
81 for (
size_t b = 0; b < blocks; ++b) {
82 output[b].
d = input[b].
d;
83 memcpy(output[b].scales, input[b].scales,
sizeof(output[b].scales));
84 for (
int n = 0; n <
QK_K; n += 128) {
85 const uint8_t *ql = input[b].
ql + n / 2;
86 const uint8_t *qh = input[b].
qh + n / 4;
87 for (
int l = 0; l < 32; ++l) {
88 output[b].qs[n + l + 0] =
89 (uint8_t)((ql[l] & 0x0f) | (((qh[l] >> 0) & 3) << 4));
90 output[b].qs[n + l + 32] =
91 (uint8_t)((ql[l + 32] & 0x0f) | (((qh[l] >> 2) & 3) << 4));
92 output[b].qs[n + l + 64] =
93 (uint8_t)((ql[l] >> 4) | (((qh[l] >> 4) & 3) << 4));
94 output[b].qs[n + l + 96] =
95 (uint8_t)((ql[l + 32] >> 4) | (((qh[l] >> 6) & 3) << 4));
110 static int cached = -1;
112 const char *env = getenv(
"CK_DEBUG_Q6K_Q8K_REF");
113 cached = (env && env[0] && env[0] !=
'0') ? 1 : 0;
139 const int nb = K /
QK_K;
141 float sums[8] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
143 for (
int i = 0; i < nb; ++i) {
146 const uint8_t *ql = w[i].
ql;
147 const uint8_t *qh = w[i].
qh;
148 const int8_t *sc = w[i].
scales;
149 const int8_t *q8 = x[i].
qs;
150 int32_t aux32[8] = {0, 0, 0, 0, 0, 0, 0, 0};
153 for (
int n = 0; n <
QK_K; n += 128) {
159 for (
int l = 0; l < 32; ++l) {
161 const int is = l / 16;
165 const int8_t q1 = (int8_t)((ql[l + 0] & 0xF) | (((qh[l] >> 0) & 3) << 4)) - 32;
167 const int8_t q2 = (int8_t)((ql[l + 32] & 0xF) | (((qh[l] >> 2) & 3) << 4)) - 32;
169 const int8_t q3 = (int8_t)((ql[l + 0] >> 4) | (((qh[l] >> 4) & 3) << 4)) - 32;
171 const int8_t q4 = (int8_t)((ql[l + 32] >> 4) | (((qh[l] >> 6) & 3) << 4)) - 32;
173 aux32[l & 7] += (int)sc[is + 0] * (
int)q1 * (int)q8[l + 0];
174 aux32[l & 7] += (int)sc[is + 2] * (
int)q2 * (int)q8[l + 32];
175 aux32[l & 7] += (int)sc[is + 4] * (
int)q3 * (int)q8[l + 64];
176 aux32[l & 7] += (int)sc[is + 6] * (
int)q4 * (int)q8[l + 96];
184 for (
int l = 0; l < 8; ++l) {
185 sums[l] += d * (float)aux32[l];
189 for (
int l = 0; l < 8; ++l) {
195#if defined(__ARM_NEON) || defined(__aarch64__)
196static float dot_q6_k_q8_k_neon(
const block_q6_K *w,
200 const int nb = K /
QK_K;
203 for (
int i = 0; i < nb; ++i) {
206 const uint8_t *ql = w[i].
ql;
207 const uint8_t *qh = w[i].
qh;
208 const int8_t *sc = w[i].
scales;
209 const int8_t *q8 = x[i].
qs;
214 for (
int n = 0; n <
QK_K; n += 128) {
215 for (
int l = 0; l < 32; ++l) {
216 const int is = l / 16;
218 const int8_t q1 = (int8_t)((ql[l + 0] & 0xF) | (((qh[l] >> 0) & 3) << 4)) - 32;
219 const int8_t q2 = (int8_t)((ql[l + 32] & 0xF) | (((qh[l] >> 2) & 3) << 4)) - 32;
220 const int8_t q3 = (int8_t)((ql[l + 0] >> 4) | (((qh[l] >> 4) & 3) << 4)) - 32;
221 const int8_t q4 = (int8_t)((ql[l + 32] >> 4) | (((qh[l] >> 6) & 3) << 4)) - 32;
224 wvals[base + l + 0] = q1;
225 wvals[base + l + 32] = q2;
226 wvals[base + l + 64] = q3;
227 wvals[base + l + 96] = q4;
229 svals[base + l + 0] = sc[is + 0];
230 svals[base + l + 32] = sc[is + 2];
231 svals[base + l + 64] = sc[is + 4];
232 svals[base + l + 96] = sc[is + 6];
240 int32x4_t acc = vdupq_n_s32(0);
241 for (
int j = 0; j <
QK_K; j += 16) {
242 const int8x16_t wv = vld1q_s8(&wvals[j]);
243 const int8x16_t sv = vld1q_s8(&svals[j]);
244 const int8x16_t xv = vld1q_s8(&q8[j]);
246 const int16x8_t ws0 = vmull_s8(vget_low_s8(wv), vget_low_s8(sv));
247 const int16x8_t ws1 = vmull_s8(vget_high_s8(wv), vget_high_s8(sv));
248 const int16x8_t x0 = vmovl_s8(vget_low_s8(xv));
249 const int16x8_t x1 = vmovl_s8(vget_high_s8(xv));
251 int32x4_t p0 = vmull_s16(vget_low_s16(ws0), vget_low_s16(x0));
252 p0 = vmlal_s16(p0, vget_high_s16(ws0), vget_high_s16(x0));
254 int32x4_t p1 = vmull_s16(vget_low_s16(ws1), vget_low_s16(x1));
255 p1 = vmlal_s16(p1, vget_high_s16(ws1), vget_high_s16(x1));
257 acc = vaddq_s32(acc, p0);
258 acc = vaddq_s32(acc, p1);
262 vst1q_s32(lanes, acc);
263 sumf += d * (float)(lanes[0] + lanes[1] + lanes[2] + lanes[3]);
269static void gemv_q6_k_q8_k_neon(
float *y,
276 const int blocks_per_row = K /
QK_K;
278 for (
int row = 0; row < M; ++row) {
279 const block_q6_K *w_row = blocks + (size_t)row * (
size_t)blocks_per_row;
280 y[row] = dot_q6_k_q8_k_neon(w_row, x, K);
290 if (!y || !W || !x_q8 || M <= 0 || K <= 0) {
296 const int blocks_per_row = K /
QK_K;
298 for (
int row = 0; row < M; ++row) {
299 const block_q6_K *w_row = blocks + (size_t)row * (
size_t)blocks_per_row;
311#if defined(__SSSE3__)
314static const int8_t q6k_scale_shuffle[8][16] = {
315 { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
316 { 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 },
317 { 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5 },
318 { 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7 },
319 { 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9 },
320 {10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11 },
321 {12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13 },
322 {14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15 },
325static float dot_q6_k_q8_k_sse(
const block_q6_K *w,
329 const int nb = K /
QK_K;
330 const __m128i m3 = _mm_set1_epi8(3);
331 const __m128i m15 = _mm_set1_epi8(15);
333 __m128 acc = _mm_setzero_ps();
335 for (
int i = 0; i < nb; ++i) {
338 const uint8_t *ql = w[i].
ql;
339 const uint8_t *qh = w[i].
qh;
340 const int8_t *q8 = x[i].
qs;
343 const __m128i scales = _mm_loadu_si128((
const __m128i *)w[i].scales);
344 const __m128i q8sums_0 = _mm_loadu_si128((
const __m128i *)x[i].bsums);
345 const __m128i q8sums_1 = _mm_loadu_si128((
const __m128i *)x[i].bsums + 1);
348 const __m128i scales_16_0 = _mm_cvtepi8_epi16(scales);
349 const __m128i scales_16_1 = _mm_cvtepi8_epi16(_mm_bsrli_si128(scales, 8));
350 const __m128i q8sclsub_0 = _mm_slli_epi32(_mm_madd_epi16(q8sums_0, scales_16_0), 5);
351 const __m128i q8sclsub_1 = _mm_slli_epi32(_mm_madd_epi16(q8sums_1, scales_16_1), 5);
353 __m128i sumi_0 = _mm_setzero_si128();
354 __m128i sumi_1 = _mm_setzero_si128();
359 for (
int j = 0; j <
QK_K / 128; ++j) {
361 const __m128i q4bitsH_0 = _mm_loadu_si128((
const __m128i *)qh);
363 const __m128i q4bitsH_1 = _mm_loadu_si128((
const __m128i *)qh);
367 const __m128i q4h_0 = _mm_slli_epi16(_mm_and_si128(q4bitsH_0, m3), 4);
368 const __m128i q4h_1 = _mm_slli_epi16(_mm_and_si128(q4bitsH_1, m3), 4);
369 const __m128i q4h_2 = _mm_slli_epi16(_mm_and_si128(q4bitsH_0, _mm_set1_epi8(12)), 2);
370 const __m128i q4h_3 = _mm_slli_epi16(_mm_and_si128(q4bitsH_1, _mm_set1_epi8(12)), 2);
371 const __m128i q4h_4 = _mm_and_si128(q4bitsH_0, _mm_set1_epi8(48));
372 const __m128i q4h_5 = _mm_and_si128(q4bitsH_1, _mm_set1_epi8(48));
373 const __m128i q4h_6 = _mm_srli_epi16(_mm_and_si128(q4bitsH_0, _mm_set1_epi8(-64)), 2);
374 const __m128i q4h_7 = _mm_srli_epi16(_mm_and_si128(q4bitsH_1, _mm_set1_epi8(-64)), 2);
377 const __m128i q4bits1_0 = _mm_loadu_si128((
const __m128i *)ql);
379 const __m128i q4bits1_1 = _mm_loadu_si128((
const __m128i *)ql);
381 const __m128i q4bits2_0 = _mm_loadu_si128((
const __m128i *)ql);
383 const __m128i q4bits2_1 = _mm_loadu_si128((
const __m128i *)ql);
387 const __m128i q4_0 = _mm_or_si128(_mm_and_si128(q4bits1_0, m15), q4h_0);
388 const __m128i q4_1 = _mm_or_si128(_mm_and_si128(q4bits1_1, m15), q4h_1);
389 const __m128i q4_2 = _mm_or_si128(_mm_and_si128(q4bits2_0, m15), q4h_2);
390 const __m128i q4_3 = _mm_or_si128(_mm_and_si128(q4bits2_1, m15), q4h_3);
391 const __m128i q4_4 = _mm_or_si128(_mm_and_si128(_mm_srli_epi16(q4bits1_0, 4), m15), q4h_4);
392 const __m128i q4_5 = _mm_or_si128(_mm_and_si128(_mm_srli_epi16(q4bits1_1, 4), m15), q4h_5);
393 const __m128i q4_6 = _mm_or_si128(_mm_and_si128(_mm_srli_epi16(q4bits2_0, 4), m15), q4h_6);
394 const __m128i q4_7 = _mm_or_si128(_mm_and_si128(_mm_srli_epi16(q4bits2_1, 4), m15), q4h_7);
397 const __m128i q8_0 = _mm_loadu_si128((
const __m128i *)q8);
399 const __m128i q8_1 = _mm_loadu_si128((
const __m128i *)q8);
401 const __m128i q8_2 = _mm_loadu_si128((
const __m128i *)q8);
403 const __m128i q8_3 = _mm_loadu_si128((
const __m128i *)q8);
405 const __m128i q8_4 = _mm_loadu_si128((
const __m128i *)q8);
407 const __m128i q8_5 = _mm_loadu_si128((
const __m128i *)q8);
409 const __m128i q8_6 = _mm_loadu_si128((
const __m128i *)q8);
411 const __m128i q8_7 = _mm_loadu_si128((
const __m128i *)q8);
415 __m128i p16_0 = _mm_maddubs_epi16(q4_0, q8_0);
416 __m128i p16_1 = _mm_maddubs_epi16(q4_1, q8_1);
417 __m128i p16_2 = _mm_maddubs_epi16(q4_2, q8_2);
418 __m128i p16_3 = _mm_maddubs_epi16(q4_3, q8_3);
419 __m128i p16_4 = _mm_maddubs_epi16(q4_4, q8_4);
420 __m128i p16_5 = _mm_maddubs_epi16(q4_5, q8_5);
421 __m128i p16_6 = _mm_maddubs_epi16(q4_6, q8_6);
422 __m128i p16_7 = _mm_maddubs_epi16(q4_7, q8_7);
425 const __m128i scale_0 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)q6k_scale_shuffle[is + 0]));
426 const __m128i scale_1 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)q6k_scale_shuffle[is + 1]));
427 const __m128i scale_2 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)q6k_scale_shuffle[is + 2]));
428 const __m128i scale_3 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)q6k_scale_shuffle[is + 3]));
432 p16_0 = _mm_madd_epi16(_mm_cvtepi8_epi16(scale_0), p16_0);
433 p16_1 = _mm_madd_epi16(_mm_cvtepi8_epi16(_mm_bsrli_si128(scale_0, 8)), p16_1);
434 p16_2 = _mm_madd_epi16(_mm_cvtepi8_epi16(scale_1), p16_2);
435 p16_3 = _mm_madd_epi16(_mm_cvtepi8_epi16(_mm_bsrli_si128(scale_1, 8)), p16_3);
436 p16_4 = _mm_madd_epi16(_mm_cvtepi8_epi16(scale_2), p16_4);
437 p16_5 = _mm_madd_epi16(_mm_cvtepi8_epi16(_mm_bsrli_si128(scale_2, 8)), p16_5);
438 p16_6 = _mm_madd_epi16(_mm_cvtepi8_epi16(scale_3), p16_6);
439 p16_7 = _mm_madd_epi16(_mm_cvtepi8_epi16(_mm_bsrli_si128(scale_3, 8)), p16_7);
442 sumi_0 = _mm_add_epi32(sumi_0, _mm_add_epi32(p16_0, p16_2));
443 sumi_1 = _mm_add_epi32(sumi_1, _mm_add_epi32(p16_1, p16_3));
444 sumi_0 = _mm_add_epi32(sumi_0, _mm_add_epi32(p16_4, p16_6));
445 sumi_1 = _mm_add_epi32(sumi_1, _mm_add_epi32(p16_5, p16_7));
449 sumi_0 = _mm_sub_epi32(sumi_0, q8sclsub_0);
450 sumi_1 = _mm_sub_epi32(sumi_1, q8sclsub_1);
453 __m128i sumi = _mm_add_epi32(sumi_0, sumi_1);
454 __m128 sumf_vec = _mm_mul_ps(_mm_set1_ps(d), _mm_cvtepi32_ps(sumi));
457 sumf_vec = _mm_hadd_ps(sumf_vec, sumf_vec);
458 sumf_vec = _mm_hadd_ps(sumf_vec, sumf_vec);
459 acc = _mm_add_ss(acc, sumf_vec);
462 return _mm_cvtss_f32(acc);
470 if (!y || !W || !x_q8 || M <= 0 || K <= 0) {
476 const int blocks_per_row = K /
QK_K;
478 for (
int row = 0; row < M; ++row) {
479 const block_q6_K *w_row = blocks + (size_t)row * (
size_t)blocks_per_row;
480 y[row] = dot_q6_k_q8_k_sse(w_row, x, K);
492#if defined(__AVX__) && !defined(__AVX2__)
494static float dot_q6_k_q8_k_avx(
const block_q6_K *w,
498 const int nb = K /
QK_K;
499 const __m128i m3 = _mm_set1_epi8(3);
500 const __m128i m15 = _mm_set1_epi8(15);
502 __m128 acc = _mm_setzero_ps();
504 for (
int i = 0; i < nb; ++i) {
507 const uint8_t *ql = w[i].
ql;
508 const uint8_t *qh = w[i].
qh;
509 const int8_t *q8 = x[i].
qs;
513 _mm_prefetch((
const char *)&w[i + 1], _MM_HINT_T0);
514 _mm_prefetch((
const char *)&x[i + 1], _MM_HINT_T0);
518 const __m128i scales = _mm_loadu_si128((
const __m128i *)w[i].scales);
519 const __m128i q8sums_0 = _mm_loadu_si128((
const __m128i *)x[i].bsums);
520 const __m128i q8sums_1 = _mm_loadu_si128((
const __m128i *)x[i].bsums + 1);
523 const __m128i scales_16_0 = _mm_cvtepi8_epi16(scales);
524 const __m128i scales_16_1 = _mm_cvtepi8_epi16(_mm_bsrli_si128(scales, 8));
525 const __m128i q8sclsub_0 = _mm_slli_epi32(_mm_madd_epi16(q8sums_0, scales_16_0), 5);
526 const __m128i q8sclsub_1 = _mm_slli_epi32(_mm_madd_epi16(q8sums_1, scales_16_1), 5);
528 __m128i sumi_0 = _mm_setzero_si128();
529 __m128i sumi_1 = _mm_setzero_si128();
534 for (
int j = 0; j <
QK_K / 128; ++j) {
536 const __m128i q4bitsH_0 = _mm_loadu_si128((
const __m128i *)qh);
538 const __m128i q4bitsH_1 = _mm_loadu_si128((
const __m128i *)qh);
542 const __m128i q4h_0 = _mm_slli_epi16(_mm_and_si128(q4bitsH_0, m3), 4);
543 const __m128i q4h_1 = _mm_slli_epi16(_mm_and_si128(q4bitsH_1, m3), 4);
544 const __m128i q4h_2 = _mm_slli_epi16(_mm_and_si128(q4bitsH_0, _mm_set1_epi8(12)), 2);
545 const __m128i q4h_3 = _mm_slli_epi16(_mm_and_si128(q4bitsH_1, _mm_set1_epi8(12)), 2);
546 const __m128i q4h_4 = _mm_and_si128(q4bitsH_0, _mm_set1_epi8(48));
547 const __m128i q4h_5 = _mm_and_si128(q4bitsH_1, _mm_set1_epi8(48));
548 const __m128i q4h_6 = _mm_srli_epi16(_mm_and_si128(q4bitsH_0, _mm_set1_epi8(-64)), 2);
549 const __m128i q4h_7 = _mm_srli_epi16(_mm_and_si128(q4bitsH_1, _mm_set1_epi8(-64)), 2);
552 const __m128i q4bits1_0 = _mm_loadu_si128((
const __m128i *)ql);
554 const __m128i q4bits1_1 = _mm_loadu_si128((
const __m128i *)ql);
556 const __m128i q4bits2_0 = _mm_loadu_si128((
const __m128i *)ql);
558 const __m128i q4bits2_1 = _mm_loadu_si128((
const __m128i *)ql);
562 const __m128i q4_0 = _mm_or_si128(_mm_and_si128(q4bits1_0, m15), q4h_0);
563 const __m128i q4_1 = _mm_or_si128(_mm_and_si128(q4bits1_1, m15), q4h_1);
564 const __m128i q4_2 = _mm_or_si128(_mm_and_si128(q4bits2_0, m15), q4h_2);
565 const __m128i q4_3 = _mm_or_si128(_mm_and_si128(q4bits2_1, m15), q4h_3);
566 const __m128i q4_4 = _mm_or_si128(_mm_and_si128(_mm_srli_epi16(q4bits1_0, 4), m15), q4h_4);
567 const __m128i q4_5 = _mm_or_si128(_mm_and_si128(_mm_srli_epi16(q4bits1_1, 4), m15), q4h_5);
568 const __m128i q4_6 = _mm_or_si128(_mm_and_si128(_mm_srli_epi16(q4bits2_0, 4), m15), q4h_6);
569 const __m128i q4_7 = _mm_or_si128(_mm_and_si128(_mm_srli_epi16(q4bits2_1, 4), m15), q4h_7);
572 const __m128i q8_0 = _mm_loadu_si128((
const __m128i *)q8);
574 const __m128i q8_1 = _mm_loadu_si128((
const __m128i *)q8);
576 const __m128i q8_2 = _mm_loadu_si128((
const __m128i *)q8);
578 const __m128i q8_3 = _mm_loadu_si128((
const __m128i *)q8);
580 const __m128i q8_4 = _mm_loadu_si128((
const __m128i *)q8);
582 const __m128i q8_5 = _mm_loadu_si128((
const __m128i *)q8);
584 const __m128i q8_6 = _mm_loadu_si128((
const __m128i *)q8);
586 const __m128i q8_7 = _mm_loadu_si128((
const __m128i *)q8);
590 __m128i p16_0 = _mm_maddubs_epi16(q4_0, q8_0);
591 __m128i p16_1 = _mm_maddubs_epi16(q4_1, q8_1);
592 __m128i p16_2 = _mm_maddubs_epi16(q4_2, q8_2);
593 __m128i p16_3 = _mm_maddubs_epi16(q4_3, q8_3);
594 __m128i p16_4 = _mm_maddubs_epi16(q4_4, q8_4);
595 __m128i p16_5 = _mm_maddubs_epi16(q4_5, q8_5);
596 __m128i p16_6 = _mm_maddubs_epi16(q4_6, q8_6);
597 __m128i p16_7 = _mm_maddubs_epi16(q4_7, q8_7);
600 const __m128i scale_0 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)q6k_scale_shuffle[is + 0]));
601 const __m128i scale_1 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)q6k_scale_shuffle[is + 1]));
602 const __m128i scale_2 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)q6k_scale_shuffle[is + 2]));
603 const __m128i scale_3 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)q6k_scale_shuffle[is + 3]));
607 p16_0 = _mm_madd_epi16(_mm_cvtepi8_epi16(scale_0), p16_0);
608 p16_1 = _mm_madd_epi16(_mm_cvtepi8_epi16(_mm_bsrli_si128(scale_0, 8)), p16_1);
609 p16_2 = _mm_madd_epi16(_mm_cvtepi8_epi16(scale_1), p16_2);
610 p16_3 = _mm_madd_epi16(_mm_cvtepi8_epi16(_mm_bsrli_si128(scale_1, 8)), p16_3);
611 p16_4 = _mm_madd_epi16(_mm_cvtepi8_epi16(scale_2), p16_4);
612 p16_5 = _mm_madd_epi16(_mm_cvtepi8_epi16(_mm_bsrli_si128(scale_2, 8)), p16_5);
613 p16_6 = _mm_madd_epi16(_mm_cvtepi8_epi16(scale_3), p16_6);
614 p16_7 = _mm_madd_epi16(_mm_cvtepi8_epi16(_mm_bsrli_si128(scale_3, 8)), p16_7);
617 sumi_0 = _mm_add_epi32(sumi_0, _mm_add_epi32(p16_0, p16_2));
618 sumi_1 = _mm_add_epi32(sumi_1, _mm_add_epi32(p16_1, p16_3));
619 sumi_0 = _mm_add_epi32(sumi_0, _mm_add_epi32(p16_4, p16_6));
620 sumi_1 = _mm_add_epi32(sumi_1, _mm_add_epi32(p16_5, p16_7));
624 sumi_0 = _mm_sub_epi32(sumi_0, q8sclsub_0);
625 sumi_1 = _mm_sub_epi32(sumi_1, q8sclsub_1);
628 __m128i sumi = _mm_add_epi32(sumi_0, sumi_1);
629 __m128 sumf_vec = _mm_mul_ps(_mm_set1_ps(d), _mm_cvtepi32_ps(sumi));
632 sumf_vec = _mm_hadd_ps(sumf_vec, sumf_vec);
633 sumf_vec = _mm_hadd_ps(sumf_vec, sumf_vec);
634 acc = _mm_add_ss(acc, sumf_vec);
637 return _mm_cvtss_f32(acc);
645 if (!y || !W || !x_q8 || M <= 0 || K <= 0) {
651 const int blocks_per_row = K /
QK_K;
653 for (
int row = 0; row < M; ++row) {
654 const block_q6_K *w_row = blocks + (size_t)row * (
size_t)blocks_per_row;
655 y[row] = dot_q6_k_q8_k_avx(w_row, x, K);
670static inline float ck_q6k_hsum_float_8(
const __m256 x)
672 __m128 res = _mm256_extractf128_ps(x, 1);
673 res = _mm_add_ps(res, _mm256_castps256_ps128(x));
674 res = _mm_add_ps(res, _mm_movehl_ps(res, res));
675 res = _mm_add_ss(res, _mm_movehdup_ps(res));
676 return _mm_cvtss_f32(res);
692static inline __m128i get_scale_shuffle_avx2(
int i) {
693 static const uint8_t patterns[8][16] = {
694 { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
695 { 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 },
696 { 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5 },
697 { 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7 },
698 { 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9 },
699 {10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11 },
700 {12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13 },
701 {14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15 },
703 return _mm_loadu_si128((
const __m128i *)patterns[i]);
706static float dot_q6_k_q8_k_avx2(
const block_q6_K *w,
710 const int nb = K /
QK_K;
711 const __m256i m3 = _mm256_set1_epi8(3);
712 const __m256i m15 = _mm256_set1_epi8(15);
714 __m256 acc = _mm256_setzero_ps();
716 for (
int i = 0; i < nb; ++i) {
719 const uint8_t *q4 = w[i].
ql;
720 const uint8_t *qh = w[i].
qh;
721 const int8_t *q8 = x[i].
qs;
723 const __m256i q8sums = _mm256_loadu_si256((
const __m256i *)x[i].bsums);
724 const __m128i scales = _mm_loadu_si128((
const __m128i *)w[i].scales);
725 const __m256i scales_16 = _mm256_cvtepi8_epi16(scales);
726 const __m256i q8sclsub = _mm256_slli_epi32(
727 _mm256_madd_epi16(q8sums, scales_16), 5);
729 __m256i sumi = _mm256_setzero_si256();
732 for (
int j = 0; j <
QK_K / 128; ++j) {
733 const __m256i q4bits1 = _mm256_loadu_si256((
const __m256i *)q4);
735 const __m256i q4bits2 = _mm256_loadu_si256((
const __m256i *)q4);
737 const __m256i q4bitsH = _mm256_loadu_si256((
const __m256i *)qh);
740 const __m256i q4h_0 = _mm256_slli_epi16(_mm256_and_si256(q4bitsH, m3), 4);
741 const __m256i q4h_1 = _mm256_slli_epi16(
742 _mm256_and_si256(q4bitsH, _mm256_set1_epi8(12)), 2);
743 const __m256i q4h_2 = _mm256_and_si256(q4bitsH, _mm256_set1_epi8(48));
744 const __m256i q4h_3 = _mm256_srli_epi16(
745 _mm256_and_si256(q4bitsH, _mm256_set1_epi8(-64)), 2);
747 const __m256i q4_0 = _mm256_or_si256(_mm256_and_si256(q4bits1, m15), q4h_0);
748 const __m256i q4_1 = _mm256_or_si256(_mm256_and_si256(q4bits2, m15), q4h_1);
749 const __m256i q4_2 = _mm256_or_si256(
750 _mm256_and_si256(_mm256_srli_epi16(q4bits1, 4), m15), q4h_2);
751 const __m256i q4_3 = _mm256_or_si256(
752 _mm256_and_si256(_mm256_srli_epi16(q4bits2, 4), m15), q4h_3);
754 const __m256i q8_0 = _mm256_loadu_si256((
const __m256i *)q8);
756 const __m256i q8_1 = _mm256_loadu_si256((
const __m256i *)q8);
758 const __m256i q8_2 = _mm256_loadu_si256((
const __m256i *)q8);
760 const __m256i q8_3 = _mm256_loadu_si256((
const __m256i *)q8);
763 __m256i p16_0 = _mm256_maddubs_epi16(q4_0, q8_0);
764 __m256i p16_1 = _mm256_maddubs_epi16(q4_1, q8_1);
765 __m256i p16_2 = _mm256_maddubs_epi16(q4_2, q8_2);
766 __m256i p16_3 = _mm256_maddubs_epi16(q4_3, q8_3);
768 const __m128i scale_0 = _mm_shuffle_epi8(
769 scales, get_scale_shuffle_avx2(is + 0));
770 const __m128i scale_1 = _mm_shuffle_epi8(
771 scales, get_scale_shuffle_avx2(is + 1));
772 const __m128i scale_2 = _mm_shuffle_epi8(
773 scales, get_scale_shuffle_avx2(is + 2));
774 const __m128i scale_3 = _mm_shuffle_epi8(
775 scales, get_scale_shuffle_avx2(is + 3));
778 p16_0 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_0), p16_0);
779 p16_1 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_1), p16_1);
780 p16_2 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_2), p16_2);
781 p16_3 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_3), p16_3);
783 sumi = _mm256_add_epi32(sumi, _mm256_add_epi32(p16_0, p16_1));
784 sumi = _mm256_add_epi32(sumi, _mm256_add_epi32(p16_2, p16_3));
787 sumi = _mm256_sub_epi32(sumi, q8sclsub);
788 acc = _mm256_fmadd_ps(_mm256_broadcast_ss(&d), _mm256_cvtepi32_ps(sumi), acc);
791 return ck_q6k_hsum_float_8(acc);
803static void dot_q6_k_q8_k_avx2_m4(
const block_q6_K *w,
810 const int nb = K /
QK_K;
811 const __m256i m3 = _mm256_set1_epi8(3);
812 const __m256i m15 = _mm256_set1_epi8(15);
814 _mm256_setzero_ps(), _mm256_setzero_ps(),
815 _mm256_setzero_ps(), _mm256_setzero_ps()
818 for (
int i = 0; i < nb; ++i) {
819 const uint8_t *q4 = w[i].
ql;
820 const uint8_t *qh = w[i].
qh;
821 const __m128i scales = _mm_loadu_si128((
const __m128i *)w[i].scales);
822 const __m256i scales_16 = _mm256_cvtepi8_epi16(scales);
825 _mm256_setzero_si256(), _mm256_setzero_si256(),
826 _mm256_setzero_si256(), _mm256_setzero_si256()
830 for (
int j = 0; j <
QK_K / 128; ++j) {
831 const __m256i q4bits1 = _mm256_loadu_si256((
const __m256i *)q4);
833 const __m256i q4bits2 = _mm256_loadu_si256((
const __m256i *)q4);
835 const __m256i q4bitsH = _mm256_loadu_si256((
const __m256i *)qh);
838 const __m256i q4h_0 = _mm256_slli_epi16(_mm256_and_si256(q4bitsH, m3), 4);
839 const __m256i q4h_1 = _mm256_slli_epi16(
840 _mm256_and_si256(q4bitsH, _mm256_set1_epi8(12)), 2);
841 const __m256i q4h_2 = _mm256_and_si256(q4bitsH, _mm256_set1_epi8(48));
842 const __m256i q4h_3 = _mm256_srli_epi16(
843 _mm256_and_si256(q4bitsH, _mm256_set1_epi8(-64)), 2);
845 const __m256i q6_0 = _mm256_or_si256(_mm256_and_si256(q4bits1, m15), q4h_0);
846 const __m256i q6_1 = _mm256_or_si256(_mm256_and_si256(q4bits2, m15), q4h_1);
847 const __m256i q6_2 = _mm256_or_si256(
848 _mm256_and_si256(_mm256_srli_epi16(q4bits1, 4), m15), q4h_2);
849 const __m256i q6_3 = _mm256_or_si256(
850 _mm256_and_si256(_mm256_srli_epi16(q4bits2, 4), m15), q4h_3);
852 const __m128i scale_0 = _mm_shuffle_epi8(
853 scales, get_scale_shuffle_avx2(is + 0));
854 const __m128i scale_1 = _mm_shuffle_epi8(
855 scales, get_scale_shuffle_avx2(is + 1));
856 const __m128i scale_2 = _mm_shuffle_epi8(
857 scales, get_scale_shuffle_avx2(is + 2));
858 const __m128i scale_3 = _mm_shuffle_epi8(
859 scales, get_scale_shuffle_avx2(is + 3));
861 const __m256i scale16_0 = _mm256_cvtepi8_epi16(scale_0);
862 const __m256i scale16_1 = _mm256_cvtepi8_epi16(scale_1);
863 const __m256i scale16_2 = _mm256_cvtepi8_epi16(scale_2);
864 const __m256i scale16_3 = _mm256_cvtepi8_epi16(scale_3);
866 for (
int r = 0; r < rows; ++r) {
867 const block_q8_K *xb = x + (size_t)r * (
size_t)x_row_blocks + i;
868 const int8_t *q8 = xb->
qs + j * 128;
869 const __m256i q8_0 = _mm256_loadu_si256((
const __m256i *)(q8 + 0));
870 const __m256i q8_1 = _mm256_loadu_si256((
const __m256i *)(q8 + 32));
871 const __m256i q8_2 = _mm256_loadu_si256((
const __m256i *)(q8 + 64));
872 const __m256i q8_3 = _mm256_loadu_si256((
const __m256i *)(q8 + 96));
874 __m256i p16_0 = _mm256_maddubs_epi16(q6_0, q8_0);
875 __m256i p16_1 = _mm256_maddubs_epi16(q6_1, q8_1);
876 __m256i p16_2 = _mm256_maddubs_epi16(q6_2, q8_2);
877 __m256i p16_3 = _mm256_maddubs_epi16(q6_3, q8_3);
878 p16_0 = _mm256_madd_epi16(scale16_0, p16_0);
879 p16_1 = _mm256_madd_epi16(scale16_1, p16_1);
880 p16_2 = _mm256_madd_epi16(scale16_2, p16_2);
881 p16_3 = _mm256_madd_epi16(scale16_3, p16_3);
883 sumi[r] = _mm256_add_epi32(
884 sumi[r], _mm256_add_epi32(p16_0, p16_1));
885 sumi[r] = _mm256_add_epi32(
886 sumi[r], _mm256_add_epi32(p16_2, p16_3));
890 for (
int r = 0; r < rows; ++r) {
891 const block_q8_K *xb = x + (size_t)r * (
size_t)x_row_blocks + i;
892 const __m256i q8sums =
893 _mm256_loadu_si256((
const __m256i *)xb->
bsums);
894 const __m256i q8sclsub = _mm256_slli_epi32(
895 _mm256_madd_epi16(q8sums, scales_16), 5);
896 sumi[r] = _mm256_sub_epi32(sumi[r], q8sclsub);
897 const float d = wd * xb->
d;
898 acc[r] = _mm256_fmadd_ps(
899 _mm256_broadcast_ss(&d), _mm256_cvtepi32_ps(sumi[r]), acc[r]);
903 for (
int r = 0; r < rows; ++r) {
904 out[r] = ck_q6k_hsum_float_8(acc[r]);
908static float dot_q6_k_prepared_q8_k_avx2(
909 const block_q6_K_prepared *w,
const block_q8_K *x,
int K)
911 const int nb = K /
QK_K;
912 __m256 acc = _mm256_setzero_ps();
914 for (
int i = 0; i < nb; ++i) {
915 const __m128i scales =
916 _mm_loadu_si128((
const __m128i *)(
const void *)w[i].scales);
917 const __m256i scales_16 = _mm256_cvtepi8_epi16(scales);
918 const __m256i q8sums =
919 _mm256_loadu_si256((
const __m256i *)(
const void *)x[i].bsums);
920 const __m256i q8sclsub = _mm256_slli_epi32(
921 _mm256_madd_epi16(q8sums, scales_16), 5);
922 __m256i sumi = _mm256_setzero_si256();
924 for (
int j = 0; j < 2; ++j) {
926 for (
int lane = 0; lane < 4; ++lane) {
927 const int group = j * 4 + lane;
928 const __m256i q6 = _mm256_loadu_si256(
929 (
const __m256i *)(
const void *)(w[i].qs + group * 32));
930 const __m256i q8 = _mm256_loadu_si256(
931 (
const __m256i *)(
const void *)(x[i].qs + group * 32));
932 p16[lane] = _mm256_maddubs_epi16(q6, q8);
933 const __m128i scale = _mm_shuffle_epi8(
934 scales, get_scale_shuffle_avx2(group));
935 p16[lane] = _mm256_madd_epi16(
936 _mm256_cvtepi8_epi16(scale), p16[lane]);
938 sumi = _mm256_add_epi32(
939 sumi, _mm256_add_epi32(p16[0], p16[1]));
940 sumi = _mm256_add_epi32(
941 sumi, _mm256_add_epi32(p16[2], p16[3]));
944 sumi = _mm256_sub_epi32(sumi, q8sclsub);
946 acc = _mm256_fmadd_ps(
947 _mm256_broadcast_ss(&d), _mm256_cvtepi32_ps(sumi), acc);
950 return ck_q6k_hsum_float_8(acc);
953#if defined(__AVX512F__) && defined(__AVX512BW__) && \
954 defined(__AVX512VNNI__)
961static float dot_q6_k_prepared_q8_k_avx512_vnni(
962 const block_q6_K_prepared *w,
const block_q8_K *x,
int K)
964 const int nb = K /
QK_K;
965 const __m512i scale_indices = _mm512_setr_epi32(
966 0, 0, 0, 0, 1, 1, 1, 1,
967 2, 2, 2, 2, 3, 3, 3, 3);
968 __m256 acc = _mm256_setzero_ps();
970 for (
int i = 0; i < nb; ++i) {
971 const __m128i scales =
972 _mm_loadu_si128((
const __m128i *)(
const void *)w[i].scales);
973 const __m512i scales_32 = _mm512_cvtepi8_epi32(scales);
974 const __m256i scales_16 = _mm256_cvtepi8_epi16(scales);
975 const __m256i q8sums =
976 _mm256_loadu_si256((
const __m256i *)(
const void *)x[i].bsums);
977 const __m256i q8sclsub = _mm256_slli_epi32(
978 _mm256_madd_epi16(q8sums, scales_16), 5);
979 __m256i sumi = _mm256_setzero_si256();
981 for (
int chunk = 0; chunk < 4; ++chunk) {
982 const __m512i q6 = _mm512_loadu_si512(
983 (
const void *)(w[i].qs + chunk * 64));
984 const __m512i q8 = _mm512_loadu_si512(
985 (
const void *)(x[i].qs + chunk * 64));
986 const __m512i products = _mm512_dpbusd_epi32(
987 _mm512_setzero_si512(), q6, q8);
988 const __m512i indices = _mm512_add_epi32(
989 scale_indices, _mm512_set1_epi32(chunk * 4));
990 const __m512i scaled = _mm512_mullo_epi32(
991 products, _mm512_permutexvar_epi32(indices, scales_32));
992 const __m512i upper_half = _mm512_shuffle_i32x4(
993 scaled, scaled, _MM_SHUFFLE(3, 2, 3, 2));
994 const __m256i pair_sum = _mm256_add_epi32(
995 _mm512_castsi512_si256(scaled),
996 _mm512_castsi512_si256(upper_half));
997 sumi = _mm256_add_epi32(sumi, pair_sum);
1000 sumi = _mm256_sub_epi32(sumi, q8sclsub);
1002 acc = _mm256_fmadd_ps(
1003 _mm256_broadcast_ss(&d), _mm256_cvtepi32_ps(sumi), acc);
1006 return ck_q6k_hsum_float_8(acc);
1015 if (!y || !W || !x_q8 || M <= 0 || K <= 0) {
1021 const int blocks_per_row = K /
QK_K;
1023 for (
int row = 0; row < M; ++row) {
1024 const block_q6_K *w_row = blocks + (size_t)row * (
size_t)blocks_per_row;
1025 y[row] = dot_q6_k_q8_k_avx2(w_row, x, K);
1037#if defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512VBMI__)
1044static float dot_q6_k_q8_k_avx512_vbmi(
const block_q6_K *w,
1048 const int nb = K /
QK_K;
1049 const __m512i m4 = _mm512_set1_epi8(0xF);
1050 const __m512i m2 = _mm512_set1_epi8(3);
1051 const __m512i m32s = _mm512_set1_epi8(32);
1053 __m512 acc = _mm512_setzero_ps();
1055 for (
int i = 0; i < nb; ++i) {
1058 const uint8_t *ql = w[i].
ql;
1059 const uint8_t *qh = w[i].
qh;
1060 const int8_t *q8 = x[i].
qs;
1061 const int8_t *sc = w[i].
scales;
1063 __m512i sumi = _mm512_setzero_si512();
1067 const __m512i q4bits1 = _mm512_loadu_si512((
const __m512i *)ql);
1068 const __m512i q4bits2 = _mm512_loadu_si512((
const __m512i *)(ql + 64));
1071 const __m512i q4bitsH = _mm512_loadu_si512((
const __m512i *)qh);
1075 const __m512i q4h_0 = _mm512_slli_epi16(_mm512_and_si512(q4bitsH, m2), 4);
1077 const __m512i q4h_1 = _mm512_slli_epi16(_mm512_and_si512(_mm512_srli_epi16(q4bitsH, 2), m2), 4);
1079 const __m512i q4h_2 = _mm512_slli_epi16(_mm512_and_si512(_mm512_srli_epi16(q4bitsH, 4), m2), 4);
1081 const __m512i q4h_3 = _mm512_slli_epi16(_mm512_and_si512(_mm512_srli_epi16(q4bitsH, 6), m2), 4);
1085 const __m512i q6_0 = _mm512_or_si512(_mm512_and_si512(q4bits1, m4), q4h_0);
1086 const __m512i q6_1 = _mm512_or_si512(_mm512_and_si512(q4bits2, m4), q4h_1);
1088 const __m512i q6_2 = _mm512_or_si512(_mm512_and_si512(_mm512_srli_epi16(q4bits1, 4), m4), q4h_2);
1089 const __m512i q6_3 = _mm512_or_si512(_mm512_and_si512(_mm512_srli_epi16(q4bits2, 4), m4), q4h_3);
1092 const __m512i q8_0 = _mm512_loadu_si512((
const __m512i *)q8);
1093 const __m512i q8_1 = _mm512_loadu_si512((
const __m512i *)(q8 + 64));
1094 const __m512i q8_2 = _mm512_loadu_si512((
const __m512i *)(q8 + 128));
1095 const __m512i q8_3 = _mm512_loadu_si512((
const __m512i *)(q8 + 192));
1098 __m512i q8s_0 = _mm512_maddubs_epi16(m32s, q8_0);
1099 __m512i q8s_1 = _mm512_maddubs_epi16(m32s, q8_1);
1100 __m512i q8s_2 = _mm512_maddubs_epi16(m32s, q8_2);
1101 __m512i q8s_3 = _mm512_maddubs_epi16(m32s, q8_3);
1104 __m512i p16_0 = _mm512_maddubs_epi16(q6_0, q8_0);
1105 __m512i p16_1 = _mm512_maddubs_epi16(q6_1, q8_1);
1106 __m512i p16_2 = _mm512_maddubs_epi16(q6_2, q8_2);
1107 __m512i p16_3 = _mm512_maddubs_epi16(q6_3, q8_3);
1110 p16_0 = _mm512_sub_epi16(p16_0, q8s_0);
1111 p16_1 = _mm512_sub_epi16(p16_1, q8s_1);
1112 p16_2 = _mm512_sub_epi16(p16_2, q8s_2);
1113 p16_3 = _mm512_sub_epi16(p16_3, q8s_3);
1118 const __m128i scales_128 = _mm_loadu_si128((
const __m128i *)sc);
1122 const __m512i scale_idx_0 = _mm512_set_epi8(
1123 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
1124 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
1125 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1126 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
1127 const __m512i scale_idx_1 = _mm512_set_epi8(
1128 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1129 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1130 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1131 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4);
1132 const __m512i scale_idx_2 = _mm512_set_epi8(
1133 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
1134 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
1135 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
1136 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8);
1137 const __m512i scale_idx_3 = _mm512_set_epi8(
1138 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
1139 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
1140 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
1141 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12);
1144 const __m512i scales_512 = _mm512_broadcast_i32x4(scales_128);
1145 const __m512i sc_0 = _mm512_permutexvar_epi8(scale_idx_0, scales_512);
1146 const __m512i sc_1 = _mm512_permutexvar_epi8(scale_idx_1, scales_512);
1147 const __m512i sc_2 = _mm512_permutexvar_epi8(scale_idx_2, scales_512);
1148 const __m512i sc_3 = _mm512_permutexvar_epi8(scale_idx_3, scales_512);
1152 __m512i p32_0 = _mm512_madd_epi16(_mm512_cvtepi8_epi16(_mm512_castsi512_si256(sc_0)), p16_0);
1153 __m512i p32_1 = _mm512_madd_epi16(_mm512_cvtepi8_epi16(_mm512_castsi512_si256(sc_1)), p16_1);
1154 __m512i p32_2 = _mm512_madd_epi16(_mm512_cvtepi8_epi16(_mm512_castsi512_si256(sc_2)), p16_2);
1155 __m512i p32_3 = _mm512_madd_epi16(_mm512_cvtepi8_epi16(_mm512_castsi512_si256(sc_3)), p16_3);
1158 sumi = _mm512_add_epi32(sumi, p32_0);
1159 sumi = _mm512_add_epi32(sumi, p32_1);
1160 sumi = _mm512_add_epi32(sumi, p32_2);
1161 sumi = _mm512_add_epi32(sumi, p32_3);
1164 acc = _mm512_fmadd_ps(_mm512_set1_ps(d), _mm512_cvtepi32_ps(sumi), acc);
1167 return _mm512_reduce_add_ps(acc);
1175 if (!y || !W || !x_q8 || M <= 0 || K <= 0) {
1181 const int blocks_per_row = K /
QK_K;
1183 for (
int row = 0; row < M; ++row) {
1184 const block_q6_K *w_row = blocks + (size_t)row * (
size_t)blocks_per_row;
1185 y[row] = dot_q6_k_q8_k_avx512_vbmi(w_row, x, K);
1191#if defined(__AVX512F__) && defined(__AVX512BW__)
1200static float dot_q6_k_q8_k_avx512(
const block_q6_K *w,
1204 const int nb = K /
QK_K;
1205 const __m256i m4 = _mm256_set1_epi8(0xF);
1206 const __m256i m2 = _mm256_set1_epi8(3);
1207 const __m256i m32s = _mm256_set1_epi8(32);
1210 __m256 acc = _mm256_setzero_ps();
1212 for (
int i = 0; i < nb; ++i) {
1215 const uint8_t *q4 = w[i].
ql;
1216 const uint8_t *qh = w[i].
qh;
1217 const int8_t *q8 = x[i].
qs;
1219 const __m128i scales = _mm_loadu_si128((
const __m128i *)w[i].scales);
1222 __m256i sumi = _mm256_setzero_si256();
1226 for (
int j = 0; j <
QK_K / 128; ++j) {
1228 static const uint8_t patterns[8][16] = {
1229 { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
1230 { 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 },
1231 { 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5 },
1232 { 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7 },
1233 { 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9 },
1234 {10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11 },
1235 {12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13 },
1236 {14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15 },
1239 const __m128i scale_0 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)patterns[is + 0]));
1240 const __m128i scale_1 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)patterns[is + 1]));
1241 const __m128i scale_2 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)patterns[is + 2]));
1242 const __m128i scale_3 = _mm_shuffle_epi8(scales, _mm_loadu_si128((
const __m128i *)patterns[is + 3]));
1246 const __m256i q4bits1 = _mm256_loadu_si256((
const __m256i *)q4);
1248 const __m256i q4bits2 = _mm256_loadu_si256((
const __m256i *)q4);
1250 const __m256i q4bitsH = _mm256_loadu_si256((
const __m256i *)qh);
1254 const __m256i q4h_0 = _mm256_slli_epi16(_mm256_and_si256(q4bitsH, m2), 4);
1255 const __m256i q4h_1 = _mm256_slli_epi16(_mm256_and_si256(_mm256_srli_epi16(q4bitsH, 2), m2), 4);
1256 const __m256i q4h_2 = _mm256_slli_epi16(_mm256_and_si256(_mm256_srli_epi16(q4bitsH, 4), m2), 4);
1257 const __m256i q4h_3 = _mm256_slli_epi16(_mm256_and_si256(_mm256_srli_epi16(q4bitsH, 6), m2), 4);
1260 const __m256i q4_0 = _mm256_or_si256(_mm256_and_si256(q4bits1, m4), q4h_0);
1261 const __m256i q4_1 = _mm256_or_si256(_mm256_and_si256(q4bits2, m4), q4h_1);
1262 const __m256i q4_2 = _mm256_or_si256(_mm256_and_si256(_mm256_srli_epi16(q4bits1, 4), m4), q4h_2);
1263 const __m256i q4_3 = _mm256_or_si256(_mm256_and_si256(_mm256_srli_epi16(q4bits2, 4), m4), q4h_3);
1266 const __m256i q8_0 = _mm256_loadu_si256((
const __m256i *)q8);
1268 const __m256i q8_1 = _mm256_loadu_si256((
const __m256i *)q8);
1270 const __m256i q8_2 = _mm256_loadu_si256((
const __m256i *)q8);
1272 const __m256i q8_3 = _mm256_loadu_si256((
const __m256i *)q8);
1276 __m256i q8s_0 = _mm256_maddubs_epi16(m32s, q8_0);
1277 __m256i q8s_1 = _mm256_maddubs_epi16(m32s, q8_1);
1278 __m256i q8s_2 = _mm256_maddubs_epi16(m32s, q8_2);
1279 __m256i q8s_3 = _mm256_maddubs_epi16(m32s, q8_3);
1282 __m256i p16_0 = _mm256_maddubs_epi16(q4_0, q8_0);
1283 __m256i p16_1 = _mm256_maddubs_epi16(q4_1, q8_1);
1284 __m256i p16_2 = _mm256_maddubs_epi16(q4_2, q8_2);
1285 __m256i p16_3 = _mm256_maddubs_epi16(q4_3, q8_3);
1288 p16_0 = _mm256_sub_epi16(p16_0, q8s_0);
1289 p16_1 = _mm256_sub_epi16(p16_1, q8s_1);
1290 p16_2 = _mm256_sub_epi16(p16_2, q8s_2);
1291 p16_3 = _mm256_sub_epi16(p16_3, q8s_3);
1294 p16_0 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_0), p16_0);
1295 p16_1 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_1), p16_1);
1296 p16_2 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_2), p16_2);
1297 p16_3 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_3), p16_3);
1300 sumi = _mm256_add_epi32(sumi, _mm256_add_epi32(p16_0, p16_1));
1301 sumi = _mm256_add_epi32(sumi, _mm256_add_epi32(p16_2, p16_3));
1305 acc = _mm256_fmadd_ps(_mm256_set1_ps(d), _mm256_cvtepi32_ps(sumi), acc);
1308 return ck_q6k_hsum_float_8(acc);
1316 if (!y || !W || !x_q8 || M <= 0 || K <= 0) {
1322 const int blocks_per_row = K /
QK_K;
1324 for (
int row = 0; row < M; ++row) {
1325 const block_q6_K *w_row = blocks + (size_t)row * (
size_t)blocks_per_row;
1326 y[row] = dot_q6_k_q8_k_avx512(w_row, x, K);
1341 if (!s || !vx || !vy || n <= 0) {
1366#if defined(__AVX2__)
1372#elif defined(__AVX__)
1375#elif defined(__SSE4_1__)
1378#elif defined(__ARM_NEON) || defined(__aarch64__)
1383 gemv_q6_k_q8_k_neon(y, W, x_q8, M, K);
1392 return "q6_k_q8_k_ref";
1394#if defined(__AVX2__)
1395 return "q6_k_q8_k_avx2";
1396#elif defined(__AVX__)
1397 return "q6_k_q8_k_avx";
1398#elif defined(__SSE4_1__)
1399 return "q6_k_q8_k_sse";
1400#elif defined(__ARM_NEON) || defined(__aarch64__)
1401 return "q6_k_q8_k_neon";
1403 return "q6_k_q8_k_ref";
1428 if (!y || !W || !x_q8 || M <= 0 || K <= 0)
return;
1429 if (ith < 0 || nth <= 0 || ith >= nth)
return;
1432 const int dr = (M + nth - 1) / nth;
1433 const int r0 = dr * ith;
1434 const int r1 = (r0 + dr < M) ? (r0 + dr) : M;
1436 if (r0 >= M)
return;
1440 const int blocks_per_row = K /
QK_K;
1442 for (
int row = r0; row < r1; ++row) {
1443 const block_q6_K *w_row = blocks + (size_t)row * (
size_t)blocks_per_row;
1460 if (!y || !W || !x_q8 || M <= 0 || K <= 0)
return;
1461 if (ith < 0 || nth <= 0 || ith >= nth)
return;
1463 const int dr = (M + nth - 1) / nth;
1464 const int r0 = dr * ith;
1465 const int r1 = (r0 + dr < M) ? (r0 + dr) : M;
1467 if (r0 >= M)
return;
1471 const int blocks_per_row = K /
QK_K;
1474 for (
int row = r0; row < r1; ++row) {
1475 const block_q6_K *w_row = blocks + (size_t)row * (
size_t)blocks_per_row;
1476#if defined(__AVX2__)
1478 : dot_q6_k_q8_k_avx2(w_row, x, K);
1479#elif defined(__AVX__)
1481 : dot_q6_k_q8_k_avx(w_row, x, K);
1482#elif defined(__SSE4_1__)
1484 : dot_q6_k_q8_k_sse(w_row, x, K);
1485#elif defined(__ARM_NEON) || defined(__aarch64__)
1487 : dot_q6_k_q8_k_neon(w_row, x, K);
1511 int M,
int N,
int K)
1513 if (!Y || !W || !X_q8 || M <= 0 || N <= 0 || K <= 0) {
1518 const int blocks_per_vec = K /
QK_K;
1520 for (
int n = 0; n < N; ++n) {
1521 const block_q8_K *x_row = X + (size_t)n * (
size_t)blocks_per_vec;
1546 int M,
int N,
int K);
1552 int M,
int N,
int K)
1554 if (!A_q8 || !B || !
C) {
1557 if (M <= 0 || N <= 0 || K <= 0) {
1560#if defined(__AVX2__) && defined(__FMA__)
1572 const int blocks_per_vec = K /
QK_K;
1573 const int blocks_per_row = K /
QK_K;
1575 for (
int m = 0; m < M; ++m) {
1576 const block_q8_K *a_row = A + (size_t)m * (
size_t)blocks_per_vec;
1577 float *c_row =
C + (size_t)m * (
size_t)N;
1578 for (
int n = 0; n < N; ++n) {
1579 const block_q6_K *w_row = W + (size_t)n * (
size_t)blocks_per_row;
1580 const float b = bias ? bias[n] : 0.0f;
1592 int M,
int N,
int K,
1593 int m0,
int m1,
int n0,
int n1)
1595 if (!A_q8 || !B || !
C || M <= 0 || N <= 0 || K <= 0 || K %
QK_K)
return;
1596 if (m0 < 0 || n0 < 0 || m1 > M || n1 > N || m0 >= m1 || n0 >= n1)
return;
1599 const int nb = K /
QK_K;
1600 for (
int m = m0; m < m1; ++m) {
1601 for (
int n = n0; n < n1; ++n) {
1603 for (
int b = 0; b < nb; ++b) {
1604 const block_q6_K *w = W + (size_t)n * (
size_t)nb + b;
1605 const block_q8_K *a = A + (size_t)m * (
size_t)nb + b;
1607 for (
int e = 0; e <
QK_K; ++e) {
1608 const int group = (e / 128) * 128;
1609 const int pos = e % 128;
1610 const int lane = pos % 32;
1611 const int ql_off = group / 2 + lane + ((pos / 32) & 1) * 32;
1612 const int qh_off = group / 4 + lane;
1613 const int ql_shift = (pos >= 64) ? 4 : 0;
1614 const int qh_shift = (pos / 32) * 2;
1615 const int code = ((w->
ql[ql_off] >> ql_shift) & 15) |
1616 (((w->
qh[qh_off] >> qh_shift) & 3) << 4);
1617 dot += (code - 32) * (
int)w->
scales[e / 16] * (int)a->
qs[e];
1621 C[(size_t)m * (
size_t)N + n] = acc + (bias ? bias[n] : 0.0f);
1630 int M,
int N,
int K)
1633 M, N, K, 0, M, 0, N);
1638 const void *B_prepared,
1641 int M,
int N,
int K,
1644 int use_avx512_vnni)
1646#if !defined(__AVX2__)
1647 (void)A_q8; (void)B_prepared; (void)bias; (void)
C;
1648 (void)M; (void)N; (void)K; (void)m0; (void)m1; (void)n0; (void)n1;
1649 (void)use_avx512_vnni;
1651#if !defined(__AVX512F__) || !defined(__AVX512BW__) || \
1652 !defined(__AVX512VNNI__)
1653 (void)use_avx512_vnni;
1655 if (!A_q8 || !B_prepared || !
C || M <= 0 || N <= 0 || K <= 0 ||
1656 (K %
QK_K) != 0)
return;
1661 if (m0 >= m1 || n0 >= n1)
return;
1664 const block_q6_K_prepared *W =
1665 (
const block_q6_K_prepared *)B_prepared;
1666 const int blocks_per_row = K /
QK_K;
1667 for (
int n = n0; n < n1; ++n) {
1668 const block_q6_K_prepared *w_row =
1669 W + (size_t)n * (
size_t)blocks_per_row;
1670 const float b = bias ? bias[n] : 0.0f;
1671 for (
int m = m0; m < m1; ++m) {
1673 A + (size_t)m * (
size_t)blocks_per_row;
1674#if defined(__AVX512F__) && defined(__AVX512BW__) && \
1675 defined(__AVX512VNNI__)
1676 const float dot = use_avx512_vnni
1677 ? dot_q6_k_prepared_q8_k_avx512_vnni(w_row, a_row, K)
1678 : dot_q6_k_prepared_q8_k_avx2(w_row, a_row, K);
1680 const float dot = dot_q6_k_prepared_q8_k_avx2(w_row, a_row, K);
1682 C[(size_t)m * (
size_t)N + (size_t)n] =
1690 const void *B_prepared,
1693 int M,
int N,
int K,
1697 int use_avx512_vnni = 0;
1698#if defined(__AVX512F__) && defined(__AVX512BW__) && \
1699 defined(__AVX512VNNI__)
1700 use_avx512_vnni = 1;
1703 A_q8, B_prepared, bias,
C, M, N, K,
1704 m0, m1, n0, n1, use_avx512_vnni);
1709 const void *B_prepared,
1712 int M,
int N,
int K)
1715 A_q8, B_prepared, bias,
C, M, N, K,
1720 const void *B_prepared,
1723 int M,
int N,
int K)
1726 A_q8, B_prepared, bias,
C, M, N, K, 0, M, 0, N);
1736#if defined(__AVX2__)
1739 return dot_q6_k_q8_k_avx2(w, x, K);
1740#elif defined(__AVX__)
1742 return dot_q6_k_q8_k_avx(w, x, K);
1743#elif defined(__SSE4_1__)
1745 return dot_q6_k_q8_k_sse(w, x, K);
1746#elif defined(__ARM_NEON) || defined(__aarch64__)
1748 return dot_q6_k_q8_k_neon(w, x, K);
1764 int M,
int N,
int K,
1768 if (!A_q8 || !B || !
C) {
1771 if (M <= 0 || N <= 0 || K <= 0 || K %
QK_K != 0) {
1778 if (m0 >= m1 || n0 >= n1) {
1784 const int blocks_per_vec = K /
QK_K;
1785 const int blocks_per_row = K /
QK_K;
1787 for (
int n = n0; n < n1; ++n) {
1788 const block_q6_K *w_row = W + (size_t)n * (
size_t)blocks_per_row;
1789 const float b = bias ? bias[n] : 0.0f;
1790 for (
int m = m0; m < m1; ++m) {
1791 const block_q8_K *a_row = A + (size_t)m * (
size_t)blocks_per_vec;
1801 int M,
int N,
int K,
1805 if (!A_q8 || !B || !
C || M <= 0 || N <= 0 || K <= 0 ||
1813 if (m0 >= m1 || n0 >= n1)
return;
1815#if defined(__AVX2__)
1819 const int blocks_per_vec = K /
QK_K;
1820 for (
int n = n0; n < n1; ++n) {
1822 W + (size_t)n * (
size_t)blocks_per_vec;
1823 const float b = bias ? bias[n] : 0.0f;
1825 for (; m + 4 <= m1; m += 4) {
1827 dot_q6_k_q8_k_avx2_m4(
1828 w_row, A + (
size_t)m * (
size_t)blocks_per_vec,
1829 blocks_per_vec, 4, K, values);
1830 for (
int r = 0; r < 4; ++r) {
1831 C[(size_t)(m + r) * (size_t)N + (
size_t)n] = values[r] + b;
1836 const int rows = m1 - m;
1837 dot_q6_k_q8_k_avx2_m4(
1838 w_row, A + (
size_t)m * (
size_t)blocks_per_vec,
1839 blocks_per_vec, rows, K, values);
1840 for (
int r = 0; r < rows; ++r) {
1841 C[(size_t)(m + r) * (size_t)N + (
size_t)n] = values[r] + b;
1849 A_q8, B, bias,
C, M, N, K, m0, m1, n0, n1);
1855 const float *bias,
float *
C,
1856 int M,
int N,
int K)
1858 if (!A_q8 || !B || !
C || M != 2 || N <= 0 || K <= 0 ||
1859 (K %
QK_K) != 0)
return;
1874 int M,
int N,
int K)
1876 enum { TILE_M = 8, TILE_N = 16 };
1877 for (
int n0 = 0; n0 < N; n0 += TILE_N) {
1878 const int n1 = (n0 + TILE_N < N) ? (n0 + TILE_N) : N;
1879 for (
int m0 = 0; m0 < M; m0 += TILE_M) {
1880 const int m1 = (m0 + TILE_M < M) ? (m0 + TILE_M) : M;
1881 gemm_nt_q6_k_q8_k_tile(A_q8, B, bias,
C, M, N, K, m0, m1, n0, n1);
int ck_strict_parity_enabled(void)
Quantization block structures for weight-only quantization.
#define GGML_FP16_TO_FP32
void gemm_nt_q6_k_q8_k_tile(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K, int m0, int m1, int n0, int n1)
Compute one C[m0:m1, n0:n1] tile for Q8_K activations x Q6_K weights.
void gemv_q6_k_q8_k_ref(float *y, const void *W, const void *x_q8, int M, int K)
void gemv_q6_k_q8_k_sse(float *y, const void *W, const void *x_q8, int M, int K)
size_t ck_q6_k_prepared_block_size(void)
void gemv_q6_k_q8_k_avx(float *y, const void *W, const void *x_q8, int M, int K)
const char * ck_q6_k_q8_k_provider_name(void)
void gemm_nt_q6_k_q8_k_tiled_parity(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
NT GEMM: C = A @ B^T where A is Q8_K and B is Q6_K.
void gemm_nt_q6_k_q8_k_m4_tile(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K, int m0, int m1, int n0, int n1)
static float ck_dot_q6_k_q8_k_fast_or_ref(const block_q6_K *w, const block_q8_K *x, int K)
void gemm_q6_k_q8_k(float *Y, const void *W, const void *X_q8, int M, int N, int K)
GEMM: Y = W @ X^T where W is Q6_K and X is Q8_K.
static void gemm_nt_q6_k_q8_k_prepared_tile_impl(const void *A_q8, const void *B_prepared, const float *bias, float *C, int M, int N, int K, int m0, int m1, int n0, int n1, int use_avx512_vnni)
void gemv_q6_k_q8_k(float *y, const void *W, const void *x_q8, int M, int K)
GEMV: y = W @ x where W is Q6_K and x is Q8_K.
void gemv_q6_k_q8_k_avx2(float *y, const void *W, const void *x_q8, int M, int K)
void vec_dot_q6_k_q8_k(int n, float *s, const void *vx, const void *vy)
Q6_K x Q8_K dot product (single row)
void gemm_nt_q6_k_q8_k_prepared_avx512_vnni(const void *A_q8, const void *B_prepared, const float *bias, float *C, int M, int N, int K)
void gemm_nt_q6_k_q8_k_prepared(const void *A_q8, const void *B_prepared, const float *bias, float *C, int M, int N, int K)
void gemm_nt_q6_k_q8_k_tiled(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
Experimental single-thread tiled NT GEMM wrapper.
void gemv_q6_k_q8_k_avx512_vbmi(float *y, const void *W, const void *x_q8, int M, int K)
void gemm_nt_q6_k_q8_k_tiled_parity_tile(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K, int m0, int m1, int n0, int n1)
void gemv_q6_k_q8_k_parallel(float *y, const void *W, const void *x_q8, int M, int K, int ith, int nth)
Parallel reference GEMV for Q6_K × Q8_K.
void gemm_nt_q6_k_q8_k_prepared_tile(const void *A_q8, const void *B_prepared, const float *bias, float *C, int M, int N, int K, int m0, int m1, int n0, int n1)
static int ck_q6k_q8k_force_ref(void)
void ck_q6_k_prepare_weight(const void *src, void *dst, int N, int K)
const char * ck_q6_k_prepared_provider_name(void)
void gemm_nt_q6_k_q8_k(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
void gemm_nt_q6_k_q8_k_m2(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
void gemv_q6_k_q8_k_avx512(float *y, const void *W, const void *x_q8, int M, int K)
void gemv_q6_k_q8_k_parallel_simd(float *y, const void *W, const void *x_q8, int M, int K, int ith, int nth)
Parallel SIMD GEMV for Q6_K × Q8_K.
static float dot_q6_k_q8_k_ref(const block_q6_K *w, const block_q8_K *x, int K)
Scalar dot product for Q6_K x Q8_K.