Optimize AVX2 ggml_vec_dot_q8_0_q8_0: hardware F16C scale conversion + 2-accumulator unroll - #30
Open
codspeed-hq[bot] wants to merge 1 commit into
Conversation
…ulator unroll Use the hardware vcvtph2ps instruction (via GGML_CPU_COMPUTE_FP16_TO_FP32) to convert the per-block FP16 scales instead of the 64K-entry lookup table when F16C is available, and split the main loop into two independent FMA accumulator chains to hide FMA latency. A scalar tail handles an odd trailing block. Results are unchanged (vcvtph2ps is the exact IEEE-754 half->single value).
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 path of
ggml_vec_dot_q8_0_q8_0(ggml/src/ggml-cpu/arch/x86/quants.c) — the q8_0×q8_0 dot product that drives every q8_0 matrix multiplication (attention/FFN projections and the LM head).Two changes in one kernel:
Hardware F16C scale conversion. Each block's two FP16 scales (
x.d,y.d) were converted to FP32 through the generic 64K-entry lookup table (ggml_lookup_fp16_to_fp32). Flamegraph analysis of the macro benchmarks showed this table access as a hot spot inside the dot product. On x86 with F16C the conversion is a singlevcvtph2psinstruction, so the kernel now uses it directly (scoped, local#define, falling back to the lookup table when F16C is unavailable).Two-accumulator unroll. The main loop processed one block per iteration with a single accumulator, so the per-block
_mm256_fmadd_psformed one serial dependency chain (latency-bound). It now processes two blocks per iteration into two independent accumulators, summed once at the end, hiding FMA latency on out-of-order cores. A scalar tail handles an odd trailing block.Correctness
The
vcvtph2psconversion produces the exact IEEE-754 half→single value (identical to the lookup-table entries for finite inputs), and splitting the float accumulation into two chains matches the reordering already used by the sibling AVX kernel in the same file. Verified with the repository'stest-quantize-fnssuite (built with-DGGML_NATIVE=ON, i.e. exercising the AVX2/F16C/FMA path) — all quantization types, including q8_0, pass with no errors.Performance (CodSpeed, CPU simulation)
Measured in-sandbox on the q8_0 macro benchmarks with matched base/head builds, two runs each. Under CPU simulation the cache-miss metric is the most stable signal; instruction counts have some run-to-run variance because the graph compute is multi-threaded, so values below are averaged over two runs.
prompt_layer[q8_0]lm_head[q8_0]decode_layer[q8_0]decode_layer[q8_0]sits within run-to-run noise: it is a single-token decode where the dot product is only ~21% of the benchmark and dominated by the (unchanged)qsloads, so this kernel change has little leverage there. No regressions on the other 12 (non-q8_0) benchmarks.The 2-accumulator unroll additionally targets FMA latency, which the CPU-simulation instrument does not model — its benefit is expected to show up on the walltime macro runners in this PR's CI.