Skip to content

fix: Q1_0_g128 x86 CPU kernel - correct output + AVX2/AVX-512 VNNI#6

Closed
stfurkan wants to merge 2 commits into
PrismML-Eng:prismfrom
stfurkan:fix/q1_0_g128-x86-cpu-kernel
Closed

fix: Q1_0_g128 x86 CPU kernel - correct output + AVX2/AVX-512 VNNI#6
stfurkan wants to merge 2 commits into
PrismML-Eng:prismfrom
stfurkan:fix/q1_0_g128-x86-cpu-kernel

Conversation

@stfurkan

@stfurkan stfurkan commented Apr 2, 2026

Copy link
Copy Markdown

Builds on the scalar fix from #8 (cpu-fixes) which corrected the float-to-int truncation bug by changing int sumi to float sumi. That fix produces correct output but falls back to scalar code on x86 (~3 tok/s).

This PR adds SIMD-optimized x86 kernels for Q1_0_g128 to bring x86 CPU performance closer to what ARM NEON achieves.

Changes

  • x86 arch/x86/quants.c: replace generic scalar delegation with three-tier SIMD implementation:
    1. AVX-512 VNNI (BW+VL+VNNI): maskz_mov_epi8 for single-instruction bit expansion + VPDPBUSD for dot product accumulation
    2. AVX2: shuffle-based bit-to-byte expansion + sign_epi8 multiply
    3. Scalar fallback: delegates to ggml_vec_dot_q1_0_g128_q8_0_generic
  • Generic scalar kernel (quants.c): minor cleanup — simplified inner loop using direct bit extraction (bits[j >> 3] >> (j & 7)) and single-level float accumulation
  • All loads use memcpy for strict-aliasing and alignment safety

ARM NEON and CUDA/Metal paths are untouched.

Benchmarks

Hetzner CPX52 (12 vCPU AMD EPYC Zen 4, shared, 24GB RAM)

Model Scalar (before) AVX-512 VNNI (after) Speedup
1.7B ~3 tok/s 51.1 tok/s ~17x
4B ~3 tok/s 19.8 tok/s ~7x
8B ~3 tok/s 11.1 tok/s ~4x

All models produce correct output. Prompt processing sees similar gains (44.8 / 23.6 / 12.8 tok/s respectively).

Live demo: https://ai.sft.best (temporary, may be taken down)

Copilot AI review requested due to automatic review settings April 2, 2026 17:12
@github-actions github-actions Bot added the ggml label Apr 2, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes incorrect Q1_0_g128 × Q8_0 dot-product results on x86 by correcting float/int accumulation and introducing optimized x86 implementations (AVX-512 VNNI, AVX2, scalar fallback) while keeping behavior consistent with the working ARM path.

Changes:

  • Fix scalar generic kernel accumulation to avoid float-to-int truncation.
  • Replace x86 scalar-only kernel with AVX-512 VNNI and AVX2 implementations plus corrected scalar fallback.
  • Simplify bit extraction logic in scalar paths.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
ggml/src/ggml-cpu/quants.c Fixes generic scalar vec_dot accumulation for correct numerical results.
ggml/src/ggml-cpu/arch/x86/quants.c Adds AVX-512 VNNI + AVX2 kernels and fixes scalar fallback accumulation for x86.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ggml/src/ggml-cpu/arch/x86/quants.c Outdated
Comment thread ggml/src/ggml-cpu/arch/x86/quants.c Outdated
Comment thread ggml/src/ggml-cpu/arch/x86/quants.c Outdated
@khosravipasha

Copy link
Copy Markdown
Collaborator

This look great thanks, there was a few CPU kernel fixes and did not see them until I pushed my changes. For now removed the buggy x86, will merge one of the correct AVX ones.

Could you run the KL divergence tests described here: #8

The Q1_0_g128 vec_dot kernel for x86 produces garbage output due to a
float-to-int truncation bug: `sumi += d1 * sumi_block` accumulates a
float product into an int, silently truncating the result to zero for
small scale factors. This affects both the generic scalar fallback and
the x86 arch-specific implementation.

The ARM NEON implementation was correct and unaffected.

Changes:
- Fix generic scalar kernel (quants.c): accumulate `d0 * d1 * sumi`
  into float, matching the working ARM scalar fallback pattern
- Replace x86 scalar-only kernel with three-tier implementation:
  1. AVX-512 VNNI (BW+VL+VNNI): uses mask registers for single-
     instruction bit expansion + VPDPBUSD for dot product
  2. AVX2: shuffle-based bit expansion + sign_epi8 multiply
  3. Scalar fallback: corrected accumulation

Benchmarks on AMD EPYC (Zen 4, 12 vCPU shared):
  Before (broken): garbage output at ~0.5 tok/s
  Scalar fix:      correct output at ~3 tok/s
  AVX2:            correct output at ~28 tok/s
  AVX-512 VNNI:    correct output at ~50 tok/s (1.7B model)
@stfurkan
stfurkan force-pushed the fix/q1_0_g128-x86-cpu-kernel branch from ba0e521 to 0b7a2dd Compare April 2, 2026 18:52
@stfurkan

stfurkan commented Apr 2, 2026

Copy link
Copy Markdown
Author

