You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by be...@apache.org on 2026/01/16 12:36:29 UTC
(lucene) branch branch_10x updated: Fix dibit striping for quantized vector formats (#15578)
This is an automated email from the ASF dual-hosted git repository.
benwtrent pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/lucene.git
The following commit(s) were added to refs/heads/branch_10x by this push:
new 4019ff1c959 Fix dibit striping for quantized vector formats (#15578)
4019ff1c959 is described below
commit 4019ff1c959ff887609a65078d4627e0be23be2e
Author: Benjamin Trent <be...@gmail.com>
AuthorDate: Thu Jan 15 16:20:35 2026 -0500
Fix dibit striping for quantized vector formats (#15578)
* Fix dibit striping for quantized vector formats
* tidy
---
.../Lucene104ScalarQuantizedVectorsFormat.java | 23 +++++++++++++++++++++-
.../quantization/TestOptimizedScalarQuantizer.java | 14 +++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104ScalarQuantizedVectorsFormat.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104ScalarQuantizedVectorsFormat.java
index 334ce565eb8..50cede6736b 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104ScalarQuantizedVectorsFormat.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene104/Lucene104ScalarQuantizedVectorsFormat.java
@@ -145,7 +145,28 @@ public class Lucene104ScalarQuantizedVectorsFormat extends FlatVectorsFormat {
* between the compression of {@link #SINGLE_BIT_QUERY_NIBBLE} and the accuracy of {@link
* #PACKED_NIBBLE}.
*/
- DIBIT_QUERY_NIBBLE(4, (byte) 2, 2, (byte) 4, 4);
+ DIBIT_QUERY_NIBBLE(4, (byte) 2, 2, (byte) 4, 4) {
+ @Override
+ public int getDiscreteDimensions(int dimensions) {
+ int queryDiscretized = (dimensions * 4 + 7) / 8 * 8 / 4;
+ // we want to force dibit packing to byte boundaries assuming single bit striping
+ // so we discretize to the same as single bit encoding
+ int docDiscretized = (dimensions + 7) / 8 * 8;
+ int maxDiscretized = Math.max(queryDiscretized, docDiscretized);
+ assert maxDiscretized % (8.0 / 4) == 0
+ : "bad discretized=" + maxDiscretized + " for dim=" + dimensions;
+ assert maxDiscretized % (8.0 / 2) == 0
+ : "bad discretized=" + maxDiscretized + " for dim=" + dimensions;
+ return maxDiscretized;
+ }
+
+ @Override
+ public int getDocPackedLength(int dimensions) {
+ int discretized = getDiscreteDimensions(dimensions);
+ // DIBIT should be stored as two single bits striped
+ return 2 * ((discretized + 7) / 8);
+ }
+ };
public static ScalarEncoding fromNumBits(int bits) {
for (ScalarEncoding encoding : values()) {
diff --git a/lucene/core/src/test/org/apache/lucene/util/quantization/TestOptimizedScalarQuantizer.java b/lucene/core/src/test/org/apache/lucene/util/quantization/TestOptimizedScalarQuantizer.java
index 62bd242531d..cb0a0add706 100644
--- a/lucene/core/src/test/org/apache/lucene/util/quantization/TestOptimizedScalarQuantizer.java
+++ b/lucene/core/src/test/org/apache/lucene/util/quantization/TestOptimizedScalarQuantizer.java
@@ -194,6 +194,20 @@ public class TestOptimizedScalarQuantizer extends LuceneTestCase {
assertArrayEquals(scratch, unpacked);
}
+ public void testPackTransposeDibit() {
+ int dim = randomIntBetween(1, 4096);
+ ScalarEncoding encoding = ScalarEncoding.DIBIT_QUERY_NIBBLE;
+ byte[] scratch = new byte[encoding.getDiscreteDimensions(dim)];
+ for (int i = 0; i < scratch.length; i++) {
+ scratch[i] = (byte) randomIntBetween(0, 3);
+ }
+ byte[] packed = new byte[encoding.getDocPackedLength(scratch.length)];
+ byte[] unpacked = new byte[scratch.length];
+ OptimizedScalarQuantizer.transposeDibit(scratch, packed);
+ OptimizedScalarQuantizer.untransposeDibit(packed, unpacked);
+ assertArrayEquals(scratch, unpacked);
+ }
+
static void assertValidQuantizedRange(byte[] quantized, byte bits) {
for (byte b : quantized) {
if (bits < 8) {