Skip to content

[MOD-14952] Support normalization in QuantPreprocessor#1000

Merged
dor-forer merged 5 commits into
mainfrom
dor-forer-MOD-14952-support-quant-normalization
Jul 26, 2026
Merged

[MOD-14952] Support normalization in QuantPreprocessor#1000
dor-forer merged 5 commits into
mainfrom
dor-forer-MOD-14952-support-quant-normalization

Conversation

@dor-forer

@dor-forer dor-forer commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Describe the changes in the pull request

PR #999 has merged. This PR targets main and builds on its stored-to-query distance dispatch.

Cherry-picks ARM's 027d5510b2bf7add6a45be9b0c07cda38c15b5ca from ARM-software/VectorSimilarity-for-Arm#2.

This PR adds an optional normalization-aware mode to QuantPreprocessor. It stores the mean-vector inner product as additional SQ8 metadata for normalized storage and queries, extends SQ8 metadata sizing, and shares a float-based quantization implementation to avoid duplicated logic.

Existing QuantPreprocessor configurations retain their current behavior. FP32 and FP16 tests cover normalization for L2 and inner-product metrics.

It also follows up on review feedback from #999 with an HNSW integration test that installs distinct stored-to-stored and stored-to-query kernels. Top-K, range, and batch-iterator searches must all return the query-kernel score, proving HNSW selects the cached StoredToQuery dispatch.

Which issues this PR fixes

  1. MOD-14952

Main objects this PR modified

  1. QuantPreprocessor
  2. vecsim_types::sq8
  3. Quantization component unit tests
  4. HNSW stored-to-query dispatch integration coverage

Mark if applicable

  • This PR introduces API changes
  • This PR introduces serialization changes

Validation

  • make format
  • make check-format
  • Release build of test_components and test_hnsw
  • test_components: 32/32 passed
  • test_hnsw excluding the two external serialization fixtures: 169/169 passed
  • GitHub Actions, sanitizer, CodeQL, and Codecov checks passed
  • git diff --check main...HEAD

Note

Medium Risk
Introduces a new preprocessor constructor and larger SQ8 metadata when normalization is on; default WithNorm=false limits blast radius, but wrong mean or layout mismatches would break distance reconstruction.

Overview
Adds an optional normalization-aware mode to QuantPreprocessor via a WithNorm template flag (default off, so existing indexes keep the same blob layout and behavior).

When WithNorm is enabled, storage quantization uses mean-centered values (x - mean[i]) for min/max, scaling, and sums, while query vectors stay in the original DataType. An extra FP32 metadata field records Σ(x·mean) on storage (x_mean_ip) and Σ(y·mean) on queries (y_mean_ip). A new constructor takes a precomputed FP32 mean vector; Cosine + WithNorm is rejected at compile time. vecsim_types::sq8 grows metadata sizing helpers and index accessors for the extra slot.

Unit coverage exercises L2 and inner product for float32 and float16 with norm. An HNSW test wires distinct stored-to-stored vs stored-to-query distance kernels and checks top-K, range, and batch search use the query path score.

Reviewed by Cursor Bugbot for commit d4e8f1c. Bugbot is set up for automated code reviews on this repo. Configure here.

@dor-forer
dor-forer force-pushed the dor-forer-MOD-14952-support-quant-normalization branch from 0bf91f7 to f438a59 Compare July 22, 2026 15:22
@dor-forer
dor-forer force-pushed the dor-forer-MOD-14952-support-quant-normalization branch from f438a59 to d37077d Compare July 23, 2026 11:59
@dor-forer
dor-forer marked this pull request as ready for review July 23, 2026 12:21
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.12%. Comparing base (6e64d11) to head (d4e8f1c).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1000      +/-   ##
==========================================
- Coverage   97.13%   97.12%   -0.02%     
==========================================
  Files         141      141              
  Lines        8268     8304      +36     
==========================================
+ Hits         8031     8065      +34     
- Misses        237      239       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dor-forer
dor-forer requested a review from ofiryanai July 23, 2026 14:50
Base automatically changed from dor-forer-MOD-14953-calc-distance-for-query to main July 23, 2026 15:18
@dor-forer
dor-forer force-pushed the dor-forer-MOD-14952-support-quant-normalization branch from d37077d to 7eaa73f Compare July 26, 2026 06:33
float x_mean_ip = 0.0f; // only used for WithNorm

// Get transformed values (convert to float, mean-subtracted for WithNorm)
vecsim_stl::vector<float> values(this->dim, this->allocator);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces a dim-sized heap allocation for every FP16 storage preprocessing call, including the existing WithNorm=false path. It also turns the previous two-pass flow into three memory passes: build the FP32 temporary, find min/max, then quantize.

The temporary is not required. Quantization already needs two passes because min/max must be known before calculating the scale. In the first pass, compute min/max directly from to_fp32(input[i]) - mean[i] and accumulate x·mean. In the second pass, recompute the same transformed value while quantizing and accumulating sum/ squares. A templated/inlined helper or lambda with if constexpr (WithNorm) would remain compile-time-specialized—no function pointer, vtable, or other runtime indirection.

This follows the allocation-free approach used by the previous FP16 implementation and by assign_query_metadata() below. Please preserve that behavior, particularly for WithNorm=false.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@dor-forer
dor-forer requested a review from ofiryanai July 26, 2026 10:53
@dor-forer
dor-forer added this pull request to the merge queue Jul 26, 2026
Merged via the queue into main with commit 8624f34 Jul 26, 2026
16 checks passed
@dor-forer
dor-forer deleted the dor-forer-MOD-14952-support-quant-normalization branch July 26, 2026 14:23
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.

2 participants