This look great thanks, there was a few CPU kernel fixes and did not see them until I pushed my changes. For now removed the buggy x86, will merge one of the correct AVX ones.

Could you run the KL divergence tests described here: #8

@khosravipasha Thanks! I rebased the branch on top of your cpu-fixes merge. The KL divergence results are below, the AVX-512 VNNI kernel matches F16 almost exactly (99.949% same top p, near-zero KL divergence).

KL Divergence Results (Q1_0_g128 vs F16)

AMD EPYC Zen 4 (AVX-512 VNNI kernel), Bonsai-1.7B, wikitext-2-raw, 100 chunks, ctx 512

Note: The wikitext-2-raw dataset had some invalid codepoints that caused the tokenizer to crash. Cleaned by removing non-BMP characters before running.

Metric Value
Same top p 99.949 ± 0.014 %
Mean KL divergence -0.000000 ± 0.000000
Max KL divergence 0.000031
Mean PPL(Q)/PPL(base) 1.000012 ± 0.000019
RMS Δp 0.000 ± 0.000 %
Prompt processing 50.29 tok/s

Q1_0 (non-g128) GGUF doesn't appear to be published on HuggingFace, only Bonsai-1.7B.gguf (Q1_0_g128) is available at prism-ml/Bonsai-1.7B-gguf. Happy to run it if you can share the file.

Full log

system_info: n_threads = 12 (n_threads_batch = 12) / 12 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VBMI = 1 | AVX512_VNNI = 1 | AVX512_BF16 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 | 
kl_divergence: computing over 100 chunks, n_ctx=512, batch_size=2048, n_seq=4
kl_divergence: 33.76 seconds per pass - ETA 14.07 minutes

