ggml-cpu: hoist loop-invariant constant and 2-block unroll in AVX2 ggml_vec_dot_q4_0_q8_0 - #22
Open
codspeed-hq[bot] wants to merge 1 commit into
Conversation
…ml_vec_dot_q4_0_q8_0 Hoist the loop-invariant nibble-offset vector (off = _mm256_set1_epi8(8)) out of the per-block loop instead of rebuilding it every iteration, and process two blocks per iteration using two independent FMA accumulator chains with a tail loop for an odd block count. This halves the loop-control overhead per block and removes the redundant per-block constant materialization. The change is confined to the __AVX2__ path; the block math is unchanged and the result matches the single-accumulator sum. Verified with test-quantize-fns (all types pass). CodSpeed simulation: mul_mat[q4_0] 101.9ms -> 98.35ms cpuTotal (~3.8% fewer instructions), no regressions.
Author
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
Optimizes the AVX2 implementation of
ggml_vec_dot_q4_0_q8_0inggml/src/ggml-cpu/arch/x86/quants.c, the dot-product kernel that dominates Q4_0 matrix multiplication (mul_mat[q4_0]) — the bulk of every linear/projection layer when running Q4_0-quantized weights.Analysis
Flamegraph analysis of the
mul_mat[q4_0]benchmark (baseline ~101.9 ms, 92% instruction-bound) showed nearly all time insideggml_vec_dot_q4_0_q8_0. Two cheap-to-fix instruction overheads were visible in the per-block loop:off = _mm256_set1_epi8(8)was rebuilt inside the block loop on every iteration even though it is loop-invariant.Change
offvector out of the block loop (built once).acc0,acc1), with a small tail loop for an odd block count. The two accumulators are summed before the existing horizontal reduce.This roughly halves the loop-control overhead per block and removes the redundant per-block constant materialization. The change is confined to the
__AVX2__path; the__AVX__/__SSSE3__/scalar paths are untouched, and the block math itself is unchanged.Correctness
The result is mathematically the original sum, only regrouped across two accumulators before the reduce (same precedent as the existing f32 dot-product accumulator grouping). Verified locally with
test-quantize-fns(AVX2 build): all types pass, includingq4_0, so the dot-product error stays within tolerance.Performance (CodSpeed, CPU simulation)
Measured with the CodSpeed CLI in an identical local environment (base = parent commit
46819c9, head = this change):mul_mat[q4_0]mul_mat[q4_0]Cache and memory components are unchanged (deterministic instruction-count reduction), and the other 14 benchmarks are unchanged — no regressions.