HelloSun commited on
Commit
fa0329a
·
1 Parent(s): 20c42e1

merge #27590 (Q5_K/Q6_K AVX-512 dots, -nr: +2.9% pp / +2.5% tg); PPL identical, backend-ops pass; update docs+LICENSE

Browse files
Files changed (3) hide show
  1. LICENSE +2 -0
  2. README.md +33 -1
  3. llama.cpp-openpangu-v0.7.0.diff +300 -0
LICENSE CHANGED
@@ -21,6 +21,8 @@ References / 引用(本專案用到的專案)
21
  and enable the VNNI path
22
  - PR #22525 — @HyeongiJeon — ggml-cpu: optimize ggml_gemm_q4_K_8x8_q8_K
23
  interleaving/staging for AVX-512 (and AVX2)
 
 
24
 
25
  4. ggml — MIT License — © ggml-org contributors
26
  https://github.com/ggml-org/ggml (隨 llama.cpp 一起提供)
 
21
  and enable the VNNI path
22
  - PR #22525 — @HyeongiJeon — ggml-cpu: optimize ggml_gemm_q4_K_8x8_q8_K
23
  interleaving/staging for AVX-512 (and AVX2)
24
+ - PR #27590 — @SongXiaoXi — ggml-cpu: add AVX-512 and VNNI paths for
25
+ Q5_K/Q6_K dot products(上游 closed 未併;本地已驗證後採用)
26
 
27
  4. ggml — MIT License — © ggml-org contributors
28
  https://github.com/ggml-org/ggml (隨 llama.cpp 一起提供)
README.md CHANGED
@@ -21,7 +21,7 @@ The support was ported from
21
 
22
  Files:
23
 
24
- - `llama.cpp-openpangu-v0.7.0.diff` — the full patch (42 files, +3055 / −347)
25
  - `patch.sh` — downloads the pinned llama.cpp commit, applies the patch and
26
  prints build/run instructions
27
  - `LICENSE` — GPL-3.0 (this project) with the references/licenses of the