chunk             PPL               ln(PPL(Q)/PPL(base))          KL Divergence              Δp RMS            Same top p
   1     798.3831 ±  121.7392      -0.00001 ±       -nan       0.00000 ±    0.00000     0.000 ±  0.000 %    100.000 ±  0.000 %
   2     620.0014 ±   65.3600       0.00001 ±       -nan       0.00000 ±    0.00000     0.001 ±  0.000 %    100.000 ±  0.000 %
   3     645.9309 ±   57.4854       0.00001 ±       -nan       0.00000 ±    0.00000     0.001 ±  0.000 %    100.000 ±  0.000 %
   4     674.1265 ±   52.2820       0.00000 ±       -nan      -0.00000 ±    0.00000     0.001 ±  0.000 %    99.902 ±  0.098 %
   5     695.0380 ±   49.2197      -0.00000 ±       -nan       0.00000 ±    0.00000     0.000 ±  0.000 %    99.922 ±  0.078 %
   6     705.0255 ±   46.4772       0.00000 ±       -nan       0.00000 ±    0.00000     0.000 ±  0.000 %    99.935 ±  0.065 %
   7     698.1185 ±   42.5761       0.00000 ±       -nan       0.00000 ±    0.00000     0.001 ±  0.000 %    99.944 ±  0.056 %
   8     704.5098 ±   40.2837       0.00000 ±       -nan       0.00000 ±    0.00000     0.001 ±  0.000 %    99.951 ±  0.049 %
   9     708.6964 ±   38.1745       0.00000 ±       -nan       0.00000 ±    0.00000     0.001 ±  0.000 %    99.956 ±  0.044 %
  10     712.0216 ±   36.1241       0.00000 ±       -nan       0.00000 ±    0.00000     0.001 ±  0.000 %    99.961 ±  0.039 %
  11     723.7918 ±   35.1560       0.00000 ±       -nan       0.00000 ±    0.00000     0.001 ±  0.000 %    99.964 ±  0.036 %
  12     722.6843 ±   33.4567       0.00000 ±       -nan       0.00000 ±    0.00000     0.000 ±  0.000 %    99.967 ±  0.033 %
  13     722.3550 ±   32.1003       0.00000 ±       -nan       0.00000 ±    0.00000     0.001 ±  0.000 %    99.970 ±  0.030 %
  14     721.8709 ±   31.0136       0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.972 ±  0.028 %
  15     724.1042 ±   29.9789      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.974 ±  0.026 %
  16     718.8967 ±   28.6933      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.975 ±  0.025 %
  17     713.8766 ±   27.5841      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.977 ±  0.023 %
  18     716.6543 ±   26.9642      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.956 ±  0.031 %
  19     714.1373 ±   26.1189      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.959 ±  0.029 %
  20     716.0243 ±   25.5827      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.961 ±  0.028 %
  21     720.8451 ±   25.2289      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.944 ±  0.032 %
  22     709.7127 ±   24.1366      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.947 ±  0.031 %
  23     722.8257 ±   24.1865      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.949 ±  0.030 %
  24     731.1260 ±   23.9849      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.951 ±  0.028 %
  25     733.6260 ±   23.5931      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.953 ±  0.027 %
  26     729.0816 ±   22.9661      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.955 ±  0.026 %
  27     732.0525 ±   22.6660      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.956 ±  0.025 %
  28     732.0982 ±   22.2974      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.958 ±  0.024 %
  29     731.2949 ±   21.8910      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.959 ±  0.023 %
  30     728.4758 ±   21.3988      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.961 ±  0.023 %
  31     731.1864 ±   21.1542      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.962 ±  0.022 %
  32     730.5836 ±   20.7615      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.963 ±  0.021 %
  33     729.5381 ±   20.4158      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.964 ±  0.021 %
  34     733.9744 ±   20.2788      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.965 ±  0.020 %
  35     730.8512 ±   19.8602      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.966 ±  0.019 %
  36     732.7395 ±   19.6591      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.967 ±  0.019 %
  37     731.6309 ±   19.3785      -0.00000 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.968 ±  0.018 %
  38     726.9186 ±   18.9506      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.969 ±  0.018 %
  39     725.5439 ±   18.6636      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.970 ±  0.017 %
  40     725.8810 ±   18.4446      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.971 ±  0.017 %
  41     727.3044 ±   18.2676      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.962 ±  0.019 %
  42     727.9197 ±   18.0797      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.963 ±  0.019 %
  43     724.1192 ±   17.7521      -0.00001 ±    0.00000       0.00000 ±    0.00000     0.000 ±  0.000 %    99.964 ±  0.018 %
  44     728.2769 ±   17.6831       0.00004 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.964 ±  0.018 %
  45     727.4466 ±   17.4680       0.00004 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.956 ±  0.019 %
  46     728.4052 ±   17.3137       0.00004 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.957 ±  0.019 %
  47     726.8054 ±   17.0814       0.00004 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.958 ±  0.019 %
  48     725.2216 ±   16.8666       0.00003 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.959 ±  0.018 %
  49     723.2643 ±   16.6521       0.00003 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.952 ±  0.020 %
  50     723.6195 ±   16.4879       0.00003 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.953 ±  0.019 %
  51     724.2560 ±   16.3305       0.00003 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.954 ±  0.019 %
  52     723.1021 ±   16.1320       0.00003 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.955 ±  0.018 %
  53     721.3222 ±   15.9305       0.00003 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.956 ±  0.018 %
  54     720.8257 ±   15.7539       0.00003 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.956 ±  0.018 %
  55     720.6670 ±   15.6011       0.00003 ±    0.00004       0.00000 ±    0.00000     0.000 ±  0.000 %    99.957 ±  0.017 %
  56     720.2911 ±   15.4446       0.00003 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.958 ±  0.017 %
  57     719.3650 ±   15.2757       0.00003 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.952 ±  0.018 %
  58     719.3343 ±   15.1429       0.00003 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.953 ±  0.018 %
  59     716.6217 ±   14.9456       0.00003 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.953 ±  0.018 %
  60     719.6623 ±   14.9223       0.00003 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.948 ±  0.018 %
  61     718.3877 ±   14.7454       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.949 ±  0.018 %
  62     721.5333 ±   14.7063       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.949 ±  0.018 %
  63     721.6858 ±   14.5951       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.950 ±  0.018 %
  64     721.6114 ±   14.4782       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.951 ±  0.017 %
  65     721.4266 ±   14.3558       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.952 ±  0.017 %
  66     718.7859 ±   14.1840       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.952 ±  0.017 %
  67     719.6319 ±   14.1144       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.953 ±  0.017 %
  68     719.4142 ±   13.9946       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.948 ±  0.017 %
  69     718.6948 ±   13.8686       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.949 ±  0.017 %
  70     720.3316 ±   13.8043       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.950 ±  0.017 %
  71     720.1921 ±   13.6989       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.950 ±  0.017 %
  72     721.1309 ±   13.6219       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.951 ±  0.016 %
  73     721.9325 ±   13.5344       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.946 ±  0.017 %
  74     722.5413 ±   13.4512       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.947 ±  0.017 %
  75     722.3066 ±   13.3536       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.948 ±  0.017 %
  76     724.6891 ±   13.3120       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.948 ±  0.016 %
  77     723.4411 ±   13.2000       0.00002 ±    0.00003       0.00000 ±    0.00000     0.000 ±  0.000 %    99.949 ±  0.016 %
  78     724.1289 ±   13.1312       0.00002 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.950 ±  0.016 %
  79     723.7522 ±   13.0401       0.00002 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.950 ±  0.016 %
  80     723.1670 ±   12.9406       0.00002 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.951 ±  0.015 %
  81     722.7882 ±   12.8539       0.00002 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.952 ±  0.015 %
  82     721.8618 ±   12.7553       0.00002 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.952 ±  0.015 %
  83     721.8330 ±   12.6808       0.00002 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.953 ±  0.015 %
  84     724.5431 ±   12.6621       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.953 ±  0.015 %
  85     726.1077 ±   12.6264       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.954 ±  0.015 %
  86     728.1747 ±   12.5917       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.954 ±  0.014 %
  87     727.5947 ±   12.4961       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.955 ±  0.014 %
  88     728.7140 ±   12.4468       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.947 ±  0.015 %
  89     726.3536 ±   12.3251       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.947 ±  0.015 %
  90     725.7515 ±   12.2391       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.948 ±  0.015 %
  91     725.6283 ±   12.1728       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.948 ±  0.015 %
  92     725.0724 ±   12.1026       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.949 ±  0.015 %
  93     725.5553 ±   12.0495       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.949 ±  0.015 %
  94     727.2092 ±   12.0117       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.950 ±  0.014 %
  95     726.7849 ±   11.9400       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.950 ±  0.014 %
  96     726.2184 ±   11.8665       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.951 ±  0.014 %
  97     723.7844 ±   11.7554       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.951 ±  0.014 %
  98     725.5034 ±   11.7319       0.00001 ±    0.00002       0.00000 ±    0.00000     0.000 ±  0.000 %    99.952 ±  0.014 %
  99     724.5530 ±   11.6529       0.00001 ±    0.00002      -0.00000 ±    0.00000     0.000 ±  0.000 %    99.949 ±  0.014 %
 100     724.6320 ±   11.5917       0.00001 ±    0.00002      -0.00000 ±    0.00000     0.000 ±  0.000 %    99.949 ±  0.014 %

