Files
Ivan PleshkovandClaude Fable 5 94f3abeb22 Turbo4 dotprod batch (#10392)
* QuerySimd::dotprod_batch: score a contiguous run of vectors in one call

The entry point for scanning a contiguous run of encoded vectors at a
stride: `out[v]` ← score of the vector at `data[v * stride..]`.  It
scores vector by vector for now; the SIMD batch kernels that share the
query loads across vectors follow.

Bench: `query{4,2,1}bit_dotprod_scan` — a hot query against runs of 512
consecutive vectors streaming from DRAM at the TurboQuant stride, per
vector and through `dotprod_batch`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* QuerySimd: interleaved AVX-512 batch kernel with a fused reduction

Vectors up to four cache lines are scored in groups of four that share
every query block load and tail mask; the group's independent
accumulators keep `VPDPBUSD` saturated while one vector's reduction
overlaps with the next group's loads.  Longer vectors keep the
per-vector walk, since the hardware prefetcher streams four interleaved
byte streams far worse than one (measured at the 4-bit width: +10 % at
dim 512, 2× slower at dim 1024).

The per-vector reduction fuses the query bytes before the horizontal
sum — `low + K · high` in i32 lanes, then one tree that widens to i64
at the end — for vectors within a per-width lane bound derived from the
encoding (2040 bytes at 4 bits, 1020 at 2, 255 for the wide 1-bit
query; unbounded for a one-byte query).  A test pins the derivation to
the hand-computed 4-bit value and drives every width to its bound with
the heaviest possible inputs.

Bench: `batch_avx512_vnni` rows in the scan groups.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* QuerySimd: AVX2 batch kernel; one fused reduction for AVX2 and AVX-512

The AVX2 batch kernel scores vectors one at a time: its loop-carried
chain is a single `vpaddd` per accumulator (the `maddubs → madd`
products hang off the loads), so interleaving vectors only adds
register pressure on the 16 YMM registers — measured 10–15 % slower
with groups of two or four at the 4-bit width.

The AVX2 per-vector reduction now uses the same fused tree as the
AVX-512 one, within the same per-width lane bound; the bound test
drives both kernels.

Bench: `batch_avx2` rows in the scan groups.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* QuerySimd: copy the tail block in constant-size pieces

The SSE, AVX2 and NEON kernels run their last partial block on a
zero-padded copy of the remaining bytes.  A `len`-byte copy compiles to
a `memcpy` call plus a `memset` for the padding — and the call forces
the accumulators out of their registers around it.  Copy in power-of-
two pieces of constant size instead: `len` is the same for every vector
of a query, so the piece branches predict perfectly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* QuerySimd: interleaved NEON batch kernels

The SDOT and plain NEON block loops take `N` vectors at a stride, and
the batch entry points score vectors up to four cache lines in groups
of four — the same policy as the AVX-512 kernel, with the group
threshold carried over from the AVX-512 measurement rather than tuned
on ARM hardware.

Bench: `batch_neon` and `batch_neon_sdot` rows in the scan groups.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-09-02 09:39:32 +02:00
..
2026-09-02 09:39:32 +02:00