@@ -259,6 +259,7 @@ their data and are **not** merged (❌ 沒幫助).
259
  | upstream PR [#27024](https://github.com/ggml-org/llama.cpp/pull/27024) by [@jinzihao](https://github.com/jinzihao) | ggml-cpu/amx: fix the (dead) `block_q8_K` VNNI quantization and enable the VNNI path | ✅ 有幫助 — merged | 57.25 → 59.20 (**+3.4 %**) | 10.94 → 11.24 (**+2.7 %**) |
260
  | upstream PR [#22525](https://github.com/ggml-org/llama.cpp/pull/22525) by [@HyeongiJeon](https://github.com/HyeongiJeon) | ggml-cpu: optimize `ggml_gemm_q4_K_8x8_q8_K` interleaving/staging for AVX-512 (and AVX2) | ✅ 有幫助(prefill)— merged | 55.78 → 57.42 (**+2.9 %**) | 10.70 → 10.87 (+1.5 %, neutral) |
261
  | upstream PR [#19706](https://github.com/ggml-org/llama.cpp/pull/19706) by [@Manogna-Sree](https://github.com/Manogna-Sree) | Q6_K block interleaving for x86 SIMD (AVX-512/AVX2) | ❌ 沒幫助 — not merged | 58.16 → 58.34 (+0.3 %) | 11.06 → 11.07 (+0.1 %) |
 
262
 
263
  Round-by-round for #27024 (candidate vs baseline, t/s):
264
 
@@ -314,6 +315,34 @@ noise. The base `Q3_K_M` model contains only **one** single `Q6_K` tensor,
314
  so a faster Q6_K kernel has almost no weight to act on. The PR is *not*
315
  merged; the data is recorded here for the record. Measured 2026-10-16.
316
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  ## License
318
 
319
  This project (the patch set, `patch.sh` and documentation) is licensed
@@ -329,4 +358,7 @@ with the references listed in the `LICENSE` header and repeated here:
329
  by [@jinzihao](https://github.com/jinzihao) — MIT (merged)
330
  - upstream PR [#22525](https://github.com/ggml-org/llama.cpp/pull/22525)
331
  by [@HyeongiJeon](https://github.com/HyeongiJeon) — MIT (merged)
 
 
 
332
  - [ggml](https://github.com/ggml-org/ggml) — MIT (bundled with llama.cpp)
 
21
 
22
  Files:
23
 
24
+ - `llama.cpp-openpangu-v0.7.0.diff` — the full patch (43 files, +3290 / −367)
25
  - `patch.sh` — downloads the pinned llama.cpp commit, applies the patch and
26
  prints build/run instructions
27
  - `LICENSE` — GPL-3.0 (this project) with the references/licenses of the
 
259
  | upstream PR [#27024](https://github.com/ggml-org/llama.cpp/pull/27024) by [@jinzihao](https://github.com/jinzihao) | ggml-cpu/amx: fix the (dead) `block_q8_K` VNNI quantization and enable the VNNI path | ✅ 有幫助 — merged | 57.25 → 59.20 (**+3.4 %**) | 10.94 → 11.24 (**+2.7 %**) |
260
  | upstream PR [#22525](https://github.com/ggml-org/llama.cpp/pull/22525) by [@HyeongiJeon](https://github.com/HyeongiJeon) | ggml-cpu: optimize `ggml_gemm_q4_K_8x8_q8_K` interleaving/staging for AVX-512 (and AVX2) | ✅ 有幫助(prefill)— merged | 55.78 → 57.42 (**+2.9 %**) | 10.70 → 10.87 (+1.5 %, neutral) |
261
  | upstream PR [#19706](https://github.com/ggml-org/llama.cpp/pull/19706) by [@Manogna-Sree](https://github.com/Manogna-Sree) | Q6_K block interleaving for x86 SIMD (AVX-512/AVX2) | ❌ 沒幫助 — not merged | 58.16 → 58.34 (+0.3 %) | 11.06 → 11.07 (+0.1 %) |
262
+ | upstream PR [#27590](https://github.com/ggml-org/llama.cpp/pull/27590) by [@SongXiaoXi](https://github.com/SongXiaoXi) | ggml-cpu: add AVX-512/VNNI paths for Q5_K/Q6_K dot products | ✅ 有幫助(`-nr`)— merged | `-nr`: 56.41 → 58.03 (**+2.9 %**) | `-nr`: 10.85 → 11.12 (**+2.5 %**) |
263
 
264
  Round-by-round for #27024 (candidate vs baseline, t/s):
265
 
 
315
  so a faster Q6_K kernel has almost no weight to act on. The PR is *not*
316
  merged; the data is recorded here for the record. Measured 2026-10-16.
317
 
318
+ Round-by-round for #27590 (candidate vs baseline, t/s), `-nr` mode. The
319
+ Q5_K/Q6_K dots this PR changes are used on the plain CPU path selected by
320
+ `-nr`; with default repacking those weights go through the repack gemv/gemm
321
+ kernels instead, and default mode indeed measured neutral
322
+ (pp512 −1.7 % / tg128 +1.0 %, within noise):
323
+
324
+ | round | pp512 | tg128 |
325
+ |---|---:|---:|
326
+ | 1 | 58.03 vs 58.58 | 11.65 vs 11.57 |
327
+ | 2 | 57.50 vs 56.41 | 11.57 vs 10.61 |
328
+ | 3 | 58.12 vs 56.24 | 11.67 vs 10.85 |
329
+ | 4 | 56.88 vs 53.06 | 10.77 vs 9.01 |
330
+ | 5 | 58.79 vs 56.58 | 11.12 vs 10.52 |
331
+ | 6 | 59.25 vs 56.38 | 11.01 vs 11.14 |
332
+ | 7 | 56.81 vs 58.01 | 10.91 vs 11.03 |
333
+
334
+ **Verdict ✅ 有幫助 (`-nr` 模式, +2.9 % prefill / +2.5 % decode medians,
335
+ 5 of 7 rounds won on both).** In this model the PR affects Q5_K (2 tensors,
336
+ the dense `ffn_down` of layers 0–1) and Q6_K (1 tensor — `output.weight`,
337
+ the 388 M-param head that is read on every token). One caveat: the upstream
338
+ PR is *closed but never merged* (only an automated AI-content flag, no
339
+ review), so it received extra local validation before merging:
340
+
341
+ - perplexity on a fixed corpus: 1.0354 → 1.0354 (identical)
342
+ - `test-backend-ops -b CPU -o MUL_MAT -p 'type=q5_K|type=q6_K'` passes
343
+
344
+ Merged. Measured 2026-10-16.
345
+
346
  ## License
347
 
348
  This project (the patch set, `patch.sh` and documentation) is licensed
 
358
  by [@jinzihao](https://github.com/jinzihao) — MIT (merged)
359
  - upstream PR [#22525](https://github.com/ggml-org/llama.cpp/pull/22525)
360
  by [@HyeongiJeon](https://github.com/HyeongiJeon) — MIT (merged)
361
+ - upstream PR [#27590](https://github.com/ggml-org/llama.cpp/pull/27590)
362
+ by [@SongXiaoXi](https://github.com/SongXiaoXi) — MIT (merged; closed
363
+ upstream unmerged, verified locally)
364
  - [ggml](https://github.com/ggml-org/ggml) — MIT (bundled with llama.cpp)
llama.cpp-openpangu-v0.7.0.diff CHANGED
@@ -725,6 +725,306 @@ index 9f3a744b5..2d79f714e 100644
725
  }
726
 
727
  // load A from memory to array when nrows can not fill in whole tile
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
728
  diff --git a/ggml/src/ggml-cpu/arch/x86/repack.cpp b/ggml/src/ggml-cpu/arch/x86/repack.cpp
729
  index af1cebad1..f30d822c5 100644
730
  --- a/ggml/src/ggml-cpu/arch/x86/repack.cpp
 
725
  }
726
 
727
  // load A from memory to array when nrows can not fill in whole tile
728
+ diff --git a/ggml/src/ggml-cpu/arch/x86/quants.c b/ggml/src/ggml-cpu/arch/x86/quants.c
729
+ index 21cd6312a..9d05aac0e 100644
730
+ --- a/ggml/src/ggml-cpu/arch/x86/quants.c
731
+ +++ b/ggml/src/ggml-cpu/arch/x86/quants.c
732
+ @@ -2302,11 +2302,107 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
733
+ const __m128i mzero = _mm_setzero_si128();
734
+ const __m256i mone = _mm256_set1_epi8(1);
735
+
736
+ - __m256 acc = _mm256_setzero_ps();
737
+ -
738
+ float summs = 0.f;
739
+
740
+ - for (int i = 0; i < nb; ++i) {
741
+ + int i = 0;
742
+ +
743
+ +#if defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512DQ__)
744
+ + __m512 acc512 = _mm512_setzero_ps();
745
+ + const __m256i scale_shuffle = _mm256_broadcastsi128_si256(_mm_setr_epi8(
746
+ + 0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 8, 9, 10, 11
747
+ + ));
748
+ + const __m256i scale_hi_shuffle = _mm256_broadcastsi128_si256(_mm_setr_epi8(
749
+ + -1, -1, -1, -1, 0, 1, 2, 3, -1, -1, -1, -1, 4, 5, 6, 7
750
+ + ));
751
+ + const __m256i scale_mask = _mm256_setr_epi32(kmask1, kmask2, kmask1, kmask2, kmask1, kmask2, kmask1, kmask2);
752
+ + const __m256i scale_hi_mask = _mm256_setr_epi32(0, kmask3, 0, kmask3, 0, kmask3, 0, kmask3);
753
+ +
754
+ + for (; i + 1 < nb; i += 2) {
755
+ + const __m256i scale_bytes = MM256_SET_M128I(
756
+ + _mm_loadu_si128((const __m128i *) x[i + 1].scales),
757
+ + _mm_loadu_si128((const __m128i *) x[i + 0].scales)
758
+ + );
759
+ + const __m256i scale_ordered = _mm256_shuffle_epi8(scale_bytes, scale_shuffle);
760
+ + const __m256i scale_low = _mm256_and_si256(_mm256_blend_epi32(scale_ordered, _mm256_srli_epi16(scale_ordered, 4), 0x88), scale_mask);
761
+ + const __m256i scale_high = _mm256_slli_epi16(_mm256_and_si256(_mm256_srli_epi16(_mm256_shuffle_epi8(scale_bytes, scale_hi_shuffle), 6), scale_hi_mask), 4);
762
+ + const __m256i mins_and_scales8 = _mm256_or_si256(scale_low, scale_high);
763
+ + const __m256i mins_and_scales0 = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(mins_and_scales8, 0));
764
+ + const __m256i mins_and_scales1 = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(mins_and_scales8, 1));
765
+ +
766
+ + const __m256i q8sums0 = _mm256_loadu_si256((const __m256i *) y[i + 0].bsums);
767
+ + const __m128i q8s0 = _mm_hadd_epi16(_mm256_extracti128_si256(q8sums0, 0), _mm256_extracti128_si256(q8sums0, 1));
768
+ + const __m128i prod0 = _mm_madd_epi16(_mm256_extracti128_si256(mins_and_scales0, 1), q8s0);
769
+ + const __m128i hsum0 = _mm_hadd_epi32(_mm_hadd_epi32(prod0, mzero), mzero);
770
+ + summs -= y[i + 0].d * GGML_CPU_FP16_TO_FP32(x[i + 0].dmin) * _mm_extract_epi32(hsum0, 0);
771
+ +
772
+ + const __m256i q8sums1 = _mm256_loadu_si256((const __m256i *) y[i + 1].bsums);
773
+ + const __m128i q8s1 = _mm_hadd_epi16(_mm256_extracti128_si256(q8sums1, 0), _mm256_extracti128_si256(q8sums1, 1));
774
+ + const __m128i prod1 = _mm_madd_epi16(_mm256_extracti128_si256(mins_and_scales1, 1), q8s1);
775
+ + const __m128i hsum1 = _mm_hadd_epi32(_mm_hadd_epi32(prod1, mzero), mzero);
776
+ + summs -= y[i + 1].d * GGML_CPU_FP16_TO_FP32(x[i + 1].dmin) * _mm_extract_epi32(hsum1, 0);
777
+ +
778
+ + const __m128i sc1280 = _mm256_extracti128_si256(mins_and_scales0, 0);
779
+ + const __m128i sc1281 = _mm256_extracti128_si256(mins_and_scales1, 0);
780
+ + const __m256i scales0 = MM256_SET_M128I(sc1280, sc1280);
781
+ + const __m256i scales1 = MM256_SET_M128I(sc1281, sc1281);
782
+ + const __m512i scales = _mm512_inserti64x4(_mm512_castsi256_si512(scales0), scales1, 1);
783
+ +
784
+ + const __m256i hbits0 = _mm256_loadu_si256((const __m256i *) x[i + 0].qh);
785
+ + const __m256i hbits1 = _mm256_loadu_si256((const __m256i *) x[i + 1].qh);
786
+ + const __m512i hbits = _mm512_inserti64x4(_mm512_castsi256_si512(hbits0), hbits1, 1);
787
+ + __m512i hmask = _mm512_set1_epi8(1);
788
+ + __m512i sumi = _mm512_setzero_si512();
789
+ +
790
+ + int bit = 0;
791
+ +
792
+ + for (int j = 0; j < QK_K/64; ++j) {
793
+ + const __m512i scale_0 = _mm512_shuffle_epi8(scales, _mm512_broadcast_i64x4(get_scale_shuffle_k4(2*j + 0)));
794
+ + const __m512i scale_1 = _mm512_shuffle_epi8(scales, _mm512_broadcast_i64x4(get_scale_shuffle_k4(2*j + 1)));
795
+ +
796
+ + const __m256i q5bits0 = _mm256_loadu_si256((const __m256i *) (x[i + 0].qs + 32*j));
797
+ + const __m256i q5bits1 = _mm256_loadu_si256((const __m256i *) (x[i + 1].qs + 32*j));
798
+ + const __m512i q5bits = _mm512_inserti64x4(_mm512_castsi256_si512(q5bits0), q5bits1, 1);
799
+ +
800
+ + const __m512i q5l_0 = _mm512_and_si512(q5bits, _mm512_set1_epi8(0xF));
801
+ + const __m512i q5h_0 = _mm512_slli_epi16(_mm512_srli_epi16(_mm512_and_si512(hbits, hmask), bit++), 4);
802
+ + const __m512i q5_0 = _mm512_add_epi8(q5l_0, q5h_0);
803
+ + hmask = _mm512_slli_epi16(hmask, 1);
804
+ +
805
+ + const __m512i q5l_1 = _mm512_and_si512(_mm512_srli_epi16(q5bits, 4), _mm512_set1_epi8(0xF));
806
+ + const __m512i q5h_1 = _mm512_slli_epi16(_mm512_srli_epi16(_mm512_and_si512(hbits, hmask), bit++), 4);
807
+ + const __m512i q5_1 = _mm512_add_epi8(q5l_1, q5h_1);
808
+ + hmask = _mm512_slli_epi16(hmask, 1);
809
+ +
810
+ + const __m256i q8_00 = _mm256_loadu_si256((const __m256i *) (y[i + 0].qs + 64*j + 0));
811
+ + const __m256i q8_01 = _mm256_loadu_si256((const __m256i *) (y[i + 1].qs + 64*j + 0));
812
+ + const __m512i q8_0 = _mm512_inserti64x4(_mm512_castsi256_si512(q8_00), q8_01, 1);
813
+ + const __m256i q8_10 = _mm256_loadu_si256((const __m256i *) (y[i + 0].qs + 64*j + 32));
814
+ + const __m256i q8_11 = _mm256_loadu_si256((const __m256i *) (y[i + 1].qs + 64*j + 32));
815
+ + const __m512i q8_1 = _mm512_inserti64x4(_mm512_castsi256_si512(q8_10), q8_11, 1);
816
+ +
817
+ + const __m512i p16_0 = _mm512_maddubs_epi16(q5_0, q8_0);
818
+ + const __m512i p16_1 = _mm512_maddubs_epi16(q5_1, q8_1);
819
+ +#if defined(__AVX512VNNI__)
820
+ + sumi = _mm512_dpwssd_epi32(sumi, scale_0, p16_0);
821
+ + sumi = _mm512_dpwssd_epi32(sumi, scale_1, p16_1);
822
+ +#else
823
+ + const __m512i p32_0 = _mm512_madd_epi16(scale_0, p16_0);
824
+ + const __m512i p32_1 = _mm512_madd_epi16(scale_1, p16_1);
825
+ + sumi = _mm512_add_epi32(sumi, _mm512_add_epi32(p32_0, p32_1));
826
+ +#endif
827
+ + }
828
+ +
829
+ + __m512 vd = _mm512_castps256_ps512(_mm256_set1_ps(y[i + 0].d * GGML_CPU_FP16_TO_FP32(x[i + 0].d)));
830
+ + vd = _mm512_insertf32x8(vd, _mm256_set1_ps(y[i + 1].d * GGML_CPU_FP16_TO_FP32(x[i + 1].d)), 1);
831
+ + acc512 = _mm512_fmadd_ps(vd, _mm512_cvtepi32_ps(sumi), acc512);
832
+ + }
833
+ +
834
+ + __m256 acc = _mm256_add_ps(_mm512_castps512_ps256(acc512), _mm512_extractf32x8_ps(acc512, 1));
835
+ +#else
836
+ + __m256 acc = _mm256_setzero_ps();
837
+ +#endif
838
+ +
839
+ + for (; i < nb; ++i) {
840
+ const uint8_t * GGML_RESTRICT q5 = x[i].qs;
841
+ const int8_t * GGML_RESTRICT q8 = y[i].qs;
842
+
843
+ @@ -2358,13 +2454,20 @@ void ggml_vec_dot_q5_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
844
+ const __m256i q8_0 = _mm256_loadu_si256((const __m256i*)q8); q8 += 32;
845
+ const __m256i q8_1 = _mm256_loadu_si256((const __m256i*)q8); q8 += 32;
846
+
847
+ - __m256i p16_0 = _mm256_maddubs_epi16(q5_0, q8_0);
848
+ - __m256i p16_1 = _mm256_maddubs_epi16(q5_1, q8_1);
849
+ + const __m256i p16_0 = _mm256_maddubs_epi16(q5_0, q8_0);
850
+ + const __m256i p16_1 = _mm256_maddubs_epi16(q5_1, q8_1);
851
+
852
+ - p16_0 = _mm256_madd_epi16(scale_0, p16_0);
853
+ - p16_1 = _mm256_madd_epi16(scale_1, p16_1);
854
+ -
855
+ - sumi = _mm256_add_epi32(sumi, _mm256_add_epi32(p16_0, p16_1));
856
+ +#if defined(__AVX512VNNI__) && defined(__AVX512VL__)
857
+ + sumi = _mm256_dpwssd_epi32(sumi, scale_0, p16_0);
858
+ + sumi = _mm256_dpwssd_epi32(sumi, scale_1, p16_1);
859
+ +#elif defined(__AVXVNNI__)
860
+ + sumi = _mm256_dpwssd_avx_epi32(sumi, scale_0, p16_0);
861
+ + sumi = _mm256_dpwssd_avx_epi32(sumi, scale_1, p16_1);
862
+ +#else
863
+ + const __m256i p32_0 = _mm256_madd_epi16(scale_0, p16_0);
864
+ + const __m256i p32_1 = _mm256_madd_epi16(scale_1, p16_1);
865
+ + sumi = _mm256_add_epi32(sumi, _mm256_add_epi32(p32_0, p32_1));
866
+ +#endif
867
+
868
+ }
869
+
870
+ @@ -2505,9 +2608,105 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
871
+ const __m256i m3 = _mm256_set1_epi8(3);
872
+ const __m256i m15 = _mm256_set1_epi8(15);
873
+
874
+ + int i = 0;
875
+ +
876
+ +#if defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512DQ__)
877
+ + const __m512i m3_512 = _mm512_set1_epi8(3);
878
+ + const __m512i m12_512 = _mm512_set1_epi8(12);
879
+ + const __m512i m15_512 = _mm512_set1_epi8(15);
880
+ + const __m512i m48_512 = _mm512_set1_epi8(48);
881
+ + const __m512i mc0_512 = _mm512_set1_epi8(-64);
882
+ +
883
+ + __m512 acc512 = _mm512_setzero_ps();
884
+ +
885
+ + for (; i + 1 < nb; i += 2) {
886
+ + const __m256i q8sums0 = _mm256_loadu_si256((const __m256i *) y[i + 0].bsums);
887
+ + const __m256i q8sums1 = _mm256_loadu_si256((const __m256i *) y[i + 1].bsums);
888
+ + const __m512i q8sums = _mm512_inserti64x4(_mm512_castsi256_si512(q8sums0), q8sums1, 1);
889
+ +
890
+ + const __m128i scales0 = _mm_loadu_si128((const __m128i *) x[i + 0].scales);
891
+ + const __m128i scales1 = _mm_loadu_si128((const __m128i *) x[i + 1].scales);
892
+ + const __m256i scales = MM256_SET_M128I(scales1, scales0);
893
+ + const __m512i scales_16 = _mm512_cvtepi8_epi16(scales);
894
+ + const __m512i q8sclsub = _mm512_slli_epi32(_mm512_madd_epi16(q8sums, scales_16), 5);
895
+ +
896
+ + __m512i sumi = _mm512_setzero_si512();
897
+ +
898
+ + for (int j = 0; j < QK_K/128; ++j) {
899
+ + const __m256i q4bits10 = _mm256_loadu_si256((const __m256i *) (x[i + 0].ql + 64*j + 0));
900
+ + const __m256i q4bits11 = _mm256_loadu_si256((const __m256i *) (x[i + 1].ql + 64*j + 0));
901
+ + const __m512i q4bits1 = _mm512_inserti64x4(_mm512_castsi256_si512(q4bits10), q4bits11, 1);
902
+ + const __m256i q4bits20 = _mm256_loadu_si256((const __m256i *) (x[i + 0].ql + 64*j + 32));
903
+ + const __m256i q4bits21 = _mm256_loadu_si256((const __m256i *) (x[i + 1].ql + 64*j + 32));
904
+ + const __m512i q4bits2 = _mm512_inserti64x4(_mm512_castsi256_si512(q4bits20), q4bits21, 1);
905
+ + const __m256i q4bitsH0 = _mm256_loadu_si256((const __m256i *) (x[i + 0].qh + 32*j));
906
+ + const __m256i q4bitsH1 = _mm256_loadu_si256((const __m256i *) (x[i + 1].qh + 32*j));
907
+ + const __m512i q4bitsH = _mm512_inserti64x4(_mm512_castsi256_si512(q4bitsH0), q4bitsH1, 1);
908
+ +
909
+ + const __m512i q4h_0 = _mm512_slli_epi16(_mm512_and_si512(q4bitsH, m3_512), 4);
910
+ + const __m512i q4h_1 = _mm512_slli_epi16(_mm512_and_si512(q4bitsH, m12_512), 2);
911
+ + const __m512i q4h_2 = _mm512_and_si512(q4bitsH, m48_512);
912
+ + const __m512i q4h_3 = _mm512_srli_epi16(_mm512_and_si512(q4bitsH, mc0_512), 2);
913
+ +
914
+ + const __m512i q4_0 = _mm512_or_si512(_mm512_and_si512(q4bits1, m15_512), q4h_0);
915
+ + const __m512i q4_1 = _mm512_or_si512(_mm512_and_si512(q4bits2, m15_512), q4h_1);
916
+ + const __m512i q4_2 = _mm512_or_si512(_mm512_and_si512(_mm512_srli_epi16(q4bits1, 4), m15_512), q4h_2);
917
+ + const __m512i q4_3 = _mm512_or_si512(_mm512_and_si512(_mm512_srli_epi16(q4bits2, 4), m15_512), q4h_3);
918
+ +
919
+ + const __m256i q8_00 = _mm256_loadu_si256((const __m256i *) (y[i + 0].qs + 128*j + 0));
920
+ + const __m256i q8_01 = _mm256_loadu_si256((const __m256i *) (y[i + 1].qs + 128*j + 0));
921
+ + const __m512i q8_0 = _mm512_inserti64x4(_mm512_castsi256_si512(q8_00), q8_01, 1);
922
+ + const __m256i q8_10 = _mm256_loadu_si256((const __m256i *) (y[i + 0].qs + 128*j + 32));
923
+ + const __m256i q8_11 = _mm256_loadu_si256((const __m256i *) (y[i + 1].qs + 128*j + 32));
924
+ + const __m512i q8_1 = _mm512_inserti64x4(_mm512_castsi256_si512(q8_10), q8_11, 1);
925
+ + const __m256i q8_20 = _mm256_loadu_si256((const __m256i *) (y[i + 0].qs + 128*j + 64));
926
+ + const __m256i q8_21 = _mm256_loadu_si256((const __m256i *) (y[i + 1].qs + 128*j + 64));
927
+ + const __m512i q8_2 = _mm512_inserti64x4(_mm512_castsi256_si512(q8_20), q8_21, 1);
928
+ + const __m256i q8_30 = _mm256_loadu_si256((const __m256i *) (y[i + 0].qs + 128*j + 96));
929
+ + const __m256i q8_31 = _mm256_loadu_si256((const __m256i *) (y[i + 1].qs + 128*j + 96));
930
+ + const __m512i q8_3 = _mm512_inserti64x4(_mm512_castsi256_si512(q8_30), q8_31, 1);
931
+ +
932
+ + const __m256i scale_shuffle0 = MM256_SET_M128I(get_scale_shuffle(4*j + 0), get_scale_shuffle(4*j + 0));
933
+ + const __m256i scale_shuffle1 = MM256_SET_M128I(get_scale_shuffle(4*j + 1), get_scale_shuffle(4*j + 1));
934
+ + const __m256i scale_shuffle2 = MM256_SET_M128I(get_scale_shuffle(4*j + 2), get_scale_shuffle(4*j + 2));
935
+ + const __m256i scale_shuffle3 = MM256_SET_M128I(get_scale_shuffle(4*j + 3), get_scale_shuffle(4*j + 3));
936
+ +
937
+ + const __m512i scale_0 = _mm512_cvtepi8_epi16(_mm256_shuffle_epi8(scales, scale_shuffle0));
938
+ + const __m512i scale_1 = _mm512_cvtepi8_epi16(_mm256_shuffle_epi8(scales, scale_shuffle1));
939
+ + const __m512i scale_2 = _mm512_cvtepi8_epi16(_mm256_shuffle_epi8(scales, scale_shuffle2));
940
+ + const __m512i scale_3 = _mm512_cvtepi8_epi16(_mm256_shuffle_epi8(scales, scale_shuffle3));
941
+ + const __m512i p16_0 = _mm512_maddubs_epi16(q4_0, q8_0);
942
+ + const __m512i p16_1 = _mm512_maddubs_epi16(q4_1, q8_1);
943
+ + const __m512i p16_2 = _mm512_maddubs_epi16(q4_2, q8_2);
944
+ + const __m512i p16_3 = _mm512_maddubs_epi16(q4_3, q8_3);
945
+ +
946
+ +#if defined(__AVX512VNNI__)
947
+ + sumi = _mm512_dpwssd_epi32(sumi, scale_0, p16_0);
948
+ + sumi = _mm512_dpwssd_epi32(sumi, scale_1, p16_1);
949
+ + sumi = _mm512_dpwssd_epi32(sumi, scale_2, p16_2);
950
+ + sumi = _mm512_dpwssd_epi32(sumi, scale_3, p16_3);
951
+ +#else
952
+ + const __m512i p32_0 = _mm512_madd_epi16(scale_0, p16_0);
953
+ + const __m512i p32_1 = _mm512_madd_epi16(scale_1, p16_1);
954
+ + const __m512i p32_2 = _mm512_madd_epi16(scale_2, p16_2);
955
+ + const __m512i p32_3 = _mm512_madd_epi16(scale_3, p16_3);
956
+ + sumi = _mm512_add_epi32(sumi, _mm512_add_epi32(p32_0, p32_1));
957
+ + sumi = _mm512_add_epi32(sumi, _mm512_add_epi32(p32_2, p32_3));
958
+ +#endif
959
+ + }
960
+ +
961
+ + sumi = _mm512_sub_epi32(sumi, q8sclsub);
962
+ + __m512 vd = _mm512_castps256_ps512(_mm256_set1_ps(y[i + 0].d * GGML_CPU_FP16_TO_FP32(x[i + 0].d)));
963
+ + vd = _mm512_insertf32x8(vd, _mm256_set1_ps(y[i + 1].d * GGML_CPU_FP16_TO_FP32(x[i + 1].d)), 1);
964
+ + acc512 = _mm512_fmadd_ps(vd, _mm512_cvtepi32_ps(sumi), acc512);
965
+ + }
966
+ +
967
+ + __m256 acc = _mm256_add_ps(_mm512_castps512_ps256(acc512), _mm512_extractf32x8_ps(acc512, 1));
968
+ +#else
969
+ __m256 acc = _mm256_setzero_ps();
970
+ +#endif
971
+
972
+ - for (int i = 0; i < nb; ++i) {
973
+ + for (; i < nb; ++i) {
974
+
975
+ const float d = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
976
+
977
+ @@ -2544,10 +2743,10 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
978
+ const __m256i q8_2 = _mm256_loadu_si256((const __m256i*)q8); q8 += 32;
979
+ const __m256i q8_3 = _mm256_loadu_si256((const __m256i*)q8); q8 += 32;
980
+
981
+ - __m256i p16_0 = _mm256_maddubs_epi16(q4_0, q8_0);
982
+ - __m256i p16_1 = _mm256_maddubs_epi16(q4_1, q8_1);
983
+ - __m256i p16_2 = _mm256_maddubs_epi16(q4_2, q8_2);
984
+ - __m256i p16_3 = _mm256_maddubs_epi16(q4_3, q8_3);
985
+ + const __m256i p16_0 = _mm256_maddubs_epi16(q4_0, q8_0);
986
+ + const __m256i p16_1 = _mm256_maddubs_epi16(q4_1, q8_1);
987
+ + const __m256i p16_2 = _mm256_maddubs_epi16(q4_2, q8_2);
988
+ + const __m256i p16_3 = _mm256_maddubs_epi16(q4_3, q8_3);
989
+
990
+ const __m128i scale_0 = _mm_shuffle_epi8(scales, get_scale_shuffle(is + 0));
991
+ const __m128i scale_1 = _mm_shuffle_epi8(scales, get_scale_shuffle(is + 1));
992
+ @@ -2555,13 +2754,29 @@ void ggml_vec_dot_q6_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const voi
993
+ const __m128i scale_3 = _mm_shuffle_epi8(scales, get_scale_shuffle(is + 3));
994
+ is += 4;
995
+
996
+ - p16_0 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_0), p16_0);
997
+ - p16_1 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_1), p16_1);
998
+ - p16_2 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_2), p16_2);
999
+ - p16_3 = _mm256_madd_epi16(_mm256_cvtepi8_epi16(scale_3), p16_3);
1000
+ + const __m256i scale16_0 = _mm256_cvtepi8_epi16(scale_0);
1001
+ + const __m256i scale16_1 = _mm256_cvtepi8_epi16(scale_1);
1002
+ + const __m256i scale16_2 = _mm256_cvtepi8_epi16(scale_2);
1003
+ + const __m256i scale16_3 = _mm256_cvtepi8_epi16(scale_3);
1004
+
1005
+ - sumi = _mm256_add_epi32(sumi, _mm256_add_epi32(p16_0, p16_1));
1006
+ - sumi = _mm256_add_epi32(sumi, _mm256_add_epi32(p16_2, p16_3));
1007
+ +#if defined(__AVX512VNNI__) && defined(__AVX512VL__)
1008
+ + sumi = _mm256_dpwssd_epi32(sumi, scale16_0, p16_0);
1009
+ + sumi = _mm256_dpwssd_epi32(sumi, scale16_1, p16_1);
1010
+ + sumi = _mm256_dpwssd_epi32(sumi, scale16_2, p16_2);
1011
+ + sumi = _mm256_dpwssd_epi32(sumi, scale16_3, p16_3);
1012
+ +#elif defined(__AVXVNNI__)
1013
+ + sumi = _mm256_dpwssd_avx_epi32(sumi, scale16_0, p16_0);
1014
+ + sumi = _mm256_dpwssd_avx_epi32(sumi, scale16_1, p16_1);
1015
+ + sumi = _mm256_dpwssd_avx_epi32(sumi, scale16_2, p16_2);
1016
+ + sumi = _mm256_dpwssd_avx_epi32(sumi, scale16_3, p16_3);
1017
+ +#else
1018
+ + const __m256i p32_0 = _mm256_madd_epi16(scale16_0, p16_0);
1019
+ + const __m256i p32_1 = _mm256_madd_epi16(scale16_1, p16_1);
1020
+ + const __m256i p32_2 = _mm256_madd_epi16(scale16_2, p16_2);
1021
+ + const __m256i p32_3 = _mm256_madd_epi16(scale16_3, p16_3);
1022
+ + sumi = _mm256_add_epi32(sumi, _mm256_add_epi32(p32_0, p32_1));
1023
+ + sumi = _mm256_add_epi32(sumi, _mm256_add_epi32(p32_2, p32_3));
1024
+ +#endif
1025
+
1026
+ }
1027
+
1028
  diff --git a/ggml/src/ggml-cpu/arch/x86/repack.cpp b/ggml/src/ggml-cpu/arch/x86/repack.cpp
1029
  index af1cebad1..f30d822c5 100644
1030
  --- a/ggml/src/ggml-cpu/arch/x86/repack.cpp