====== Perplexity statistics ======
Mean PPL(Q)                   : 724.631977 ±  11.591689
Mean PPL(base)                : 724.623018 ±  11.591121
Cor(ln(PPL(Q)), ln(PPL(base))): 100.00%
Mean ln(PPL(Q)/PPL(base))     :   0.000012 ±   0.000019
Mean PPL(Q)/PPL(base)         :   1.000012 ±   0.000019
Mean PPL(Q)-PPL(base)         :   0.008959 ±   0.014099

====== KL divergence statistics ======
Mean    KLD:  -0.000000 ±   0.000000
Maximum KLD:   0.000031
99.9%   KLD:   0.000023
99.0%   KLD:   0.000016
95.0%   KLD:   0.000011
90.0%   KLD:   0.000008
Median  KLD:  -0.000000
10.0%   KLD:  -0.000008
 5.0%   KLD:  -0.000011
 1.0%   KLD:  -0.000016
 0.1%   KLD:  -0.000022
Minimum KLD:  -0.000028

====== Token probability statistics ======
Mean    Δp:  0.000 ± 0.000 %
Maximum Δp:  0.010%
99.9%   Δp:  0.002%
99.0%   Δp:  0.001%
95.0%   Δp:  0.000%
90.0%   Δp:  0.000%
75.0%   Δp:  0.000%
Median  Δp:  0.000%
25.0%   Δp: -0.000%
10.0%   Δp: -0.000%
 5.0%   Δp: -0.000%
 1.0%   Δp: -0.001%
 0.1%   Δp: -0.003%
Minimum Δp: -0.018%
RMS Δp    :  0.000 ± 0.000 %
Same top p: 99.949 ± 0.014 %

@khosravipasha

Copy link
Copy Markdown
Collaborator

Thanks looks good its close to 0.
do you have tg128 and pp512 speeds as well

Its okay for Q1_0, we won't be using it. Also seems llama.cpp people don't like the Q1_0_g128 naming so most likely we will rename the Q1_0_g128 => Q1_0 and remove Q1_0 in future in llama.cpp's main repo.

@stfurkan

stfurkan commented Apr 2, 2026

Copy link
Copy Markdown
Author

Here are the pp512/tg128 benchmarks for all three models:

Benchmarks (pp512 / tg128)

AMD EPYC Zen 4 (12 vCPU shared), AVX-512 VNNI kernel, -r 3

Model Size pp512 (tok/s) tg128 (tok/s)
Bonsai 1.7B 231 MiB 46.92 ± 2.02 98.16 ± 1.02
Bonsai 4B 540 MiB 30.35 ± 0.21 45.96 ± 0.04
Bonsai 8B 1.07 GiB 23.96 ± 0.03 27.58 ± 0.31

12 threads, BLAS backend, shared vCPU (Hetzner CPX52). Note these are with all threads on a single model, in production I run all 3 simultaneously with 4 threads each, which gives roughly half these numbers.

Good to know about the Q1_0_g128 → Q1_0 rename. Thanks @khosravipasha

@zcattacz

zcattacz commented Apr 3, 2026

Copy link
Copy Markdown

This is slower than PR7 on my i5 box with AVX2 only. llamacpp build with

rm -rf build
cmake -B build -DGGML_NATIVE=ON
cmake --build build --config Release -j 4

pr6

llm/llama.cpp-prism$ cd bin && rm cpu && ln -sf pr6 cpu && cd ..
llm/llama.cpp-prism$ BONSAI_MODEL=4B ./scripts/run_llama.sh -c 8192 -p "Hi"
build      : b0-unknown
model      : Bonsai-4B.gguf
modalities : text
available commands:
  /exit or Ctrl+C     stop or exit
  /regen              regenerate the last response
  /clear              clear the chat history
  /read               add a text file
> Hi                                                                                                                                       
Hello! I'm Bonsai, a 1-bit AI assistant developed by PrismML. I'm here to help with any questions or tasks you might have. How can I assist you today?
[ Prompt: 3.2 t/s | Generation: 2.9 t/s ]                                                                                                  
>                                                                                                                                          
Exiting...
llama_memory_breakdown_print: | memory breakdown [MiB] | total   free    self   model   context   compute    unaccounted |
llama_memory_breakdown_print: |   - Host               |                 2003 =   540 +    1152 +     311                |

pr7

