Skip to content

Feat/q2 avx2 bitplane - #706

Closed
merbanan wants to merge 2 commits into
Niko1221:mainfrom
merbanan:feat/q2-avx2-bitplane
Closed

merbanan wants to merge 2 commits into
Niko1221:mainfrom
merbanan:feat/q2-avx2-bitplane

Conversation

@merbanan

@merbanan merbanan commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

A new AVX2 row kernel for Q2_0 experts on CPUs without AVX-512, the default path in q2_0_gguf_rows_multi_avx2.

Single thread, weights in L2: 2.3–2.8× faster at every token count from 1 to 4.

merbanan and others added 2 commits October 4, 2026 02:37
The activation is pre-permuted once per token into the 2-bit codes' plane order (ActQ::qp/psum/pscale), so rows need no unpack interleave: four planes summed in int16, one madd, the -1 code offset subtracted exactly in the integers, one FMA per two blocks per token. 2.3-2.8x faster per core than the b256 kernel, closer to exact (rms rel 1.0e-7 vs 2.7e-7), width-invariant. STRATA_Q2_LEGACY=1 selects the previous kernel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Down rows are only 10 blocks, so the per-row reduction was a large share; four rows now share one hadd tree. The single-row reduction uses the same tree, so a row's bits do not depend on how rows are split into tasks. Down rows +6-7% per core.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@star1872

star1872 commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Measured on a Haswell-EP Xeon with slow DDR3, where the PR said end-to-end was not measured on such a machine.

PC: Xeon E5-2673 v3 (12 cores, AVX2, no AVX-512), 3 x 32 GB DDR3-1866 LRDIMM (the first 64 GB interleaved over two
channels, ~26 GB/s read with 11 threads; buffers allocated with the page cache dropped), RTX 4060 Ti 16 GB on PCIe 3.0 x8, Ubuntu 24.04. Engine: main at 6f32ec0 (0.1.39) built from source with
CUDA 12.8 for sm_89, plus this PR's two commits (applied cleanly to q2_avx2.cpp and expert.hpp). Model: original
Q2_0 (GSQ-RCO), setup's default config for this PC (64K, int8 KV, --spec 4 --spec-min-p 0.5).

Kernel alone (a small harness calling q2_0_gguf_rows_multi_avx2 on synthetic experts in the GGUF layout,
gate/up 1280 rows + down 2560 rows, 11 threads; "DRAM" = 4000 experts round-robin, "L3" = 16 experts):

tokens per expert main, L3 / DRAM this PR, L3 / DRAM
1 29.8 / 24.5 GB/s 74.8 / 24.7 GB/s
2 16.8 / 16.2 42.3 / 24.6
3 13.3 / 13.0 32.3 / 24.2

On this CPU the current kernel is compute-bound from two tokens per expert on (L3 and DRAM give the same rate); with
this PR every token count reaches the memory bandwidth.

Numerics: against a double-precision evaluation of the same formula (d · Σ(code−1)·q·scale, random blocks and
activations, 1..8 tokens, n = 2560 and 640): max error / Σ|terms| is 3.4e-8 for this PR, 6.5e-8 for main; the two
differ by 7.9e-8 (summation order).

End to end (server, 4 prompts: Chinese essay, code edit, translation, explanation; greedy, 512 tokens, thinking
off, 2 passes each; same binary, STRATA_Q2_LEGACY=1 for the old kernel, interleaved old/new/old/new):

old this PR
mean of the 4 prompts 49.16, 48.55 tok/s 51.30, 50.59 tok/s

+4.3%; all 8 prompt pairs faster (essay 47.0/47.0 → 47.9/47.5, code edit 48.5/48.1 → 50.5/50.6, translation
44.7/44.0 → 47.9/45.9, explanation 56.5/55.1 → 58.9/58.4). In the code-edit windows (STRATA_DECODE_TIMING=1) the
CPU part went from 39.3 to 36.6 ms per window. It is less than the kernel numbers because the pool's two phase
barriers per layer now take a larger share (~0.18 ms per layer in those windows).

