i8 x i8 MaxSim Kernels - #1429
Suryansh Gupta (suri-kumkaran) wants to merge 10 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1429 +/- ##
==========================================
+ Coverage 91.92% 91.95% +0.02%
==========================================
Files 580 581 +1
Lines 114938 115864 +926
==========================================
+ Hits 105657 106542 +885
- Misses 9281 9322 +41
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Dimensions above 131,071 can overflow the new i32 accumulation paths and produce panics or incorrect scores.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Adds exact i8 × i8 MaxSim support with architecture-specific kernels and i32 scores.
Changes:
- Adds Scalar, V3, V4, and Neon integer kernels.
- Extends packed layouts and MaxSim APIs for typed scores.
- Adds correctness tests and benchmark configurations.
| File | Description |
|---|---|
diskann-wide/src/arch/aarch64/u32x4_.rs |
Adds Neon reinterpretation support. |
diskann-quantization/src/multi_vector/distance/kernel.rs |
Generalizes kernel score types. |
diskann-quantization/src/multi_vector/distance/fallback.rs |
Adds reference i8 scoring. |
diskann-quantization/src/multi_vector/distance/factory.rs |
Wires i8 kernels and dispatch. |
diskann-quantization/src/matrix_kernels/util.rs |
Adds integer conversion and load/store helpers. |
diskann-quantization/src/matrix_kernels/test_util.rs |
Adds random i8 test data. |
diskann-quantization/src/matrix_kernels/maxsim/test.rs |
Adds integer test generation. |
diskann-quantization/src/matrix_kernels/maxsim/packed_i8_x_unpacked_i8.rs |
Implements integer MaxSim kernels. |
diskann-quantization/src/matrix_kernels/maxsim/packed_f32_x_unpacked_f32.rs |
Updates renamed test helper usage. |
diskann-quantization/src/matrix_kernels/maxsim/packed_f32_x_unpacked_f16.rs |
Updates renamed test helper usage. |
diskann-quantization/src/matrix_kernels/maxsim/mod.rs |
Exposes the integer kernel module. |
diskann-quantization/src/matrix_kernels/blocks/unpacked.rs |
Exposes remainder start offsets. |
diskann-quantization/src/matrix_kernels/blocks/packed.rs |
Adds packed contraction grouping. |
diskann-benchmark/src/multi_vector/kernels.rs |
Registers i8 benchmarks. |
diskann-benchmark/src/multi_vector/driver.rs |
Supports element-specific score buffers. |
diskann-benchmark/perf_test_inputs/multi-vector.json |
Adds i8 performance jobs. |
diskann-benchmark/example/multi-vector.json |
Adds example i8 jobs. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Mark Hildebrand (hildebrandmw)
left a comment
There was a problem hiding this comment.
I mainly looked at the stuff in matrix_kernels. I think this is mostly okay to merge. It is starting to show some cracks in our abstractions (I made a few notes in the inline comments), and this gets worse with #1394.
The general problems that are emerging are
- The fixed tiling iteration order. I'm still not sure if it's the best nor how k-blocking will affect things.
- The long-range implicit contracts between panel preparation and the micro-kernels. I would feel much better if there was a single source of truth for how these things interacted. However, I don't have an actual concrete suggestion yet.
Thanks for the review, Mark. Agreed on both points. I felt the second one most with V4: the query is packed as x + 128 in the factory, while the -128 * column sum that cancels it is computed in PrepareB , and only comments and tests tie the two together. For the tiling order I reused the f32 one as is, so I don't have a better idea there yet. Happy to help work out a cleaner design along with #1394. |

Integer MaxSim matrix kernels for
i8 x i8, alongside the existing f32 and f16 paths.Scores stay in
i32end to end instead of routing through f32, so results are exact.Status
Scalar, V3, V4 and Neon each have their own kernel. Known gaps:
i16pair dot, which widens each lane toi32before multiplying. PACK = 1 versions were slower still.What is here
The packed
ViewandPanelinmatrix_kernels::blocks::packedgain aPACKparameter (default 1, as inBlockTransposed), so contraction elements can be interleaved to match the width of the dot product instruction.i8i16vpmaddwdu8, asx + 128vpdpbusdi8sdotPACK differs by target because the instruction does.
vpmaddwdis a 2 way dot per 32 bit lane,vpdpbusdandsdotare 4 way.A
PrepareBseam in the driver prepares each L1 sized block of B (the documents) before the micro-kernels use it:i16. The query is widened when the kernel is built, so the inner loop does no widening.vpdpbusdis unsigned by signed, so the query is stored asx + 128inu8, and each accumulator starts at-128times its column sum to cancel the shift.MaxSimElementis implemented fori8and gains aScoretype (i32for i8,f32for f32 and f16) and aNO_MATCHscore for empty documents.MaxSimKernel<T>andErase<T>now takeT: MaxSimElementinstead ofT: Copy, andcompute_max_simwrites to&mut [T::Score]. f32 and f16 callers still pass&mut [f32]. Generic code needs the new bound.build_max_simnow returnsBuildMaxSimErrorinstead ofNotSupported. It wrapsNotSupportedand addsDimTooLarge, which the i8 build returns for queries with more than 131_071 dimensions. Products are bounded by 128 * 128, so that is the largest dimension wherei32cannot overflow.Also adds:
AutoandReferenceagainstMaxSim, including the fulli8range, and tests on either side of the dimension limit.max_sim_kernel_i8infallback.rsfor the i8referenceISA.int8as an element type formulti-vector-op, with example and perf test jobs.SIMDReinterpret<i8x16> for u32x4on aarch64 in diskann-wide, for the Neon broadcast, with a test.Performance
V3 and V4 on a Xeon Gold 6426Y, best of 30 interleaved runs over two job orders, reference held at 1.000 as control:
Neon on an Apple M5 Pro, best of 15 interleaved runs: 1.75x geomean over reference, 1.66x to 1.88x across shapes. Measured on an earlier revision and not re-run since.