llm/llama.cpp-prism$ cd bin && rm cpu && ln -sf pr7 cpu && cd ..
llm/llama.cpp-prism$ BONSAI_MODEL=4B ./scripts/run_llama.sh -c 8192 -p "Hi"
build      : b0-unknown
model      : Bonsai-4B.gguf
modalities : text
available commands:
  /exit or Ctrl+C     stop or exit
  /regen              regenerate the last response
  /clear              clear the chat history
  /read               add a text file
> Hi                                                                                                                                       
Hello! I'm Bonsai, an AI assistant developed by PrismML. I'm here to help with any questions or tasks you might have. How can I assist you today?
[ Prompt: 5.2 t/s | Generation: 4.5 t/s ]                                                                                                  
>                                                                                                                                          
Exiting...
llama_memory_breakdown_print: | memory breakdown [MiB] | total   free    self   model   context   compute    unaccounted |
llama_memory_breakdown_print: |   - Host               |                 2003 =   540 +    1152 +     311                |

llm/llama.cpp-prism$ BONSAI_MODEL=8B ./scripts/run_llama.sh -c 8192 -p "Hi"
build      : b0-unknown
model      : Bonsai-8B.gguf
modalities : text
available commands:
  /exit or Ctrl+C     stop or exit
  /regen              regenerate the last response
  /clear              clear the chat history
  /read               add a text file
> Hi                                                                                                                                       
Hello! I'm Bonsai, an AI assistant developed by PrismML. How can I assist you today?
[ Prompt: 2.7 t/s | Generation: 2.5 t/s ]                                                                                                  
>
Exiting...
llama_memory_breakdown_print: | memory breakdown [MiB] | total   free    self   model   context   compute    unaccounted |
llama_memory_breakdown_print: |   - Host               |                 2571 =  1099 +    1152 +     320                |

- AVX2: replace manual int8→int16→int32 reduction with mul_sum_i8_pairs_float()
  (auto-selects AVXVNNI dpbssd on supported CPUs)
- Both paths: accumulate into __m256 float via fmadd_ps, single hsum_float_8 at end
  (eliminates per-block horizontal int32 sum)
- Remove unused variables and constants
@stfurkan

stfurkan commented Apr 3, 2026

Copy link
Copy Markdown
Author

@zcattacz Thanks for testing! I've updated the AVX2 path, replaced the manual int8→int16→int32 reduction chain with mul_sum_i8_pairs_float() (which auto-selects dpbssd on AVXVNNI CPUs) and switched to a float accumulator with fmadd_ps + single hsum_float_8() at the end. This should be significantly faster on AVX2-only hardware.

Updated benchmarks (AMD EPYC Zen 4, 12 vCPU shared):

Model pp512 (tok/s) tg128 (tok/s)
1.7B 46.87 ± 3.08 118.65 ± 0.14
4B 30.87 ± 1.08 59.79 ± 0.39
8B 23.92 ± 0.42 35.03 ± 0.11

tg128 improved ~20-30% over the previous version. Would be great to see your i5 numbers with this update if you get a chance.

@zcattacz

zcattacz commented Apr 3, 2026

Copy link
Copy Markdown

Hi @stfurkan I don't know which one is likely to get worked on, so I commented on both PR. Kinda awkward... The optimization later gave me real speed is documented in a later reply in #7 It's not PR7's way but partly from PR4 with an extra 40%~60% boost in tps.

@khosravipasha

Copy link
Copy Markdown
Collaborator

There is a lot of CPU PRs, planning to gether all in one and then send to the main llama.cpp
Going to close this and mention people that helped in a thread there, if you think your solution is better please comment there:
#10

bricklc pushed a commit to bricklc/prism-ml-llama.cpp that referenced this pull request Apr 25, 2026
Complete experiment log:
  Mintplex-Labs#1  4-mag LUT:           15.1 at 8K (BEST, +38%)
  Mintplex-Labs#2  Batched extract:     13.7 (+25%)
  PrismML-Eng#3  Inline FA block:     13.5 (I-cache pressure)
  PrismML-Eng#4  Deferred norm:       12.9 (loses ILP)
  PrismML-Eng#5  2-pair half2:        12.0 (ternary overhead)
  PrismML-Eng#6  Select chain:        11.9 (branches kill)
  PrismML-Eng#7  Bit-arithmetic:      11.6 (ALU too heavy)
  PrismML-Eng#8  FMA branchless:      11.4 (ALU still too heavy)
  PrismML-Eng#9  Named-reg ternary:   10.3 (branches worst)
  PrismML-Eng#10 Main (8-LUT):        10.95 (baseline)
  PrismML-Eng#11 Non-vec FA:          10.2 (wrong kernel)
  Ceiling:                 24.5 (no dequant)

Apple8 hardware truth:
  1 divergent constant read < 7 ALU ops (even with fma)
  Branches cost MORE than divergent constant reads
  Array indexing ALWAYS spills on Metal
  4 constant addresses is the sweet spot

