ggml-cpu: 2x2 register-blocked AVX2 kernel for ggml_vec_dot_q4_K_q8_K - #36
Open
codspeed-hq[bot] wants to merge 1 commit into
Conversation
Add an nrc == 2 path to the x86 Q4_K dot product so that a 2x2 output tile decodes each src0 row's scales/mins and 4-bit weights once instead of four times, and enable nrows = 2 for GGML_TYPE_Q4_K under AVX2 so ggml_compute_forward_mul_mat drives it. The per-block accumulation order matches the existing 1x1 path, so the results are bit-identical.
Author
Merging this PR will improve performance by 36.42%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | Simulation | mul_mat[q4_k] |
72.4 ms | 53.1 ms | +36.42% |
Tip
Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.
Comparing codspeed-optim-2-2-register-blocked-avx2-kernel-for-ggml-vec-dot-1785301877014 (471ee09) with master (46819c9)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Q4_K matrix multiplication on x86 computes one output element per
ggml_vec_dot_q4_K_q8_K()call. Every call re-does the full per-block weight decoding - the 6-bit scale/min unpacking, the_mm256_cvtepu8_epi16+ shuffle broadcast of the scales, and the 4-bit nibble extraction - even though those depend only on the src0 row. Computing a 2x2 output tile therefore decodes the same weights twice.This adds an
nrc == 22x2 register-blocked path: two src0 rows against two src1 columns in one pass.ggml_compute_forward_mul_mat()already drives this throughggml_type_traits_cpu::nrows- it is the path the ARMi8mmkernels use, andGGML_TYPE_Q4_Kalready setsnrows = 2there. x86 was simply missing the kernel, so this closes an existing gap rather than adding new machinery.Files changed (2, +125/-1)
ggml/src/ggml-cpu/arch/x86/quants.c- the blocked kernel plus a smallhsum_float_4()helper.ggml/src/ggml-cpu/ggml-cpu.c-GGML_TYPE_Q4_Ktraitnrows = 2also under__AVX2__.Why it helps
Per 64-weight sub-block, the blocked kernel decodes each row's nibbles and scales once and feeds them into four
maddubs/maddchains instead of four independent decodes. All four accumulators, both scale vectors and the nibble masks stay in registers.Measured impact (CodSpeed, CPU simulation)
benchmarks/bench_ggml.cpp::mul_mat[q4_k]benchmarks/bench_macro.cpp::prompt_layer[q4_k]Everything else is unchanged:
mul_mat[f32],mul_mat[q4_0],prompt_layer[f32],prompt_layer[q8_0]andprompt_layer[q4_0]all report as unchanged (byte-identical values for the pure-f32/q4_0 micro benchmarks).Correctness
The per-block accumulation order is identical to the existing 1x1 path, so results are bit-identical, not merely close. Verified locally by building the same
ggml_mul_matQ4_K test program against an unpatched and a patchedlibggml, dumping every output float, and comparing the raw bytes:cmpclean over 529 KB of results).nrc == 2result confirms the new path is genuinely taken for the even shapes and not for the odd-M/N or N = 1 cases, so the bit-exactness is not a false negative.test-quantize-fnspasses;test-backend-ops -o MUL_MATis OK (a CPU-only run has no second backend to compare against).arch/x86/quants.ccompiles warning-free with-msse4.2,-mavx -mf16c,-mavx2 -mfma -mf16cand-mavx512f/bw/vl/dq.Scope
The 2x2 path activates only when
nr0 % 2 == 0,ne11 % 2 == 0and both chunk extents are even - i.e. prompt processing and the LM head. Single-token decode (ne11 == 1) keeps the existing 1x1 path and is untouched, as are all non-AVX2 targets and every other quantization type.