37#if defined(__AVX512F__) || defined(__AVX2__) || defined(__AVX__) || defined(__SSE4_1__)
40#if defined(__ARM_NEON) || defined(__aarch64__)
73 const int blocks_per_row = K /
QK5_0;
75 for (
int row = 0; row < M; row++) {
78 for (
int b = 0; b < blocks_per_row; b++) {
79 const block_q5_0 *block = &blocks[row * blocks_per_row + b];
81 const float *xp = &x[b *
QK5_0];
85 memcpy(&qh, block->
qh,
sizeof(qh));
92 for (
int j = 0; j <
QK5_0 / 2; j++) {
93 const uint8_t packed = block->
qs[j];
96 const int lo = (packed & 0x0F);
97 const int hi = (packed >> 4);
100 const int xh_0 = ((qh >> (j + 0)) << 4) & 0x10;
101 const int xh_1 = ((qh >> (j + 12))) & 0x10;
104 const int q0 = (lo | xh_0) - 16;
105 const int q1 = (hi | xh_1) - 16;
108 sum += d * (float)q0 * xp[j];
109 sum += d * (float)q1 * xp[j + 16];
121void gemv_q5_0_avx512(
float *y,
127 const int blocks_per_row = K /
QK5_0;
128 const __m512i offset = _mm512_set1_epi32(16);
129 const __m512i mask_lo = _mm512_set1_epi32(0x0F);
130 const __m512i one = _mm512_set1_epi32(1);
132 for (
int row = 0; row < M; row++) {
133 __m512 acc = _mm512_setzero_ps();
135 for (
int b = 0; b < blocks_per_row; b++) {
136 const block_q5_0 *block = &blocks[row * blocks_per_row + b];
138 const float *xp = &x[b *
QK5_0];
142 memcpy(&qh, block->
qh,
sizeof(qh));
145 __m128i packed = _mm_loadu_si128((
const __m128i *)block->
qs);
146 __m512i bytes = _mm512_cvtepu8_epi32(packed);
149 __m512i lo = _mm512_and_epi32(bytes, mask_lo);
150 __m512i hi_shift = _mm512_srli_epi32(bytes, 4);
157 __m512i qh_lo = _mm512_set_epi32(
158 ((qh >> 15) & 1) << 4, ((qh >> 14) & 1) << 4,
159 ((qh >> 13) & 1) << 4, ((qh >> 12) & 1) << 4,
160 ((qh >> 11) & 1) << 4, ((qh >> 10) & 1) << 4,
161 ((qh >> 9) & 1) << 4, ((qh >> 8) & 1) << 4,
162 ((qh >> 7) & 1) << 4, ((qh >> 6) & 1) << 4,
163 ((qh >> 5) & 1) << 4, ((qh >> 4) & 1) << 4,
164 ((qh >> 3) & 1) << 4, ((qh >> 2) & 1) << 4,
165 ((qh >> 1) & 1) << 4, ((qh >> 0) & 1) << 4
172 __m512i qh_hi = _mm512_set_epi32(
173 ((qh >> 31) & 1) << 4, ((qh >> 30) & 1) << 4,
174 ((qh >> 29) & 1) << 4, ((qh >> 28) & 1) << 4,
175 ((qh >> 27) & 1) << 4, ((qh >> 26) & 1) << 4,
176 ((qh >> 25) & 1) << 4, ((qh >> 24) & 1) << 4,
177 ((qh >> 23) & 1) << 4, ((qh >> 22) & 1) << 4,
178 ((qh >> 21) & 1) << 4, ((qh >> 20) & 1) << 4,
179 ((qh >> 19) & 1) << 4, ((qh >> 18) & 1) << 4,
180 ((qh >> 17) & 1) << 4, ((qh >> 16) & 1) << 4
184 __m512i q_lo = _mm512_sub_epi32(_mm512_or_epi32(lo, qh_lo), offset);
185 __m512i q_hi = _mm512_sub_epi32(_mm512_or_epi32(hi_shift, qh_hi), offset);
188 __m512 w_lo = _mm512_mul_ps(_mm512_cvtepi32_ps(q_lo), vscale);
189 __m512 w_hi = _mm512_mul_ps(_mm512_cvtepi32_ps(q_hi), vscale);
192 __m512 x_first = _mm512_loadu_ps(&xp[0]);
193 __m512 x_second = _mm512_loadu_ps(&xp[16]);
195 acc = _mm512_fmadd_ps(w_lo, x_first, acc);
196 acc = _mm512_fmadd_ps(w_hi, x_second, acc);
199 y[row] = _mm512_reduce_add_ps(acc);
216#if defined(__AVX2__) && !defined(__AVX512F__)
219static inline float hsum_avx2(__m256 v) {
220 __m128 lo = _mm256_castps256_ps128(v);
221 __m128 hi = _mm256_extractf128_ps(v, 1);
222 lo = _mm_add_ps(lo, hi);
223 __m128 shuf = _mm_shuffle_ps(lo, lo, _MM_SHUFFLE(2, 3, 0, 1));
224 __m128 sums = _mm_add_ps(lo, shuf);
225 shuf = _mm_movehl_ps(shuf, sums);
226 sums = _mm_add_ss(sums, shuf);
227 return _mm_cvtss_f32(sums);
236void gemv_q5_0_avx2(
float *y,
242 const int blocks_per_row = K /
QK5_0;
244 for (
int row = 0; row < M; row++) {
245 __m256 acc = _mm256_setzero_ps();
247 for (
int b = 0; b < blocks_per_row; b++) {
248 const block_q5_0 *block = &blocks[row * blocks_per_row + b];
250 const __m256 vscale = _mm256_set1_ps(d);
251 const float *xp = &x[b *
QK5_0];
255 memcpy(&qh, block->
qh,
sizeof(qh));
266 __m128i qs8 = _mm_loadl_epi64((
const __m128i *)block->
qs);
267 __m128i lo = _mm_and_si128(qs8, _mm_set1_epi8(0x0F));
271 for (
int i = 0; i < 8; i++) {
272 hb[i] = ((qh >> i) << 4) & 0x10;
274 __m128i hi = _mm_loadl_epi64((
const __m128i *)hb);
277 __m128i q5 = _mm_or_si128(lo, hi);
278 __m128i offset = _mm_set1_epi8(16);
279 __m128i q5_signed = _mm_sub_epi8(q5, offset);
282 __m256i q32 = _mm256_cvtepi8_epi32(q5_signed);
283 __m256 wf = _mm256_cvtepi32_ps(q32);
284 wf = _mm256_mul_ps(wf, vscale);
287 __m256 xv = _mm256_loadu_ps(&xp[0]);
288 acc = _mm256_fmadd_ps(wf, xv, acc);
293 __m128i qs8 = _mm_loadl_epi64((
const __m128i *)(block->
qs + 8));
294 __m128i lo = _mm_and_si128(qs8, _mm_set1_epi8(0x0F));
297 for (
int i = 0; i < 8; i++) {
298 hb[i] = ((qh >> (8 + i)) << 4) & 0x10;
300 __m128i hi = _mm_loadl_epi64((
const __m128i *)hb);
302 __m128i q5 = _mm_or_si128(lo, hi);
303 __m128i offset = _mm_set1_epi8(16);
304 __m128i q5_signed = _mm_sub_epi8(q5, offset);
306 __m256i q32 = _mm256_cvtepi8_epi32(q5_signed);
307 __m256 wf = _mm256_cvtepi32_ps(q32);
308 wf = _mm256_mul_ps(wf, vscale);
310 __m256 xv = _mm256_loadu_ps(&xp[8]);
311 acc = _mm256_fmadd_ps(wf, xv, acc);
316 __m128i qs8 = _mm_loadl_epi64((
const __m128i *)block->
qs);
317 __m128i hi_nib = _mm_and_si128(_mm_srli_epi16(qs8, 4), _mm_set1_epi8(0x0F));
321 for (
int i = 0; i < 8; i++) {
322 hb[i] = ((qh >> (16 + i)) & 1) << 4;
324 __m128i hi = _mm_loadl_epi64((
const __m128i *)hb);
326 __m128i q5 = _mm_or_si128(hi_nib, hi);
327 __m128i offset = _mm_set1_epi8(16);
328 __m128i q5_signed = _mm_sub_epi8(q5, offset);
330 __m256i q32 = _mm256_cvtepi8_epi32(q5_signed);
331 __m256 wf = _mm256_cvtepi32_ps(q32);
332 wf = _mm256_mul_ps(wf, vscale);
334 __m256 xv = _mm256_loadu_ps(&xp[16]);
335 acc = _mm256_fmadd_ps(wf, xv, acc);
340 __m128i qs8 = _mm_loadl_epi64((
const __m128i *)(block->
qs + 8));
341 __m128i hi_nib = _mm_and_si128(_mm_srli_epi16(qs8, 4), _mm_set1_epi8(0x0F));
344 for (
int i = 0; i < 8; i++) {
345 hb[i] = ((qh >> (24 + i)) & 1) << 4;
347 __m128i hi = _mm_loadl_epi64((
const __m128i *)hb);
349 __m128i q5 = _mm_or_si128(hi_nib, hi);
350 __m128i offset = _mm_set1_epi8(16);
351 __m128i q5_signed = _mm_sub_epi8(q5, offset);
353 __m256i q32 = _mm256_cvtepi8_epi32(q5_signed);
354 __m256 wf = _mm256_cvtepi32_ps(q32);
355 wf = _mm256_mul_ps(wf, vscale);
357 __m256 xv = _mm256_loadu_ps(&xp[24]);
358 acc = _mm256_fmadd_ps(wf, xv, acc);
362 y[row] = hsum_avx2(acc);
385#if defined(__AVX__) && !defined(__AVX2__) && !defined(__AVX512F__)
388static inline __m128i extract_low_nibbles(__m128i packed) {
389 return _mm_and_si128(packed, _mm_set1_epi8(0x0F));
393static inline __m128i extract_high_nibbles(__m128i packed) {
394 return _mm_and_si128(_mm_srli_epi16(packed, 4), _mm_set1_epi8(0x0F));
398static inline float hsum_sse(__m128 v) {
399 __m128 shuf = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 3, 0, 1));
400 __m128 sums = _mm_add_ps(v, shuf);
401 shuf = _mm_movehl_ps(shuf, sums);
402 sums = _mm_add_ss(sums, shuf);
403 return _mm_cvtss_f32(sums);
407static inline float dot_int8_float8_sse(__m128i q8_lo,
const float *x,
float scale) {
409 __m128i lo16 = _mm_cvtepi8_epi16(q8_lo);
410 __m128i lo32_0 = _mm_cvtepi16_epi32(lo16);
411 __m128i lo32_1 = _mm_cvtepi16_epi32(_mm_srli_si128(lo16, 8));
414 __m128 w0 = _mm_cvtepi32_ps(lo32_0);
415 __m128 w1 = _mm_cvtepi32_ps(lo32_1);
418 __m128 vscale = _mm_set1_ps(scale);
419 w0 = _mm_mul_ps(w0, vscale);
420 w1 = _mm_mul_ps(w1, vscale);
423 __m128 x0 = _mm_loadu_ps(x);
424 __m128 x1 = _mm_loadu_ps(x + 4);
426 __m128 prod0 = _mm_mul_ps(w0, x0);
427 __m128 prod1 = _mm_mul_ps(w1, x1);
430 __m128 sum = _mm_add_ps(prod0, prod1);
431 return hsum_sse(sum);
440void gemv_q5_0_avx(
float *y,
446 const int blocks_per_row = K /
QK5_0;
448 const __m128i mask_0f = _mm_set1_epi8(0x0F);
449 const __m128i mask_10 = _mm_set1_epi8(0x10);
451 for (
int row = 0; row < M; row++) {
454 for (
int b = 0; b < blocks_per_row; b++) {
455 const block_q5_0 *block = &blocks[row * blocks_per_row + b];
457 const float *xp = &x[b *
QK5_0];
460 __m128i qs = _mm_loadu_si128((
const __m128i *)block->
qs);
463 __m128i lo_nibbles = _mm_and_si128(qs, mask_0f);
464 __m128i hi_nibbles = _mm_and_si128(_mm_srli_epi16(qs, 4), mask_0f);
468 memcpy(&qh, block->
qh,
sizeof(qh));
481 for (
int i = 0; i < 8; i++) {
482 int lo = block->
qs[i] & 0x0F;
483 int hb = ((qh >> i) << 4) & 0x10;
484 w8[i] = (lo | hb) - 16;
486 __m128i q8 = _mm_loadl_epi64((
const __m128i *)w8);
487 sum += dot_int8_float8_sse(q8, &xp[0], d);
493 for (
int i = 0; i < 8; i++) {
494 int lo = block->
qs[8 + i] & 0x0F;
495 int hb = ((qh >> (8 + i)) << 4) & 0x10;
496 w8[i] = (lo | hb) - 16;
498 __m128i q8 = _mm_loadl_epi64((
const __m128i *)w8);
499 sum += dot_int8_float8_sse(q8, &xp[8], d);
505 for (
int i = 0; i < 8; i++) {
506 int hi = block->
qs[i] >> 4;
507 int hb = (qh >> (12 + i)) & 0x10;
508 w8[i] = (hi | hb) - 16;
510 __m128i q8 = _mm_loadl_epi64((
const __m128i *)w8);
511 sum += dot_int8_float8_sse(q8, &xp[16], d);
517 for (
int i = 0; i < 8; i++) {
518 int hi = block->
qs[8 + i] >> 4;
519 int hb = (qh >> (20 + i)) & 0x10;
520 w8[i] = (hi | hb) - 16;
522 __m128i q8 = _mm_loadl_epi64((
const __m128i *)w8);
523 sum += dot_int8_float8_sse(q8, &xp[24], d);
556#if defined(__AVX512F__)
557 gemv_q5_0_avx512(y, W, x, M, K);
558#elif defined(__AVX2__)
559 gemv_q5_0_avx2(y, W, x, M, K);
560#elif defined(__AVX__)
561 gemv_q5_0_avx(y, W, x, M, K);
562#elif defined(__SSE4_1__)
585 if (!y || !W || !x || M <= 0 || K <= 0)
return;
586 if (ith < 0 || nth <= 0 || ith >= nth)
return;
588 const int dr = (M + nth - 1) / nth;
589 const int r0 = dr * ith;
590 const int r1 = (r0 + dr < M) ? (r0 + dr) : M;
595 const int blocks_per_row = K /
QK5_0;
597 for (
int row = r0; row < r1; row++) {
599 for (
int b = 0; b < blocks_per_row; b++) {
600 const block_q5_0 *block = &blocks[row * blocks_per_row + b];
602 const float *xp = &x[b *
QK5_0];
605 memcpy(&qh, block->
qh,
sizeof(qh));
607 for (
int j = 0; j <
QK5_0 / 2; j++) {
608 const uint8_t packed = block->
qs[j];
609 const int lo = (packed & 0x0F);
610 const int hi = (packed >> 4);
611 const int xh_0 = ((qh >> (j + 0)) << 4) & 0x10;
612 const int xh_1 = ((qh >> (j + 12))) & 0x10;
613 const int w0 = (lo | xh_0) - 16;
614 const int w1 = (hi | xh_1) - 16;
615 sum += d * (w0 * xp[j] + w1 * xp[j +
QK5_0/2]);
631 if (!y || !W || !x || M <= 0 || K <= 0)
return;
632 if (ith < 0 || nth <= 0 || ith >= nth)
return;
634 const int dr = (M + nth - 1) / nth;
635 const int r0 = dr * ith;
636 const int r1 = (r0 + dr < M) ? (r0 + dr) : M;
640#if defined(__AVX__) || defined(__SSE4_1__)
642 const int blocks_per_row = K /
QK5_0;
644 const int PREFETCH_ROWS = 4;
645 for (
int p = 0; p < PREFETCH_ROWS && r0 + p < r1; ++p) {
646 const char *row_ptr = (
const char *)(blocks + (r0 + p) * blocks_per_row);
647 _mm_prefetch(row_ptr, _MM_HINT_T0);
648 _mm_prefetch(row_ptr + 64, _MM_HINT_T0);
651 for (
int row = r0; row < r1; ++row) {
653 if (row + PREFETCH_ROWS < r1) {
654 const char *prefetch_ptr = (
const char *)(blocks + (row + PREFETCH_ROWS) * blocks_per_row);
655 _mm_prefetch(prefetch_ptr, _MM_HINT_T0);
656 _mm_prefetch(prefetch_ptr + 64, _MM_HINT_T0);
660#if defined(__AVX512F__)
662 gemv_q5_0_avx512(&y[row], (
const char *)blocks + row * blocks_per_row *
sizeof(
block_q5_0), x, 1, K);
663#elif defined(__AVX2__)
664 gemv_q5_0_avx2(&y[row], (
const char *)blocks + row * blocks_per_row *
sizeof(
block_q5_0), x, 1, K);
665#elif defined(__AVX__)
666 gemv_q5_0_avx(&y[row], (
const char *)blocks + row * blocks_per_row *
sizeof(
block_q5_0), x, 1, K);
689 for (
int n = 0; n < N; n++) {
690 gemv_q5_0(&Y[n * M], W, &X[n * K], M, K);
713 const int blocks_per_row = K /
QK5_0;
716 memset(dX, 0, K *
sizeof(
float));
719 for (
int row = 0; row < M; row++) {
720 const float dy = dY[row];
722 for (
int b = 0; b < blocks_per_row; b++) {
723 const block_q5_0 *block = &blocks[row * blocks_per_row + b];
725 float *dxp = &dX[b *
QK5_0];
729 memcpy(&qh, block->
qh,
sizeof(qh));
732 for (
int j = 0; j <
QK5_0 / 2; j++) {
733 const uint8_t packed = block->
qs[j];
736 const int lo = (packed & 0x0F);
737 const int hi = (packed >> 4);
738 const int xh_0 = ((qh >> (j + 0)) << 4) & 0x10;
739 const int xh_1 = ((qh >> (j + 12))) & 0x10;
740 const int q0 = (lo | xh_0) - 16;
741 const int q1 = (hi | xh_1) - 16;
743 dxp[j] += d * (float)q0 * dy;
744 dxp[j + 16] += d * (float)q1 * dy;
769 for (
int n = 0; n < N; n++) {
797 const int blocks_per_row = K /
QK5_0;
799 for (
int m = 0; m < M; m++) {
800 const float *a_row = &A[m * K];
802 for (
int n = 0; n < N; n++) {
805 for (
int b = 0; b < blocks_per_row; b++) {
806 const block_q5_0 *block = &blocks[n * blocks_per_row + b];
808 const float *ap = &a_row[b *
QK5_0];
811 memcpy(&qh, block->
qh,
sizeof(qh));
814 for (
int j = 0; j <
QK5_0 / 2; j++) {
815 const uint8_t packed = block->
qs[j];
816 const int lo = (packed & 0x0F);
817 const int hi = (packed >> 4);
818 const int xh_0 = ((qh >> (j + 0)) << 4) & 0x10;
819 const int xh_1 = ((qh >> (j + 12))) & 0x10;
820 const int q0 = (lo | xh_0) - 16;
821 const int q1 = (hi | xh_1) - 16;
823 sum += d * (float)q0 * ap[j];
824 sum += d * (float)q1 * ap[j + 16];
828 C[m * N + n] = sum + (bias ? bias[n] : 0.0f);
845 for (
int n = 0; n < N; n++) {
859 for (
int m = 0; m < M; m++) {
860 float *row =
C + (size_t)m * (
size_t)N;
861 for (
int n = 0; n < N; n++) {
872float dot_q5_0(
const void *w_q5_0,
const float *x,
int K)
903 const int qk =
QK5_0;
904 const int nb = n / qk;
911 for (
int ib = 0; ib < nb; ib++) {
914 memcpy(&qh, x[ib].qh,
sizeof(qh));
919 for (
int j = 0; j < qk / 2; j++) {
921 const uint8_t xh_0 = ((qh & (1u << (j + 0))) >> (j + 0)) << 4;
922 const uint8_t xh_1 = ((qh & (1u << (j + 16))) >> (j + 12));
925 const int32_t x0 = (int8_t)(((x[ib].qs[j] & 0x0F) | xh_0) - 16);
926 const int32_t x1 = (int8_t)(((x[ib].qs[j] >> 4) | xh_1) - 16);
929 sumi0 += x0 * y[ib].
qs[j];
930 sumi1 += x1 * y[ib].
qs[j + qk / 2];
933 int sumi = sumi0 + sumi1;
940#if defined(__ARM_NEON) || defined(__aarch64__)
941static inline int32_t ck_hsum_s32x4(int32x4_t v)
945 return lanes[0] + lanes[1] + lanes[2] + lanes[3];
948void vec_dot_q5_0_q8_0_neon(
int n,
float *s,
const void *vx,
const void *vy)
950 const int qk =
QK5_0;
951 const int nb = n / qk;
958 for (
int ib = 0; ib < nb; ib++) {
960 memcpy(&qh, x[ib].qh,
sizeof(qh));
963 for (
int j = 0; j < qk / 2; j++) {
964 const uint8_t packed = x[ib].
qs[j];
965 const uint8_t xh_0 = ((qh >> (j + 0)) & 1u) << 4;
966 const uint8_t xh_1 = ((qh >> (j + 16)) & 1u) << 4;
968 wvals[j] = (int8_t)(((packed & 0x0F) | xh_0) - 16);
969 wvals[j + qk / 2] = (int8_t)(((packed >> 4) | xh_1) - 16);
972 const int8x16_t w0 = vld1q_s8(&wvals[0]);
973 const int8x16_t w1 = vld1q_s8(&wvals[16]);
974 const int8x16_t x0 = vld1q_s8(&y[ib].qs[0]);
975 const int8x16_t x1 = vld1q_s8(&y[ib].qs[16]);
977 int32x4_t acc = vdupq_n_s32(0);
979 int16x8_t p0 = vmull_s8(vget_low_s8(w0), vget_low_s8(x0));
980 int16x8_t p1 = vmull_s8(vget_high_s8(w0), vget_high_s8(x0));
981 int16x8_t p2 = vmull_s8(vget_low_s8(w1), vget_low_s8(x1));
982 int16x8_t p3 = vmull_s8(vget_high_s8(w1), vget_high_s8(x1));
984 acc = vaddq_s32(acc, vpaddlq_s16(p0));
985 acc = vaddq_s32(acc, vpaddlq_s16(p1));
986 acc = vaddq_s32(acc, vpaddlq_s16(p2));
987 acc = vaddq_s32(acc, vpaddlq_s16(p3));
990 sumf += d * (float)ck_hsum_s32x4(acc);
1001void vec_dot_q5_0_q8_0_avx512(
int n,
float *s,
const void *vx,
const void *vy)
1003 const int qk =
QK5_0;
1004 const int nb = n / qk;
1011 for (
int ib = 0; ib < nb; ib++) {
1016 memcpy(&qh, x[ib].qh,
sizeof(qh));
1019 __m128i qs = _mm_loadu_si128((
const __m128i *)x[ib].qs);
1022 __m512i lo_nibbles = _mm512_cvtepu8_epi32(qs);
1023 lo_nibbles = _mm512_and_epi32(lo_nibbles, _mm512_set1_epi32(0x0F));
1026 __m512i qh_lo = _mm512_set_epi32(
1027 ((qh >> 15) & 1) << 4, ((qh >> 14) & 1) << 4,
1028 ((qh >> 13) & 1) << 4, ((qh >> 12) & 1) << 4,
1029 ((qh >> 11) & 1) << 4, ((qh >> 10) & 1) << 4,
1030 ((qh >> 9) & 1) << 4, ((qh >> 8) & 1) << 4,
1031 ((qh >> 7) & 1) << 4, ((qh >> 6) & 1) << 4,
1032 ((qh >> 5) & 1) << 4, ((qh >> 4) & 1) << 4,
1033 ((qh >> 3) & 1) << 4, ((qh >> 2) & 1) << 4,
1034 ((qh >> 1) & 1) << 4, ((qh >> 0) & 1) << 4
1038 __m512i q5_lo = _mm512_sub_epi32(_mm512_or_epi32(lo_nibbles, qh_lo),
1039 _mm512_set1_epi32(16));
1042 __m128i y8_lo = _mm_loadu_si128((
const __m128i *)&y[ib].qs[0]);
1043 __m512i y32_lo = _mm512_cvtepi8_epi32(y8_lo);
1046 __m512i prod_lo = _mm512_mullo_epi32(q5_lo, y32_lo);
1049 __m512i hi_nibbles = _mm512_cvtepu8_epi32(qs);
1050 hi_nibbles = _mm512_srli_epi32(hi_nibbles, 4);
1053 __m512i qh_hi = _mm512_set_epi32(
1054 ((qh >> 31) & 1) << 4, ((qh >> 30) & 1) << 4,
1055 ((qh >> 29) & 1) << 4, ((qh >> 28) & 1) << 4,
1056 ((qh >> 27) & 1) << 4, ((qh >> 26) & 1) << 4,
1057 ((qh >> 25) & 1) << 4, ((qh >> 24) & 1) << 4,
1058 ((qh >> 23) & 1) << 4, ((qh >> 22) & 1) << 4,
1059 ((qh >> 21) & 1) << 4, ((qh >> 20) & 1) << 4,
1060 ((qh >> 19) & 1) << 4, ((qh >> 18) & 1) << 4,
1061 ((qh >> 17) & 1) << 4, ((qh >> 16) & 1) << 4
1064 __m512i q5_hi = _mm512_sub_epi32(_mm512_or_epi32(hi_nibbles, qh_hi),
1065 _mm512_set1_epi32(16));
1068 __m128i y8_hi = _mm_loadu_si128((
const __m128i *)&y[ib].qs[16]);
1069 __m512i y32_hi = _mm512_cvtepi8_epi32(y8_hi);
1071 __m512i prod_hi = _mm512_mullo_epi32(q5_hi, y32_hi);
1074 int sumi = _mm512_reduce_add_epi32(_mm512_add_epi32(prod_lo, prod_hi));
1077 sumf += d * (float)sumi;
1084#if defined(__AVX2__)
1085static inline __m256i bytes_from_bits_32_avx(
const uint8_t *qh);
1086static inline __m256i bytes_from_nibbles_32_avx(
const uint8_t *qs);
1087static inline __m256 mul_sum_i8_pairs_float_avx(
const __m256i x,
const __m256i y);
1088static inline float hsum_float_8_avx(
const __m256 x);
1097void vec_dot_q5_0_q8_0_avx2(
int n,
float *s,
const void *vx,
const void *vy)
1099 const int qk =
QK5_0;
1100 const int nb = n / qk;
1105 __m256 acc = _mm256_setzero_ps();
1107 for (
int ib = 0; ib < nb; ++ib) {
1111 __m256i qx = bytes_from_nibbles_32_avx(x[ib].qs);
1112 __m256i bxhi = bytes_from_bits_32_avx(x[ib].qh);
1113 bxhi = _mm256_andnot_si256(bxhi, _mm256_set1_epi8((
char)0xF0));
1114 qx = _mm256_or_si256(qx, bxhi);
1116 const __m256i qy = _mm256_loadu_si256((
const __m256i *)y[ib].qs);
1117 const __m256 q = mul_sum_i8_pairs_float_avx(qx, qy);
1119 acc = _mm256_fmadd_ps(d, q, acc);
1121 acc = _mm256_add_ps(_mm256_mul_ps(d, q), acc);
1125 *s = hsum_float_8_avx(acc);
1129#if defined(__SSSE3__)
1137static inline void bytes_from_bits_32_sse(__m128i *out_lo, __m128i *out_hi,
const uint8_t *qh)
1140 memcpy(&x32, qh,
sizeof(uint32_t));
1143 const __m128i shuf_maskl = _mm_set_epi64x(0x0101010101010101LL, 0x0000000000000000LL);
1144 const __m128i shuf_maskh = _mm_set_epi64x(0x0303030303030303LL, 0x0202020202020202LL);
1146 __m128i bytes_lo = _mm_shuffle_epi8(_mm_set1_epi32(x32), shuf_maskl);
1147 __m128i bytes_hi = _mm_shuffle_epi8(_mm_set1_epi32(x32), shuf_maskh);
1152 const __m128i bit_mask = _mm_set1_epi64x(0x7fbfdfeff7fbfdfeLL);
1154 bytes_lo = _mm_or_si128(bytes_lo, bit_mask);
1155 bytes_hi = _mm_or_si128(bytes_hi, bit_mask);
1158 *out_lo = _mm_cmpeq_epi8(bytes_lo, _mm_set1_epi64x(-1LL));
1159 *out_hi = _mm_cmpeq_epi8(bytes_hi, _mm_set1_epi64x(-1LL));
1168static inline __m128i mul_sum_i8_pairs_sse(
const __m128i x,
const __m128i y)
1170 const __m128i ax = _mm_sign_epi8(x, x);
1171 const __m128i sy = _mm_sign_epi8(y, x);
1172 const __m128i dot = _mm_maddubs_epi16(ax, sy);
1173 return _mm_madd_epi16(dot, _mm_set1_epi16(1));
1188void vec_dot_q5_0_q8_0_sse(
int n,
float *s,
const void *vx,
const void *vy)
1190 const int qk =
QK5_0;
1191 const int nb = n / qk;
1198 const __m128i mask_0f = _mm_set1_epi8(0x0F);
1199 const __m128i mask_f0 = _mm_set1_epi8((
char)0xF0);
1201 for (
int ib = 0; ib < nb; ib++) {
1205 __m128i qs = _mm_loadu_si128((
const __m128i *)x[ib].qs);
1208 __m128i bx_lo = _mm_and_si128(qs, mask_0f);
1209 __m128i bx_hi = _mm_and_si128(_mm_srli_epi16(qs, 4), mask_0f);
1212 __m128i bxhi_lo, bxhi_hi;
1213 bytes_from_bits_32_sse(&bxhi_lo, &bxhi_hi, x[ib].qh);
1218 bxhi_lo = _mm_andnot_si128(bxhi_lo, mask_f0);
1219 bxhi_hi = _mm_andnot_si128(bxhi_hi, mask_f0);
1222 bx_lo = _mm_or_si128(bx_lo, bxhi_lo);
1223 bx_hi = _mm_or_si128(bx_hi, bxhi_hi);
1226 __m128i by_lo = _mm_loadu_si128((
const __m128i *)y[ib].qs);
1227 __m128i by_hi = _mm_loadu_si128((
const __m128i *)(y[ib].qs + 16));
1230 __m128i p_lo = mul_sum_i8_pairs_sse(bx_lo, by_lo);
1231 __m128i p_hi = mul_sum_i8_pairs_sse(bx_hi, by_hi);
1234 __m128i sum = _mm_add_epi32(p_lo, p_hi);
1237 __m128i hi64 = _mm_unpackhi_epi64(sum, sum);
1238 __m128i sum64 = _mm_add_epi32(hi64, sum);
1239 __m128i hi32 = _mm_shuffle_epi32(sum64, _MM_SHUFFLE(2, 3, 0, 1));
1240 int32_t sumi = _mm_cvtsi128_si32(_mm_add_epi32(sum64, hi32));
1243 sumf += d * (float)sumi;
1253#define MM256_SET_M128I(hi, lo) _mm256_insertf128_si256(_mm256_castsi128_si256(lo), (hi), 1)
1259static inline __m256i bytes_from_bits_32_avx(
const uint8_t *qh)
1262 memcpy(&x32, qh,
sizeof(uint32_t));
1264 const __m128i shuf_maskl = _mm_set_epi64x(0x0101010101010101LL, 0x0000000000000000LL);
1265 const __m128i shuf_maskh = _mm_set_epi64x(0x0303030303030303LL, 0x0202020202020202LL);
1267 __m128i bytesl = _mm_shuffle_epi8(_mm_set1_epi32(x32), shuf_maskl);
1268 __m128i bytesh = _mm_shuffle_epi8(_mm_set1_epi32(x32), shuf_maskh);
1270 const __m128i bit_mask = _mm_set1_epi64x(0x7fbfdfeff7fbfdfeLL);
1272 bytesl = _mm_or_si128(bytesl, bit_mask);
1273 bytesh = _mm_or_si128(bytesh, bit_mask);
1275 bytesl = _mm_cmpeq_epi8(bytesl, _mm_set1_epi64x(-1LL));
1276 bytesh = _mm_cmpeq_epi8(bytesh, _mm_set1_epi64x(-1LL));
1278 return MM256_SET_M128I(bytesh, bytesl);
1284static inline __m256i bytes_from_nibbles_32_avx(
const uint8_t *qs)
1286 __m128i tmpl = _mm_loadu_si128((
const __m128i *)qs);
1287 __m128i tmph = _mm_srli_epi16(tmpl, 4);
1288 const __m128i lowMask = _mm_set1_epi8(0x0F);
1289 tmpl = _mm_and_si128(lowMask, tmpl);
1290 tmph = _mm_and_si128(lowMask, tmph);
1291 return MM256_SET_M128I(tmph, tmpl);
1298static inline __m256 mul_sum_i8_pairs_float_avx(
const __m256i x,
const __m256i y)
1300 const __m128i xl = _mm256_castsi256_si128(x);
1301 const __m128i xh = _mm256_extractf128_si256(x, 1);
1302 const __m128i yl = _mm256_castsi256_si128(y);
1303 const __m128i yh = _mm256_extractf128_si256(y, 1);
1306 const __m128i axl = _mm_sign_epi8(xl, xl);
1307 const __m128i axh = _mm_sign_epi8(xh, xh);
1309 const __m128i syl = _mm_sign_epi8(yl, xl);
1310 const __m128i syh = _mm_sign_epi8(yh, xh);
1313 const __m128i dotl = _mm_maddubs_epi16(axl, syl);
1314 const __m128i doth = _mm_maddubs_epi16(axh, syh);
1317 const __m128i ones = _mm_set1_epi16(1);
1318 const __m128i summed_pairsl = _mm_madd_epi16(ones, dotl);
1319 const __m128i summed_pairsh = _mm_madd_epi16(ones, doth);
1322 const __m256i summed_pairs = MM256_SET_M128I(summed_pairsh, summed_pairsl);
1323 return _mm256_cvtepi32_ps(summed_pairs);
1329static inline float hsum_float_8_avx(
const __m256 x)
1331 __m128 res = _mm256_extractf128_ps(x, 1);
1332 res = _mm_add_ps(res, _mm256_castps256_ps128(x));
1333 res = _mm_add_ps(res, _mm_movehl_ps(res, res));
1334 res = _mm_add_ss(res, _mm_movehdup_ps(res));
1335 return _mm_cvtss_f32(res);
1349void vec_dot_q5_0_q8_0_avx(
int n,
float *s,
const void *vx,
const void *vy)
1351 const int qk =
QK5_0;
1352 const int nb = n / qk;
1357 __m256 acc0 = _mm256_setzero_ps();
1358 __m256 acc1 = _mm256_setzero_ps();
1359 const __m128i
mask = _mm_set1_epi8((
char)0xF0);
1363 for (; ib + 1 < nb; ib += 2) {
1365 _mm_prefetch((
const char *)&x[ib + 4], _MM_HINT_T0);
1366 _mm_prefetch((
const char *)&y[ib + 4], _MM_HINT_T0);
1372 __m256i bx0 = bytes_from_nibbles_32_avx(x[ib].qs);
1375 const __m256i bxhi0 = bytes_from_bits_32_avx(x[ib].qh);
1376 __m128i bxhil0 = _mm256_castsi256_si128(bxhi0);
1377 __m128i bxhih0 = _mm256_extractf128_si256(bxhi0, 1);
1382 __m256i bx1 = bytes_from_nibbles_32_avx(x[ib+1].qs);
1383 const __m256i bxhi1 = bytes_from_bits_32_avx(x[ib+1].qh);
1384 __m128i bxhil1 = _mm256_castsi256_si128(bxhi1);
1385 __m128i bxhih1 = _mm256_extractf128_si256(bxhi1, 1);
1388 bxhil0 = _mm_andnot_si128(bxhil0,
mask);
1389 bxhih0 = _mm_andnot_si128(bxhih0,
mask);
1391 __m128i bxl0 = _mm256_castsi256_si128(bx0);
1392 __m128i bxh0 = _mm256_extractf128_si256(bx0, 1);
1393 bxl0 = _mm_or_si128(bxl0, bxhil0);
1394 bxh0 = _mm_or_si128(bxh0, bxhih0);
1395 bx0 = MM256_SET_M128I(bxh0, bxl0);
1397 const __m256i by0 = _mm256_loadu_si256((
const __m256i *)y[ib].qs);
1398 const __m256 q0 = mul_sum_i8_pairs_float_avx(bx0, by0);
1399 acc0 = _mm256_add_ps(_mm256_mul_ps(d0, q0), acc0);
1402 bxhil1 = _mm_andnot_si128(bxhil1,
mask);
1403 bxhih1 = _mm_andnot_si128(bxhih1,
mask);
1405 __m128i bxl1 = _mm256_castsi256_si128(bx1);
1406 __m128i bxh1 = _mm256_extractf128_si256(bx1, 1);
1407 bxl1 = _mm_or_si128(bxl1, bxhil1);
1408 bxh1 = _mm_or_si128(bxh1, bxhih1);
1409 bx1 = MM256_SET_M128I(bxh1, bxl1);
1411 const __m256i by1 = _mm256_loadu_si256((
const __m256i *)y[ib+1].qs);
1412 const __m256 q1 = mul_sum_i8_pairs_float_avx(bx1, by1);
1413 acc1 = _mm256_add_ps(_mm256_mul_ps(d1, q1), acc1);
1417 for (; ib < nb; ib++) {
1420 __m256i bx_0 = bytes_from_nibbles_32_avx(x[ib].qs);
1421 const __m256i bxhi = bytes_from_bits_32_avx(x[ib].qh);
1422 __m128i bxhil = _mm256_castsi256_si128(bxhi);
1423 __m128i bxhih = _mm256_extractf128_si256(bxhi, 1);
1425 bxhil = _mm_andnot_si128(bxhil,
mask);
1426 bxhih = _mm_andnot_si128(bxhih,
mask);
1428 __m128i bxl = _mm256_castsi256_si128(bx_0);
1429 __m128i bxh = _mm256_extractf128_si256(bx_0, 1);
1430 bxl = _mm_or_si128(bxl, bxhil);
1431 bxh = _mm_or_si128(bxh, bxhih);
1432 bx_0 = MM256_SET_M128I(bxh, bxl);
1434 const __m256i by_0 = _mm256_loadu_si256((
const __m256i *)y[ib].qs);
1435 const __m256 q = mul_sum_i8_pairs_float_avx(bx_0, by_0);
1436 acc0 = _mm256_add_ps(_mm256_mul_ps(d, q), acc0);
1440 acc0 = _mm256_add_ps(acc0, acc1);
1441 *s = hsum_float_8_avx(acc0);
1473 int M,
int N,
int K)
1475 const int nb = K /
QK5_0;
1478 const __m128i
mask = _mm_set1_epi8((
char)0xF0);
1480 for (
int m = 0; m < M; m++) {
1481 const block_q8_0 *a_row = a_blocks + (size_t)m * nb;
1485 for (; n + 1 < N; n += 2) {
1486 const block_q5_0 *w0 = b_blocks + (size_t)(n + 0) * nb;
1487 const block_q5_0 *w1 = b_blocks + (size_t)(n + 1) * nb;
1489 __m256 acc_n0 = _mm256_setzero_ps();
1490 __m256 acc_n1 = _mm256_setzero_ps();
1492 for (
int ib = 0; ib < nb; ib++) {
1495 _mm_prefetch((
const char *)&w0[ib + 2], _MM_HINT_T0);
1496 _mm_prefetch((
const char *)&w1[ib + 2], _MM_HINT_T0);
1500 const __m256i by = _mm256_loadu_si256((
const __m256i *)a_row[ib].qs);
1508 __m256i bx = bytes_from_nibbles_32_avx(w0[ib].qs);
1511 const __m256i bxhi = bytes_from_bits_32_avx(w0[ib].qh);
1512 __m128i bxhil = _mm256_castsi256_si128(bxhi);
1513 __m128i bxhih = _mm256_extractf128_si256(bxhi, 1);
1516 bxhil = _mm_andnot_si128(bxhil,
mask);
1517 bxhih = _mm_andnot_si128(bxhih,
mask);
1518 __m128i bxl = _mm256_castsi256_si128(bx);
1519 __m128i bxh = _mm256_extractf128_si256(bx, 1);
1520 bxl = _mm_or_si128(bxl, bxhil);
1521 bxh = _mm_or_si128(bxh, bxhih);
1522 bx = MM256_SET_M128I(bxh, bxl);
1525 const __m256 q = mul_sum_i8_pairs_float_avx(bx, by);
1526 acc_n0 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(d), q), acc_n0);
1533 __m256i bx = bytes_from_nibbles_32_avx(w1[ib].qs);
1534 const __m256i bxhi = bytes_from_bits_32_avx(w1[ib].qh);
1535 __m128i bxhil = _mm256_castsi256_si128(bxhi);
1536 __m128i bxhih = _mm256_extractf128_si256(bxhi, 1);
1538 bxhil = _mm_andnot_si128(bxhil,
mask);
1539 bxhih = _mm_andnot_si128(bxhih,
mask);
1540 __m128i bxl = _mm256_castsi256_si128(bx);
1541 __m128i bxh = _mm256_extractf128_si256(bx, 1);
1542 bxl = _mm_or_si128(bxl, bxhil);
1543 bxh = _mm_or_si128(bxh, bxhih);
1544 bx = MM256_SET_M128I(bxh, bxl);
1546 const __m256 q = mul_sum_i8_pairs_float_avx(bx, by);
1547 acc_n1 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(d), q), acc_n1);
1552 float s0 = hsum_float_8_avx(acc_n0);
1553 float s1 = hsum_float_8_avx(acc_n1);
1554 if (bias) { s0 += bias[n]; s1 += bias[n + 1]; }
1555 C[(size_t)m * N + n] = s0;
1556 C[(size_t)m * N + n + 1] = s1;
1560 for (; n < N; n++) {
1561 const block_q5_0 *w = b_blocks + (size_t)n * nb;
1562 __m256 acc = _mm256_setzero_ps();
1564 for (
int ib = 0; ib < nb; ib++) {
1565 const __m256i by = _mm256_loadu_si256((
const __m256i *)a_row[ib].qs);
1568 __m256i bx = bytes_from_nibbles_32_avx(w[ib].qs);
1569 const __m256i bxhi = bytes_from_bits_32_avx(w[ib].qh);
1570 __m128i bxhil = _mm256_castsi256_si128(bxhi);
1571 __m128i bxhih = _mm256_extractf128_si256(bxhi, 1);
1572 bxhil = _mm_andnot_si128(bxhil,
mask);
1573 bxhih = _mm_andnot_si128(bxhih,
mask);
1574 __m128i bxl = _mm256_castsi256_si128(bx);
1575 __m128i bxh = _mm256_extractf128_si256(bx, 1);
1576 bxl = _mm_or_si128(bxl, bxhil);
1577 bxh = _mm_or_si128(bxh, bxhih);
1578 bx = MM256_SET_M128I(bxh, bxl);
1580 const __m256 q = mul_sum_i8_pairs_float_avx(bx, by);
1581 acc = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(d), q), acc);
1584 float s = hsum_float_8_avx(acc);
1585 if (bias) s += bias[n];
1586 C[(size_t)m * N + n] = s;
1604#if defined(__AVX2__)
1608 vec_dot_q5_0_q8_0_avx2(n, s, vx, vy);
1609#elif defined(__AVX512F__)
1610 vec_dot_q5_0_q8_0_avx512(n, s, vx, vy);
1611#elif defined(__ARM_NEON) || defined(__aarch64__)
1612 vec_dot_q5_0_q8_0_neon(n, s, vx, vy);
1613#elif defined(__AVX__)
1615 vec_dot_q5_0_q8_0_avx(n, s, vx, vy);
1616#elif defined(__SSSE3__)
1618 vec_dot_q5_0_q8_0_sse(n, s, vx, vy);
1647 const int blocks_per_row = K /
QK5_0;
1649 for (
int row = 0; row < M; row++) {
1651 &w_blocks[row * blocks_per_row],
1668 if (!y || !W || !x_q8 || M <= 0 || K <= 0)
return;
1669 if (ith < 0 || nth <= 0 || ith >= nth)
return;
1671 const int dr = (M + nth - 1) / nth;
1672 const int r0 = dr * ith;
1673 const int r1 = (r0 + dr < M) ? (r0 + dr) : M;
1675 if (r0 >= M)
return;
1679 const int blocks_per_row = K /
QK5_0;
1681#if defined(__AVX__) || defined(__SSE4_1__)
1682 const int PREFETCH_ROWS = 4;
1683 for (
int p = 0; p < PREFETCH_ROWS && r0 + p < r1; ++p) {
1684 const char *row_ptr = (
const char *)(w_blocks + (r0 + p) * blocks_per_row);
1685 _mm_prefetch(row_ptr, _MM_HINT_T0);
1686 _mm_prefetch(row_ptr + 64, _MM_HINT_T0);
1689 for (
int row = r0; row < r1; ++row) {
1690 if (row + PREFETCH_ROWS < r1) {
1691 const char *pf = (
const char *)(w_blocks + (row + PREFETCH_ROWS) * blocks_per_row);
1692 _mm_prefetch(pf, _MM_HINT_T0);
1693 _mm_prefetch(pf + 64, _MM_HINT_T0);
1697 &w_blocks[row * blocks_per_row],
1701 for (
int row = r0; row < r1; row++) {
1703 &w_blocks[row * blocks_per_row],
1739 const int blocks_per_row = K /
QK5_0;
1741 for (
int m = 0; m < M; m++) {
1742 const block_q8_0 *input_row = &inputs[m * blocks_per_row];
1744 for (
int n = 0; n < N; n++) {
1745 const block_q5_0 *weight_row = &weights[n * blocks_per_row];
1746 float *out = &
C[m * N + n];
1776#if defined(__AVX2__)
1777 if (!A_q8 || !B_q5 || !
C || M <= 0 || N <= 0 || K <= 0 ||
1778 (K %
QK5_0) != 0 || ldc < N) {
1784 const int nb = K /
QK5_0;
1787 for (; m + 1 < M; m += 2) {
1788 const block_q8_0 *a0 = a + (size_t)(m + 0) * (size_t)nb;
1789 const block_q8_0 *a1 = a + (size_t)(m + 1) * (size_t)nb;
1792 for (; n + 3 < N; n += 4) {
1793 const block_q5_0 *w0 = w + (size_t)(n + 0) * (size_t)nb;
1794 const block_q5_0 *w1 = w + (size_t)(n + 1) * (size_t)nb;
1795 const block_q5_0 *w2 = w + (size_t)(n + 2) * (size_t)nb;
1796 const block_q5_0 *w3 = w + (size_t)(n + 3) * (size_t)nb;
1797 __m256 acc00 = _mm256_setzero_ps();
1798 __m256 acc01 = _mm256_setzero_ps();
1799 __m256 acc02 = _mm256_setzero_ps();
1800 __m256 acc03 = _mm256_setzero_ps();
1801 __m256 acc10 = _mm256_setzero_ps();
1802 __m256 acc11 = _mm256_setzero_ps();
1803 __m256 acc12 = _mm256_setzero_ps();
1804 __m256 acc13 = _mm256_setzero_ps();
1806 for (
int ib = 0; ib < nb; ++ib) {
1807 __m256i qw0 = bytes_from_nibbles_32_avx(w0[ib].qs);
1808 __m256i qw1 = bytes_from_nibbles_32_avx(w1[ib].qs);
1809 __m256i qw2 = bytes_from_nibbles_32_avx(w2[ib].qs);
1810 __m256i qw3 = bytes_from_nibbles_32_avx(w3[ib].qs);
1811 const __m256i sign = _mm256_set1_epi8((
char)0xF0);
1812 qw0 = _mm256_or_si256(qw0, _mm256_andnot_si256(bytes_from_bits_32_avx(w0[ib].qh), sign));
1813 qw1 = _mm256_or_si256(qw1, _mm256_andnot_si256(bytes_from_bits_32_avx(w1[ib].qh), sign));
1814 qw2 = _mm256_or_si256(qw2, _mm256_andnot_si256(bytes_from_bits_32_avx(w2[ib].qh), sign));
1815 qw3 = _mm256_or_si256(qw3, _mm256_andnot_si256(bytes_from_bits_32_avx(w3[ib].qh), sign));
1817 const __m256i qa0 = _mm256_loadu_si256((
const __m256i *)a0[ib].qs);
1818 const __m256i qa1 = _mm256_loadu_si256((
const __m256i *)a1[ib].qs);
1825 const __m256 p00 = mul_sum_i8_pairs_float_avx(qw0, qa0);
1826 const __m256 p01 = mul_sum_i8_pairs_float_avx(qw1, qa0);
1827 const __m256 p02 = mul_sum_i8_pairs_float_avx(qw2, qa0);
1828 const __m256 p03 = mul_sum_i8_pairs_float_avx(qw3, qa0);
1829 const __m256 p10 = mul_sum_i8_pairs_float_avx(qw0, qa1);
1830 const __m256 p11 = mul_sum_i8_pairs_float_avx(qw1, qa1);
1831 const __m256 p12 = mul_sum_i8_pairs_float_avx(qw2, qa1);
1832 const __m256 p13 = mul_sum_i8_pairs_float_avx(qw3, qa1);
1834 acc00 = _mm256_fmadd_ps(_mm256_set1_ps(dw0 * da0), p00, acc00);
1835 acc01 = _mm256_fmadd_ps(_mm256_set1_ps(dw1 * da0), p01, acc01);
1836 acc02 = _mm256_fmadd_ps(_mm256_set1_ps(dw2 * da0), p02, acc02);
1837 acc03 = _mm256_fmadd_ps(_mm256_set1_ps(dw3 * da0), p03, acc03);
1838 acc10 = _mm256_fmadd_ps(_mm256_set1_ps(dw0 * da1), p10, acc10);
1839 acc11 = _mm256_fmadd_ps(_mm256_set1_ps(dw1 * da1), p11, acc11);
1840 acc12 = _mm256_fmadd_ps(_mm256_set1_ps(dw2 * da1), p12, acc12);
1841 acc13 = _mm256_fmadd_ps(_mm256_set1_ps(dw3 * da1), p13, acc13);
1843 acc00 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw0 * da0), p00), acc00);
1844 acc01 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw1 * da0), p01), acc01);
1845 acc02 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw2 * da0), p02), acc02);
1846 acc03 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw3 * da0), p03), acc03);
1847 acc10 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw0 * da1), p10), acc10);
1848 acc11 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw1 * da1), p11), acc11);
1849 acc12 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw2 * da1), p12), acc12);
1850 acc13 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw3 * da1), p13), acc13);
1854 C[(size_t)(m + 0) * (size_t)ldc + n + 0] = hsum_float_8_avx(acc00) + (bias ? bias[n + 0] : 0.0f);
1855 C[(size_t)(m + 0) * (size_t)ldc + n + 1] = hsum_float_8_avx(acc01) + (bias ? bias[n + 1] : 0.0f);
1856 C[(size_t)(m + 0) * (size_t)ldc + n + 2] = hsum_float_8_avx(acc02) + (bias ? bias[n + 2] : 0.0f);
1857 C[(size_t)(m + 0) * (size_t)ldc + n + 3] = hsum_float_8_avx(acc03) + (bias ? bias[n + 3] : 0.0f);
1858 C[(size_t)(m + 1) * (size_t)ldc + n + 0] = hsum_float_8_avx(acc10) + (bias ? bias[n + 0] : 0.0f);
1859 C[(size_t)(m + 1) * (size_t)ldc + n + 1] = hsum_float_8_avx(acc11) + (bias ? bias[n + 1] : 0.0f);
1860 C[(size_t)(m + 1) * (size_t)ldc + n + 2] = hsum_float_8_avx(acc12) + (bias ? bias[n + 2] : 0.0f);
1861 C[(size_t)(m + 1) * (size_t)ldc + n + 3] = hsum_float_8_avx(acc13) + (bias ? bias[n + 3] : 0.0f);
1864 for (; n < N; ++n) {
1865 const block_q5_0 *wn = w + (size_t)n * (
size_t)nb;
1869 C[(size_t)(m + 0) * (size_t)ldc + n] += bias[n];
1870 C[(size_t)(m + 1) * (size_t)ldc + n] += bias[n];
1877 a + (
size_t)m * (
size_t)nb, w, bias,
1878 C + (
size_t)m * (
size_t)ldc, 1, N, K);
1884 const int nb = K /
QK5_0;
1886 for (
int m = 0; m < M; ++m) {
1888 C + (
size_t)m * (
size_t)ldc, 1, N, K);
1918#if defined(__AVX2__)
1919 if (!A_q8 || !B_q5 || !
C || M <= 0 || N <= 0 || K <= 0 ||
1920 (K %
QK5_0) != 0 || ldc < N) {
1926 const int nb = K /
QK5_0;
1929 for (; m + 3 < M; m += 4) {
1930 const block_q8_0 *a0 = a + (size_t)(m + 0) * (size_t)nb;
1931 const block_q8_0 *a1 = a + (size_t)(m + 1) * (size_t)nb;
1932 const block_q8_0 *a2 = a + (size_t)(m + 2) * (size_t)nb;
1933 const block_q8_0 *a3 = a + (size_t)(m + 3) * (size_t)nb;
1936 for (; n + 1 < N; n += 2) {
1937 const block_q5_0 *w0 = w + (size_t)(n + 0) * (size_t)nb;
1938 const block_q5_0 *w1 = w + (size_t)(n + 1) * (size_t)nb;
1939 __m256 acc00 = _mm256_setzero_ps();
1940 __m256 acc01 = _mm256_setzero_ps();
1941 __m256 acc10 = _mm256_setzero_ps();
1942 __m256 acc11 = _mm256_setzero_ps();
1943 __m256 acc20 = _mm256_setzero_ps();
1944 __m256 acc21 = _mm256_setzero_ps();
1945 __m256 acc30 = _mm256_setzero_ps();
1946 __m256 acc31 = _mm256_setzero_ps();
1948 for (
int ib = 0; ib < nb; ++ib) {
1949 __m256i qw0 = bytes_from_nibbles_32_avx(w0[ib].qs);
1950 __m256i qw1 = bytes_from_nibbles_32_avx(w1[ib].qs);
1951 const __m256i sign = _mm256_set1_epi8((
char)0xF0);
1952 qw0 = _mm256_or_si256(qw0, _mm256_andnot_si256(bytes_from_bits_32_avx(w0[ib].qh), sign));
1953 qw1 = _mm256_or_si256(qw1, _mm256_andnot_si256(bytes_from_bits_32_avx(w1[ib].qh), sign));
1955 const __m256i qa0 = _mm256_loadu_si256((
const __m256i *)a0[ib].qs);
1956 const __m256i qa1 = _mm256_loadu_si256((
const __m256i *)a1[ib].qs);
1957 const __m256i qa2 = _mm256_loadu_si256((
const __m256i *)a2[ib].qs);
1958 const __m256i qa3 = _mm256_loadu_si256((
const __m256i *)a3[ib].qs);
1966 acc00 = _mm256_fmadd_ps(_mm256_set1_ps(dw0 * da0), mul_sum_i8_pairs_float_avx(qw0, qa0), acc00);
1967 acc01 = _mm256_fmadd_ps(_mm256_set1_ps(dw1 * da0), mul_sum_i8_pairs_float_avx(qw1, qa0), acc01);
1968 acc10 = _mm256_fmadd_ps(_mm256_set1_ps(dw0 * da1), mul_sum_i8_pairs_float_avx(qw0, qa1), acc10);
1969 acc11 = _mm256_fmadd_ps(_mm256_set1_ps(dw1 * da1), mul_sum_i8_pairs_float_avx(qw1, qa1), acc11);
1970 acc20 = _mm256_fmadd_ps(_mm256_set1_ps(dw0 * da2), mul_sum_i8_pairs_float_avx(qw0, qa2), acc20);
1971 acc21 = _mm256_fmadd_ps(_mm256_set1_ps(dw1 * da2), mul_sum_i8_pairs_float_avx(qw1, qa2), acc21);
1972 acc30 = _mm256_fmadd_ps(_mm256_set1_ps(dw0 * da3), mul_sum_i8_pairs_float_avx(qw0, qa3), acc30);
1973 acc31 = _mm256_fmadd_ps(_mm256_set1_ps(dw1 * da3), mul_sum_i8_pairs_float_avx(qw1, qa3), acc31);
1975 acc00 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw0 * da0), mul_sum_i8_pairs_float_avx(qw0, qa0)), acc00);
1976 acc01 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw1 * da0), mul_sum_i8_pairs_float_avx(qw1, qa0)), acc01);
1977 acc10 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw0 * da1), mul_sum_i8_pairs_float_avx(qw0, qa1)), acc10);
1978 acc11 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw1 * da1), mul_sum_i8_pairs_float_avx(qw1, qa1)), acc11);
1979 acc20 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw0 * da2), mul_sum_i8_pairs_float_avx(qw0, qa2)), acc20);
1980 acc21 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw1 * da2), mul_sum_i8_pairs_float_avx(qw1, qa2)), acc21);
1981 acc30 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw0 * da3), mul_sum_i8_pairs_float_avx(qw0, qa3)), acc30);
1982 acc31 = _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(dw1 * da3), mul_sum_i8_pairs_float_avx(qw1, qa3)), acc31);
1986 C[(size_t)(m + 0) * (size_t)ldc + n + 0] = hsum_float_8_avx(acc00) + (bias ? bias[n + 0] : 0.0f);
1987 C[(size_t)(m + 0) * (size_t)ldc + n + 1] = hsum_float_8_avx(acc01) + (bias ? bias[n + 1] : 0.0f);
1988 C[(size_t)(m + 1) * (size_t)ldc + n + 0] = hsum_float_8_avx(acc10) + (bias ? bias[n + 0] : 0.0f);
1989 C[(size_t)(m + 1) * (size_t)ldc + n + 1] = hsum_float_8_avx(acc11) + (bias ? bias[n + 1] : 0.0f);
1990 C[(size_t)(m + 2) * (size_t)ldc + n + 0] = hsum_float_8_avx(acc20) + (bias ? bias[n + 0] : 0.0f);
1991 C[(size_t)(m + 2) * (size_t)ldc + n + 1] = hsum_float_8_avx(acc21) + (bias ? bias[n + 1] : 0.0f);
1992 C[(size_t)(m + 3) * (size_t)ldc + n + 0] = hsum_float_8_avx(acc30) + (bias ? bias[n + 0] : 0.0f);
1993 C[(size_t)(m + 3) * (size_t)ldc + n + 1] = hsum_float_8_avx(acc31) + (bias ? bias[n + 1] : 0.0f);
1997 const block_q5_0 *wn = w + (size_t)n * (
size_t)nb;
1998 const block_q8_0 *rows[4] = {a0, a1, a2, a3};
1999 for (
int r = 0; r < 4; ++r) {
2000 float *out = &
C[(size_t)(m + r) * (size_t)ldc + n];
2002 if (bias) *out += bias[n];
2009 a + (
size_t)m * (
size_t)nb, w, bias,
2010 C + (
size_t)m * (
size_t)ldc, M - m, N, K, ldc);
CPU feature detection and dispatch macros.
Quantization block structures for weight-only quantization.
#define CK_FP16_TO_FP32(x)
void gemm_nt_q5_0_q8_0_unroll_avx(const void *A_q8, const void *B_q5, const float *bias, float *C, int M, int N, int K)
void gemm_nt_q5_0_sse_v2(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
void gemm_q5_0_backward(float *dX, const void *W, const float *dY, int M, int N, int K)
Batched backward pass.
void gemv_q5_0_backward_ref(float *dX, const void *W, const float *dY, int M, int K)
Backward pass: compute input gradient.
void dequant_q5_0_block(const block_q5_0 *block, float *output)
Dequantize a single Q5_0 block to FP32.
void gemm_nt_q5_0_q8_0_m4n2(const void *A_q8, const void *B_q5, const float *bias, float *C, int M, int N, int K)
void dequant_q5_0_row(const void *src, float *dst, size_t n_elements)
Dequantize Q5_0 row (multiple blocks)
void gemv_q5_0_ref(float *y, const void *W, const float *x, int M, int K)
Matrix-vector multiply with Q5_0 weights (scalar reference)
void gemv_q5_0_backward(float *dX, const void *W, const float *dY, int M, int K)
Auto-dispatch backward.
void gemv_q5_0_q8_0(float *y, const void *W, const void *x_q8, int M, int K)
Matrix-vector multiply with Q5_0 weights and Q8_0 input.
void gemv_q5_0(float *y, const void *W, const float *x, int M, int K)
Auto-dispatch GEMV for Q5_0 weights based on CPU features.
void vec_dot_q5_0_q8_0_ref(int n, float *s, const void *vx, const void *vy)
Quantized dot product: Q5_0 weights x Q8_0 input (scalar reference)
void gemm_nt_q5_0(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
void vec_dot_q5_0_q8_0(int n, float *s, const void *vx, const void *vy)
Auto-dispatch quantized dot product Q5_0 x Q8_0.
void gemm_q5_0(float *Y, const void *W, const float *X, int M, int N, int K)
Matrix-matrix multiply with Q5_0 weights.
void gemm_nt_q5_0_q8_0_m4n2_tile(const void *A_q8, const void *B_q5, const float *bias, float *C, int M, int N, int K, int ldc)
void gemm_nt_q5_0_q8_0_m2n4_tile(const void *A_q8, const void *B_q5, const float *bias, float *C, int M, int N, int K, int ldc)
void gemm_nt_q5_0_ref(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
GEMM with transposed Q5_0 weights: C = A @ B^T.
void gemm_nt_q5_0_q8_0(const void *A_q8, const void *B_q5, const float *bias, float *C, int M, int N, int K)
Batch GEMM with Q5_0 weights and Q8_0 activations for prefill.
void gemv_q5_0_parallel(float *y, const void *W, const float *x, int M, int K, int ith, int nth)
Parallel reference GEMV for Q5_0 × FP32.
float dot_q5_0(const void *w_q5_0, const float *x, int K)
void gemm_nt_q5_0_q8_0_m2n4(const void *A_q8, const void *B_q5, const float *bias, float *C, int M, int N, int K)
void gemv_q5_0_q8_0_parallel_simd(float *y, const void *W, const void *x_q8, int M, int K, int ith, int nth)
Parallel SIMD GEMV for Q5_0 x Q8_0 with prefetching.
void gemv_q5_0_parallel_simd(float *y, const void *W, const float *x, int M, int K, int ith, int nth)
Parallel SIMD GEMV for Q5_0 × FP32 with prefetching.
int32_t int32_t int32_t int32_t int32_t mask