The 4-mag LUT is the dequant-level ceiling on Apple Silicon.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
retroheim pushed a commit to retroheim/prism-ml-llama.cpp that referenced this pull request May 3, 2026
Complete experiment log:
  Mintplex-Labs#1  4-mag LUT:           15.1 at 8K (BEST, +38%)
  Mintplex-Labs#2  Batched extract:     13.7 (+25%)
  PrismML-Eng#3  Inline FA block:     13.5 (I-cache pressure)
  PrismML-Eng#4  Deferred norm:       12.9 (loses ILP)
  PrismML-Eng#5  2-pair half2:        12.0 (ternary overhead)
  PrismML-Eng#6  Select chain:        11.9 (branches kill)
  PrismML-Eng#7  Bit-arithmetic:      11.6 (ALU too heavy)
  PrismML-Eng#8  FMA branchless:      11.4 (ALU still too heavy)
  PrismML-Eng#9  Named-reg ternary:   10.3 (branches worst)
  PrismML-Eng#10 Main (8-LUT):        10.95 (baseline)
  PrismML-Eng#11 Non-vec FA:          10.2 (wrong kernel)
  Ceiling:                 24.5 (no dequant)

Apple8 hardware truth:
  1 divergent constant read < 7 ALU ops (even with fma)
  Branches cost MORE than divergent constant reads
  Array indexing ALWAYS spills on Metal
  4 constant addresses is the sweet spot

The 4-mag LUT is the dequant-level ceiling on Apple Silicon.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
retroheim pushed a commit to retroheim/prism-ml-llama.cpp that referenced this pull request May 3, 2026
Complete experiment log:
  Mintplex-Labs#1  4-mag LUT:           15.1 at 8K (BEST, +38%)
  Mintplex-Labs#2  Batched extract:     13.7 (+25%)
  PrismML-Eng#3  Inline FA block:     13.5 (I-cache pressure)
  PrismML-Eng#4  Deferred norm:       12.9 (loses ILP)
  PrismML-Eng#5  2-pair half2:        12.0 (ternary overhead)
  PrismML-Eng#6  Select chain:        11.9 (branches kill)
  PrismML-Eng#7  Bit-arithmetic:      11.6 (ALU too heavy)
  PrismML-Eng#8  FMA branchless:      11.4 (ALU still too heavy)
  PrismML-Eng#9  Named-reg ternary:   10.3 (branches worst)
  PrismML-Eng#10 Main (8-LUT):        10.95 (baseline)
  PrismML-Eng#11 Non-vec FA:          10.2 (wrong kernel)
  Ceiling:                 24.5 (no dequant)

Apple8 hardware truth:
  1 divergent constant read < 7 ALU ops (even with fma)
  Branches cost MORE than divergent constant reads
  Array indexing ALWAYS spills on Metal
  4 constant addresses is the sweet spot

The 4-mag LUT is the dequant-level ceiling on Apple Silicon.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: tturney@psyguard.ai
khosravipasha pushed a commit that referenced this pull request Jul 13, 2026
* ggml-et: Add performance logging

* ggml-et: Quants helpers

* ggml-et: Add MUL_MAT kernel

* ggml-et: Add ROPE kernel

* ggml-et: Add RMS_NORM kernel

* ggml-et: Add GLU kernel

* ggml-et: Add SOFT_MAX kernel

* ggml-et: Add GET_ROWS kernel

* ggml-et: Add CONT kernel

* ggml-et: Add SET_ROWS kernel

* ggml-et: Add MUL_MAT_ID kernel

* ggml-et: Build et kernels as part of ggml

* ggml-et: Embed kernels with fs fallback

* ggml-et: Build fixes

* ggml-et: Add MUL_MAT F32xF32 op

* ggml_et: Add MUL_MAT_ID op

* ggml-et: Disable offloading for debug

* ggml-et: Refactor out block ops

* ggml-et: ggml backend API changes

* ggml-et: Add RESHAPE/TRANSPOSE to supported

* ggml-et: Add CONT_F16

* ggml-et: Add supported ops doc

* gglm-et: Initial doc

* ggml-et: Remove  runtime import hacks

We can now import the runtime by a simple find_package(), so we
can cleanup the CMakeLists.txt.

* ggml-et: Fix GET_ROWS kernel

Fix lost batch dimension.

Also clean vibe-comments.

* ggml-et: Fix SET_ROWS kernel

Remove incorrect broadcasting guard.

* ggml-et: Use custom instruction for fp32->fp16

* ggml-et: Vectorize set_rows fp32->fp16

* ggml-et: Fix ROPE kernel (yarn)

ggml-et: fix et_logf

WIP: Fix ramp

WIP: fix ROPE!

* ggml-et: Better sinf

* ggml-et: Fix SOFT_MAX

Add `max_bias` and `sink` support.

* ggml-et: Fix CONT

Reorder from contiguous write to read with atomic stores.

* ggml-et: Fix elmap kernel

Remainder handlin

* ggml-et: Fix MUL_MAT MUL_MAT_ID remainders

* ggml-et: Fix ET-SOC reference

* ggml-et: Fix embed kernels scripts for old python

This allows GGML-ET to build on pre-3.8 python.