imanu86 added a commit to imanu86/Strata-2080Ti that referenced this pull request Oct 5, 2026
Il kernel Q2_0 AVX2 di default spacchetta i codici con 8 operazioni invece di
~17 (stessi vettori lo/hi byte per byte), moltiplica d per la scala in vettore
e lavora 4 righe insieme sui down corti: ogni operazione in virgola mobile e'
la stessa, nello stesso ordine. STRATA_Q2_LEGACY=1 tiene il kernel precedente.
Differenza dalla PR upstream Niko1221#706, che fonde le scale di due blocchi e cambia
l'arrotondamento (KL 0,0008-0,0015 a posizionamento fisso).

Verifica: q2_exact_parity 504 casi, 570.634 uscite identiche bit per bit al
kernel precedente; pool_quant_parity 64 casi sul GGUF reale; teacher forcing a
posizionamento fisso identico bit per bit su code ed explain. Un thread:
1,11-1,45x; pool reale (7 worker): down Q2_0 -4%, gate/up Q2_0 -8%, tutto Q2_0
-17% per strato. A 131k nel rumore (la CPU calcola ~2 esperti per strato).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Niko1221 added a commit that referenced this pull request Oct 6, 2026
…T1=1); the default keeps 0.1.39's rounding

Items 1-2 of #863 (gathered decode per core, AVX-VNNI rows) are bitwise and stay. Item 3 changes a lone token's IQ3_S
rounding on Intel hybrid CPUs, so it needs the switch. The #706 bit-plane path stays in front of the VNNI/plain rows.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Niko1221

Niko1221 commented Oct 6, 2026

Copy link
Copy Markdown
Owner

In 0.1.40, opt-in: STRATA_Q2_BITPLANE=1 selects the bit-plane kernel (off by default, the activation image is only built when it is on). New q2_bitplane_parity test: against the legacy kernel within tolerance, and bitwise for a token alone vs in a window vs split row ranges.

@Niko1221 Niko1221 closed this Oct 6, 2026
Niko1221 added a commit that referenced this pull request Oct 6, 2026
…T1=1); the default keeps 0.1.39's rounding

Items 1-2 of #863 (gathered decode per core, AVX-VNNI rows) are bitwise and stay. Item 3 changes a lone token's IQ3_S
rounding on Intel hybrid CPUs, so it needs the switch. The #706 bit-plane path stays in front of the VNNI/plain rows.
anon761 pushed a commit to anon761/Strata-upstream that referenced this pull request Oct 6, 2026
…T1=1); the default keeps 0.1.39's rounding

Items 1-2 of Niko1221#863 (gathered decode per core, AVX-VNNI rows) are bitwise and stay. Item 3 changes a lone token's IQ3_S
rounding on Intel hybrid CPUs, so it needs the switch. The Niko1221#706 bit-plane path stays in front of the VNNI/plain rows.
Niko1221 pushed a commit that referenced this pull request Oct 7, 2026
…0 x8), Q2_0 and IQ3_S, 0.1.39 path vs #706 + #764 + a busier tier (#913)

Bench folder ported from PR #913 by 1872183316, authorship kept.
Trimmed for 0.1.40.2: 0 raw dumps/logs/binaries left out (listed in TRIMMED.md of each folder).
Not ported: docs/COMMUNITY_BENCHMARKS.md.
sskver pushed a commit to sskver/Strata that referenced this pull request Oct 7, 2026
…T1=1); the default keeps 0.1.39's rounding

Items 1-2 of Niko1221#863 (gathered decode per core, AVX-VNNI rows) are bitwise and stay. Item 3 changes a lone token's IQ3_S
rounding on Intel hybrid CPUs, so it needs the switch. The Niko1221#706 bit-plane path stays in front of the VNNI/plain rows.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants