Repository navigation
docs(avx2-repack-design): Phase 1 design brief for runtime repack of Q1_0_g128 - #10
Merged
Merged
Conversation
flake8-no-print 0.1.x hard-pins flake8==4.0.1, which conflicts with the pinned flake8 7.0.0 in this config. The unresolvable dependency graph caused 'pre-commit' to fail to even install the hook environment, so every 'git commit' on this repo was blocked before any actual lint ran. Drop the additional_dependencies entry; flake8 7.0.0 still runs the default pyflakes/pycodestyle checks. If we want a no-print rule back later, we can re-introduce it via a flake8 plugin that's compatible with flake8 >= 7.
…Q1_0_g128
Adds three design documents under docs/avx2-repack-design/. No source
code changes; this is a Phase 1 research/design deliverable that needs
sign-off before Phase 2 (microbenchmark) and Phase 3 (kernels) begin.
* 01-survey.md — annotated walkthrough of the existing mainline Q4_0
repack pattern (block templates, helpers, repack converters, GEMV
entry, dispatcher, backend buffer registration), with file:line refs
into this fork. The new Q1_0_g128 repack will mirror this template
exactly.
* 02-q1-layout.md — inventory of the prism block_q1_0_g128 layout
(18 B per block: f16 delta + 16 packed weight bits), instruction-
count breakdown of the existing AVX-512 fast path (~3 ops / 32
weights via vpdpbusd) vs the AVX2 fallback (~10 ops / 32 weights
via shuffle-broadcast + cmpeq + vpmaddubsw + vpmaddwd). Lists four
optimization levers ranked by ease/ROI.
* 03-design-brief.md — concrete proposal:
- block_q1_0_g128x4 layout (4 deltas + 4 × 16 packed bytes interleaved
at 4-byte granularity = 72 B). 4-row interleave, no on-disk format
change, repack happens at tensor-allocation time (mirrors mainline
Q4_0_4_4 / 8_8 mechanism).
- Two GEMV kernel branches: AVX2-only (zen 3, skylake-X-no-VNNI) and
AVX-VNNI (Alder Lake P-cores, Zen 4), both consuming the same
packed-block format, dispatched on ggml_cpu_has_avx_vnni() then
ggml_cpu_has_avx2(). AVX-512 hosts use the existing fast path.
- sum(qy) computed on the fly inside the kernel (no per-block extra
storage in the activation block).
- Test plan: bit-identical parity vs the existing single-row vec_dot,
e2e log-prob diff vs Q1_0_g128, generic fallback for non-x86 hosts.
- Implementation phases: 6 phases totaling 5–7 working days for the
kernels + GEMM + tests + microbench harness.
- Sign-off checklist at the bottom for Ken to review before Phase 2
starts.
Expected speedup on the EPYC 7763 demo VM: ~2.5× (23 t/s → 50–60 t/s
prefill on Q1_0_g128 prefill), keeping the 248 MB on-disk footprint.
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
… sums vectorised Devin Review caught a real correctness bug in the GEMV kernel A pseudocode in 03-design-brief.md (PR #10). The inner loop reduced 'partial_v' and 'sum_qy_v' to scalars via 'hsum_epi32', then broadcast the result back to all 8 lanes of '__m256 acc[r]' via '_mm256_set1_ps'. The closing 'hsum_float_8(acc[r])' would then sum 8 identical lanes, producing 8x the correct output. Fix: keep partial sums as per-lane '__m256i' vectors throughout the inner loop (no horizontal-sum in the hot path), do the final '2*partial_v - sum_qy_v' in vector form, convert to float, and let the existing 'hsum_float_8' at write-out correctly combine the per-lane partial sums. This matches the pattern used by the AVX-VNNI kernel B in the same document and by 'mul_sum_i8_pairs_float' at ggml/src/ggml-cpu/arch/x86/quants.c:937. The amortised op-count table is updated to reflect the actual ops in the corrected kernel (~12 ops/32 weights/row before sharing, dropping to ~3.5-4 amortised across 4 rows per sub-block load) \u2014 the end-to-end speedup target on the EPYC 7763 demo VM is unchanged (~50-60 t/s prefill, ~2.5x over un-repacked AVX2 single-row).
This was referenced May 1, 2026
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
Phase 1 (research / design) of a multi-phase project to give
Q1_0_g128a meaningful AVX2 throughput uplift on hosts that lack AVX-512 (Zen 3, Skylake-X-non-VNNI, etc.) without changing the on-disk GGUF format and without touching the existing AVX-512 / CUDA / Metal / Vulkan / NEON fast paths.This PR adds only three design documents under
docs/avx2-repack-design/. No source code is changed in this PR. It is a sign-off PR — once the design is approved, follow-up PRs implement the microbenchmark harness (Phase 2), the kernel intrinsics (Phase 3), and the dispatcher / repack plumbing (Phase 4).Why
On the cv-guard demo VM (AMD EPYC 7763, Zen 3, AVX2 only),
Bonsai-1.7B.gguf(Q1_0_g128, 248 MB) currently prefills at 23 t/s, giving a 38 s P50 perdecide()call. Investigation showed the AVX2 path is already enabled and is correctly executing 256-bit AVX2 instructions — the perf gap vs AVX-512 is real and fundamental to the existing AVX2 inner loop (~10 ops per 32 weights vs ~3 ops on AVX-512 VNNI). Seedocs/avx2-repack-design/02-q1-layout.mdfor the instruction-count breakdown.Mainline ggml already solves this exact pattern for Q4_0 via
Q4_0_4_4 / 4_8 / 8_8runtime repacking: weights are physically re-laid-out at tensor-allocation time so a single SIMD load services 4 or 8 output rows in parallel. The on-disk GGUF format stays identical; only the in-memory layout changes. This PR proposes mirroring that exact mechanism forQ1_0_g128.What's in this PR
docs/avx2-repack-design/01-survey.md— annotated walkthrough of the existing mainline Q4_0 repack pattern (block templates,make_block_*helpers, repack converters, GEMV entry points, dispatcher, backend buffer registration), withfile:linereferences into this fork. The new Q1_0_g128 repack will mirror this template exactly.docs/avx2-repack-design/02-q1-layout.md— inventory of the prismblock_q1_0_g128layout (18 B per block: f16 delta + 16 packed weight bits), and an instruction-count breakdown of the existing AVX-512 fast path vs the AVX2 fallback. Lists four optimisation levers ranked by ease and ROI.docs/avx2-repack-design/03-design-brief.md— concrete proposal:block_q1_0_g128x4layout (4 deltas + 4 × 16 packed bytes interleaved at 4-byte granularity = 72 B), AVX2-only and AVX-VNNI GEMV kernels, dispatcher gate, test plan, microbenchmark plan, 6-phase implementation schedule, and a yes/no sign-off checklist at the bottom.What this PR is not
ggml_typeenum changes, noggml.hABI changes, no on-disk GGUF format changes — ever. The repack happens at tensor-allocation time only.Bonsai-1.7B.ggufor any other model artifact.Expected outcome (once the full project lands)
Pre-commit fix (precursor commit on this branch)
The pre-commit config pinned
flake8-no-printas an additional dependency forflake8 7.0.0, butflake8-no-print0.1.x hard-pinsflake8==4.0.1— an unresolvable dependency conflict that preventedpre-commitfrom installing the hook environment, so everygit commiton this repo was blocked. This branch includes a one-line precursor commit dropping that additional dependency. flake8 7.0.0 still runs the default pyflakes/pycodestyle checks. If we want a no-print rule back later, we can re-introduce it via a flake8 plugin compatible with flake8 ≥ 7.Sign-off
Per the checklist in
03-design-brief.md, this design is gated on yes/no answers to:block_q1_0_g128x4(4 deltas + 4 × 16 quant bytes, 4-byte interleave, 72 B total) — OK?sum(qy)computed on the fly inside the kernel (not stored in the activation block) — OK?ggml_typeenum changes, noggml.hABI changes — OK?A "yes" on all 7 boxes triggers Phase 2 (microbench harness PR).
Link to Devin session: https://uney.devinenterprise.com/sessions/576d78b01f9b4389b375033162f7b7b4
Requested by: @kennguy3n