* Add sysemu support with compile time flag `-DGGML_ET_SYSEMU=ON` (#6)

* Example using ET-Soc-1 emulator configuration

Example usage:
```bash
cmake -B build -DGGML_CUDA=OFF -DGGML_ET=ON -DLLAMA_CURL=OFF -DGGML_CCACHE=ON
cmake --build build --config Release -j $(nproc)

time ./build/bin/test-backend-ops

./build/bin/llama-server \
    --model Qwen3-0.6B-Q8_0.gguf \
    --alias Qwen3-0.6B-Q8_0 \
    -fa 0 \
    --ctx-size 1024 \
    --no-warmup \
    --host 127.0.0.1 \
    --port 8080
```

* build: proper dep tracking for kernels

* support host using MOLD linker

* initial multi core GET_ROW F32 implementation

* vectorized q8 dequant

* wip: cland warning clenaups and initial logging refactor

* wip: message default message cleanup

* chore: message cleanups

* cmake cleanup

* migrate to use platform provided functions

* cmake back into subdir

* support et_print() in kernels

* fix: repair kernel building

* perf: operations run async by default

* debug: proper kernel dep tracking and error detection on kenrel launch

* fix: kernel binary dep tracking and fixing get_rows_f32 erroring

* perf: back to doing async kernel runs by default

* perf: vectorize and parallel device memset

* merge matmul work

* misc: align allocation and enable all offload

* misc: delete deadcode and respect memory limits

* fix: repair tensor debug print

* fix: loosen RMS_NORM op percision

* feat: Q4_0 GET_ROWS

* perf: FP32 MUL_MAT using TensorFMA

* update limitations

* perf: redue L1 load in compute_block_dot_product_q8_0

* feat: save kernel mapping (name to id) when profiling is enabled

* chore: memops cleanup

* perf: parallelize softmax by rows

* perf: vectorize 2nd phase of softmax

* perf: ban GET_ROWS from offloaded

* perf: vectorize and non-atomic for eltwise ops and sub support

* perf: vectorize normal rope

* perf: glu runs in parallel

* merge: manually merge saqib's work on kernel fixes

* perf: more vectorized RoPE

* perf: parallelize mul_mat_id

* perf: parallelize set_rows_f32

* perf: vectorize softmax

* feat: support kernel fusion and fuse RMS_NORM + MUL

* fix: mostly resolve test-backend-ops failure in SOFT_MAX and ROPE

* fix: bump max rope dims for gemma

* feat: GeGLU and SCALE support to fully offload Gemma

* perf: faster device memset

* feat: get_rows supporting Q4_K and avoid cont cache coherent issues

* better F32 MM

* feat: NORM for ET backend

* feat: SQR for ET backend

* feat: UNARY on ET

* feat: el_map support broadcasting for ET

* feat: SUM_ROWS in ET backend

* feat: more ops in ET backend

* feat: WKV* operators in ET backend

* perf: parallelize operators across cacheline instead of row

* perf: parallelize get_rows on cacheline

* wip: baseline FlashAttention for ET backend

* wip: enough FA and CPY f32->f16 to run llama 3.1 fully offloaded with FA on

* feat: f16 x f16 -> f32 MM using matrix engine

* wip: f16 FlashAttention using matrix engine

* wip: clean up

* feat: barriers

* perf: optimize FA_F16 in ET

* perf: vectorize pack_k_for_transpose16

* perf: prefetch next loop matrix tile

* perf: FlashAttention 2nd MM uses TensorFMA and optimizations

* cleanup: flashattention reorg

* perf: optimizations and fixes

* feat: L2SCP API and make FlashAttention support DV = 256 for gemma

* perf: parallelize norms beyond single row

* feat: GATED_DELTA_NET support and relaxed L2_NORM requirment

* feat: loosen RMS_NORM, NORM, ROPE contingous req too

* feat: repeat supports brocasting on dim 0 and loosen cont check

* feat: FILL and DIAG operator

* feat: loosen UNARY support chcek

* feat: TRI support

* feat: SOLVE_TRI support

* feat: basic SET support

* feat: loosen CONT req

* perf: fp16_to_fp32 use ASM

* feat: IMROPE support

* feat: PAD support

* feat: global barrier

* fix: view must live on the same backend as backing tensor

* feat: relax CONCAT in ET backend

* feat: dead simple CUMSUM implementation

* feat: basic SSM_CONV support

* feat: loosen CONCAT req

* feat: relax GATED_DELTA_NET and add SET support proper

* cleanup: cleanup LCM math

* feat: SWIGLU single input

* feat: SSM_SCAN support

* feat: el_map supports non aligned tensors in best effort

* feat: basic GROUP_NORM support

* feat: loosen MUL_MAT capablities slightly

* feat: loosen MUL_MAT and GET_ROWS and add IM2COL

* feat: special case for softmax 1x1x1x1

* feat: loosen SOFT_MAX req in ET backend

* fix: el_map unaligned acse fixes

* perf: optimize zero_acc_vec in flash_attn_ext_f16_me

* perf: use hart 1 for packing in MM and FA for FP16

* feat: kernel semaphore

* perf: better instruction sequence in FlashAttention

* fix: gated_delta_net with proper masking

* perf: better parallelization for GATED_DELTA_NET

* perf: parallelize SSM_CONV over nr

* perf: vectorize SSM_CONV

* perf: optimize MUL_MAT for q8

* feat: support Gemma 4

* fix: support multi-device

* feat: broader GLU support

* feat: unary ops supports view

* fix: repair fp16 MM using matrix engine

* perf: handle large N GEMV better

* perf: better q8_0 MM

* perf: better set_rows

* add back deleted files

* fix: repair after merge

* feat: POC version of uberkernel

* feat: RMS_NORM in uberkernel

* feat: add more kernels into usage

* chore: clean up uberkernel compilation

* perf: faster flash attention

* perf: opt flash attention for large seq length

* feat: loosen op bounds. clamp and mean support

* perf: vectorize ssm_scan

* perf: slightly faster FA

* perf: FlashAttention parallel MM and load

* perf: fuse Q8 MM and ADD

* feat: basic conv kernel for ET

* softMAx_test

* set_rows_f32

* get_rows and cont

* testing

* set_rows_exp

* Junk addition

* Narrowing the issue

* Update flash_attn_ext_f16_me.c

Focusing FA_ext_f16_me

* test

* Eviction updated

* Detailed cache eviction debug

* mulmat

* removeal of `BUILD_FOR_UBERKERNEL` flag

* cleaning...

* fix: balance FCC0 count

* feat: implement mul_mat and mul_mat_id for Q4_0 type

* optimize uberkernel plan upload

* add mul_mat q4 into uberkernel

* enable gating flush to just uberkernel

* update docs for ET

* update op support for ET

* et-backend: optimize Q4_0 and Q8_0 mul_mat_id row accumulations

* et-backend: specialize mul_mat_id kernels for Q4_0 and Q8_0

* et-backend: fix RoPE YaRN corr_dim formula and handle degenerate inputs

* test-backend-ops: add DeepSeek-V2-Lite RoPE test coverage

* et-backend: add Q4_0 mul_mat matrix-engine kernel using TensorFMA32

* et-backend: vectorize Q4_0 matrix-engine dequantization

* et-backend: support hybrid matrix/vector engine execution for Q4_0 mul_mat tail

* et-backend: run partial-N tiles on matrix engine for Q4_0 mul_mat

* et-backend: route Q4_0 mul_mat N < 53 to vecdot for better prefill latency

* Update uberkernel.c

* Update unary_f32.c

* gemma 4

* bisect gemma4: enable scale_f32 only

* bisect gemma4: +rms_norm_f32

* bisect gemma4: +rms_norm_mul_f32

* bisect gemma4: disable rms_norm_mul_f32 -- BREAKS OUTPUT

* bisect gemma4: +rope_f32 (skip rms_norm_mul)

* bisect gemma4: +el_map_f32

* bisect gemma4: +softmax_f32

* bisect gemma4: +get_rows_f32

* bisect gemma4: +glu_f32

* bisect gemma4: +mul_mat_f32 +mul_mat_f32_matrix_engine

* bisect gemma4: +mul_mat_f16 +mul_mat_f16_matrix_engine

* bisect gemma4: +mul_mat_Q8_0 +mul_mat_Q4_0

* bisect gemma4: +flash_attn_ext_f32 +flash_attn_ext_f16_me

* bisect gemma4: +mul_mat_id_f32

* bisect gemma4: +sum_rows_f32

* bisect gemma4: +cont_f16

* bisect gemma4: +fill_f32

* bisect gemma4: +unary_f32 (all ops re-enabled except rms_norm_mul)

* Update rms_norm_mul_f32.c

* bisect2 gemma4 n64: +scale_f32 only

* bisect2 gemma4 n64: +rms_norm_f32 +rope_f32

* bisect2 gemma4 n64: +rms_norm_mul_f32 (with ET_UBERKERNEL eviction fix)

* bisect2 gemma4 n64: +el_map +get_rows +glu +softmax (skip rms_norm_mul)

* bisect2 gemma4 n64: all ops enabled except rms_norm_mul

* bisect2 n64: test unary+cont+fill+sum_rows (no mul_mat/flash_attn)

* bisect2 n64: +mul_mat_f32 +mul_mat_f32_matrix_engine

* bisect2 n64: +mul_mat_f16 +mul_mat_f16_matrix_engine

* bisect2 n64: +mul_mat_Q8_0 +mul_mat_Q4_0

* bisect2 n64: +mul_mat_Q8_0 only (disable Q4_0)

* bisect2 n64: +mul_mat_Q4_0 only (Q8_0 breaks)

* bisect2 n64: +mul_mat_id +flash_attn_ext (skip Q8_0)

* run-3: matmul + rms_norm_mul

* run-4

* Revert "run-4"

* run5

* changes after cleanup

* cleanup before upstream

* restrict changes into ET backend

* move kernel embedding from Python to CMake

* move uberkernel gen into CMake

* apply clang format

* update CMake style

* update to match C and C++ style

* use source ggml and quant headers instead of ET's

* MROPE support

* absorb view ops into same branch as none

* fix bad rebase

* add marty1885 to codeowners

* oops

* remove redundant newline

* fix CI editor warnings

---------

Co-authored-by: Vidas <vidas@nuolat.lt>
Co-authored-by: Gianluca Guida <glguida@tlbflush.org>
Co-authored-by: Gianluca Guida <gianluca@nekko.ai>
Co-authored-by: ubergarm <leimgrub@gmail.com>
Co-authored-by: SaqibAkram-10xE <saqib.akram@10xengineers.ai>
Co-authored-by: Rehan Qasim <rehan.qasim@10xengineers.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants