faiss 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +3 -1
- data/vendor/faiss/faiss/Clustering.cpp +9 -1
- data/vendor/faiss/faiss/IVFlib.cpp +14 -3
- data/vendor/faiss/faiss/Index.h +2 -2
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +9 -10
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +2 -3
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +1 -2
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +4 -5
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +2 -4
- data/vendor/faiss/faiss/IndexEDEN.cpp +273 -0
- data/vendor/faiss/faiss/IndexEDEN.h +57 -0
- data/vendor/faiss/faiss/IndexFastScan.cpp +15 -4
- data/vendor/faiss/faiss/IndexFlat.cpp +13 -50
- data/vendor/faiss/faiss/IndexHNSW.cpp +10 -11
- data/vendor/faiss/faiss/IndexIDMap.cpp +16 -3
- data/vendor/faiss/faiss/IndexIDMap.h +2 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +17 -6
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +3 -4
- data/vendor/faiss/faiss/IndexIVFEDEN.cpp +302 -0
- data/vendor/faiss/faiss/IndexIVFEDEN.h +70 -0
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +5 -6
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +3 -4
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +40 -22
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +19 -49
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +180 -76
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -4
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +8 -6
- data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
- data/vendor/faiss/faiss/IndexLattice.cpp +5 -0
- data/vendor/faiss/faiss/IndexNNDescent.cpp +9 -2
- data/vendor/faiss/faiss/IndexNSG.cpp +7 -2
- data/vendor/faiss/faiss/IndexPQ.cpp +6 -8
- data/vendor/faiss/faiss/IndexPreTransform.cpp +15 -0
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +2 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +1 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +5 -1
- data/vendor/faiss/faiss/IndexRefine.cpp +30 -1
- data/vendor/faiss/faiss/IndexReplicas.cpp +1 -2
- data/vendor/faiss/faiss/IndexShards.cpp +2 -2
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +2 -2
- data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
- data/vendor/faiss/faiss/SuperKMeans.cpp +256 -240
- data/vendor/faiss/faiss/SuperKMeans.h +30 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +33 -2
- data/vendor/faiss/faiss/clone_index.cpp +5 -0
- data/vendor/faiss/faiss/factory_tools.cpp +47 -4
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
- data/vendor/faiss/faiss/gpu/GpuIndex.h +34 -11
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +47 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +17 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +16 -0
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
- data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -2
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +180 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +1 -5
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -0
- data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h +134 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +2 -2
- data/vendor/faiss/faiss/impl/DistanceComputer.h +34 -0
- data/vendor/faiss/faiss/impl/EDENQuantizer.h +119 -0
- data/vendor/faiss/faiss/impl/HNSW.cpp +109 -152
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/impl/NSG.cpp +3 -1
- data/vendor/faiss/faiss/impl/Panorama.h +9 -7
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +34 -22
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +44 -36
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +168 -67
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +19 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +2 -11
- data/vendor/faiss/faiss/impl/ResultHandler.h +25 -31
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +258 -57
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +20 -0
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
- data/vendor/faiss/faiss/impl/VisitedTable.cpp +22 -2
- data/vendor/faiss/faiss/impl/VisitedTable.h +20 -0
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +1 -1
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +35 -2
- data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
- data/vendor/faiss/faiss/impl/index_read.cpp +376 -36
- data/vendor/faiss/faiss/impl/index_write.cpp +55 -4
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
- data/vendor/faiss/faiss/impl/platform_macros.h +3 -1
- data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +284 -0
- data/vendor/faiss/faiss/impl/polysemous_training/dispatch.h +115 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +0 -1
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +26 -15
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp +195 -0
- data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +133 -0
- data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +281 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +72 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +228 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +882 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +9 -8
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +85 -23
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +30 -30
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +4 -5
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +101 -34
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +136 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +16 -16
- data/vendor/faiss/faiss/impl/simd_dispatch.h +30 -9
- data/vendor/faiss/faiss/index_factory.cpp +32 -6
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +2 -2
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +19 -4
- data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +60 -0
- data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +26 -1
- data/vendor/faiss/faiss/svs/IndexSVSFlat.h +13 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +31 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +15 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +1 -2
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
- data/vendor/faiss/faiss/utils/distances.cpp +14 -2
- data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -3
- data/vendor/faiss/faiss/utils/extra_distances.cpp +4 -14
- data/vendor/faiss/faiss/utils/extra_distances.h +1 -2
- data/vendor/faiss/faiss/utils/hamming.cpp +1 -1
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +29 -8
- data/vendor/faiss/faiss/utils/rabitq_simd.h +202 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +0 -1
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +263 -15
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +160 -18
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +273 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_spr.cpp +92 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +11 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +143 -6
- data/vendor/faiss/faiss/utils/simd_levels.cpp +44 -0
- data/vendor/faiss/faiss/utils/simd_levels.h +14 -0
- data/vendor/faiss/faiss/utils/utils.cpp +9 -27
- metadata +16 -1
|
@@ -19,8 +19,10 @@
|
|
|
19
19
|
#include <faiss/impl/ResultHandler.h>
|
|
20
20
|
#include <faiss/impl/fast_scan/FastScanDistancePostProcessing.h>
|
|
21
21
|
#include <faiss/impl/fast_scan/fast_scan.h>
|
|
22
|
+
#include <faiss/impl/simd_dispatch.h>
|
|
22
23
|
#include <faiss/invlists/BlockInvertedLists.h>
|
|
23
24
|
#include <faiss/utils/distances.h>
|
|
25
|
+
#include <faiss/utils/rabitq_simd.h>
|
|
24
26
|
#include <faiss/utils/utils.h>
|
|
25
27
|
|
|
26
28
|
namespace faiss {
|
|
@@ -28,6 +30,7 @@ namespace faiss {
|
|
|
28
30
|
// Import shared utilities from RaBitQUtils
|
|
29
31
|
using rabitq_utils::ExtraBitsFactors;
|
|
30
32
|
using rabitq_utils::QueryFactorsData;
|
|
33
|
+
using rabitq_utils::round_nonnegative_to_uint16;
|
|
31
34
|
using rabitq_utils::SignBitFactors;
|
|
32
35
|
using rabitq_utils::SignBitFactorsWithError;
|
|
33
36
|
|
|
@@ -62,8 +65,9 @@ IndexIVFRaBitQFastScan::IndexIVFRaBitQFastScan(
|
|
|
62
65
|
metric == METRIC_L2 || metric == METRIC_INNER_PRODUCT,
|
|
63
66
|
"RaBitQ only supports L2 and Inner Product metrics");
|
|
64
67
|
FAISS_THROW_IF_NOT_MSG(
|
|
65
|
-
bbs_in % 32 == 0,
|
|
66
|
-
|
|
68
|
+
bbs_in > 0 && bbs_in % 32 == 0,
|
|
69
|
+
"Batch size must be positive and a multiple of 32");
|
|
70
|
+
FAISS_THROW_IF_MSG(quantizer_in == nullptr, "Quantizer cannot be null");
|
|
67
71
|
|
|
68
72
|
by_residual = true;
|
|
69
73
|
qb = 8; // RaBitQ quantization bits
|
|
@@ -91,10 +95,12 @@ IndexIVFRaBitQFastScan::IndexIVFRaBitQFastScan(
|
|
|
91
95
|
}
|
|
92
96
|
}
|
|
93
97
|
|
|
94
|
-
// Constructor that converts an existing IndexIVFRaBitQ to FastScan format
|
|
98
|
+
// Constructor that converts an existing IndexIVFRaBitQ to FastScan format.
|
|
99
|
+
// Like other IVF FastScan conversion constructors, this borrows orig's
|
|
100
|
+
// quantizer and orig_invlists; orig must outlive the converted index.
|
|
95
101
|
IndexIVFRaBitQFastScan::IndexIVFRaBitQFastScan(
|
|
96
102
|
const IndexIVFRaBitQ& orig,
|
|
97
|
-
int
|
|
103
|
+
int bbs_in)
|
|
98
104
|
: IndexIVFFastScan(
|
|
99
105
|
orig.quantizer,
|
|
100
106
|
orig.d,
|
|
@@ -102,7 +108,93 @@ IndexIVFRaBitQFastScan::IndexIVFRaBitQFastScan(
|
|
|
102
108
|
0,
|
|
103
109
|
orig.metric_type,
|
|
104
110
|
false),
|
|
105
|
-
rabitq(orig.rabitq) {
|
|
111
|
+
rabitq(orig.rabitq) {
|
|
112
|
+
FAISS_THROW_IF_NOT_MSG(orig.d > 0, "Dimension must be positive");
|
|
113
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
114
|
+
orig.metric_type == METRIC_L2 ||
|
|
115
|
+
orig.metric_type == METRIC_INNER_PRODUCT,
|
|
116
|
+
"RaBitQ only supports L2 and Inner Product metrics");
|
|
117
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
118
|
+
bbs_in > 0 && bbs_in % 32 == 0,
|
|
119
|
+
"Batch size must be positive and a multiple of 32");
|
|
120
|
+
FAISS_THROW_IF_NOT_MSG(orig.invlists != nullptr, "Source invlists null");
|
|
121
|
+
|
|
122
|
+
by_residual = true;
|
|
123
|
+
qb = orig.qb;
|
|
124
|
+
centered = false;
|
|
125
|
+
|
|
126
|
+
const size_t M_fastscan = (orig.d + 3) / 4;
|
|
127
|
+
constexpr size_t nbits_fastscan = 4;
|
|
128
|
+
|
|
129
|
+
this->bbs = bbs_in;
|
|
130
|
+
this->fine_quantizer = &rabitq;
|
|
131
|
+
this->M = M_fastscan;
|
|
132
|
+
this->nbits = nbits_fastscan;
|
|
133
|
+
this->ksub = (1 << nbits_fastscan);
|
|
134
|
+
this->M2 = roundup(M_fastscan, 2);
|
|
135
|
+
|
|
136
|
+
const size_t bit_pattern_size = (d + 7) / 8;
|
|
137
|
+
const size_t storage_size = compute_per_vector_storage_size();
|
|
138
|
+
this->code_size = bit_pattern_size + storage_size;
|
|
139
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
140
|
+
orig.code_size == code_size,
|
|
141
|
+
"Source IndexIVFRaBitQ code size is incompatible");
|
|
142
|
+
|
|
143
|
+
ntotal = orig.ntotal;
|
|
144
|
+
is_trained = orig.is_trained;
|
|
145
|
+
nprobe = orig.nprobe;
|
|
146
|
+
|
|
147
|
+
replace_invlists(new BlockInvertedLists(nlist, get_CodePacker()), true);
|
|
148
|
+
|
|
149
|
+
#pragma omp parallel for if (nlist > 100)
|
|
150
|
+
for (idx_t list_no = 0; list_no < static_cast<idx_t>(nlist); list_no++) {
|
|
151
|
+
const size_t nb = orig.invlists->list_size(list_no);
|
|
152
|
+
if (nb == 0) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
AlignedTable<uint8_t> flat_codes(nb * code_size);
|
|
157
|
+
memset(flat_codes.get(), 0, nb * code_size);
|
|
158
|
+
|
|
159
|
+
InvertedLists::ScopedCodes orig_codes(orig.invlists, list_no);
|
|
160
|
+
for (size_t i = 0; i < nb; i++) {
|
|
161
|
+
const uint8_t* orig_code = orig_codes.get() + i * orig.code_size;
|
|
162
|
+
uint8_t* fs_code = flat_codes.get() + i * code_size;
|
|
163
|
+
|
|
164
|
+
for (size_t j = 0; j < static_cast<size_t>(d); j++) {
|
|
165
|
+
const size_t orig_byte_idx = j / 8;
|
|
166
|
+
const size_t orig_bit_offset = j % 8;
|
|
167
|
+
const bool bit_value =
|
|
168
|
+
(orig_code[orig_byte_idx] >> orig_bit_offset) & 1;
|
|
169
|
+
if (bit_value) {
|
|
170
|
+
rabitq_utils::set_bit_fastscan(fs_code, j);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
memcpy(fs_code + bit_pattern_size,
|
|
175
|
+
orig_code + bit_pattern_size,
|
|
176
|
+
storage_size);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
std::unique_ptr<CodePacker> packer(get_CodePacker());
|
|
180
|
+
const size_t nb2 = roundup(nb, bbs);
|
|
181
|
+
AlignedTable<uint8_t> block_codes(nb2 / bbs * packer->block_size);
|
|
182
|
+
memset(block_codes.get(), 0, block_codes.size());
|
|
183
|
+
|
|
184
|
+
for (size_t i = 0; i < nb; i++) {
|
|
185
|
+
packer->pack_1(
|
|
186
|
+
flat_codes.get() + i * code_size, i, block_codes.get());
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
invlists->add_entries(
|
|
190
|
+
list_no,
|
|
191
|
+
nb,
|
|
192
|
+
InvertedLists::ScopedIds(orig.invlists, list_no).get(),
|
|
193
|
+
block_codes.get());
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
orig_invlists = orig.invlists;
|
|
197
|
+
}
|
|
106
198
|
|
|
107
199
|
size_t IndexIVFRaBitQFastScan::compute_per_vector_storage_size() const {
|
|
108
200
|
return rabitq_utils::compute_per_vector_storage_size(rabitq.nb_bits, d);
|
|
@@ -161,8 +253,10 @@ void IndexIVFRaBitQFastScan::train_encoder(
|
|
|
161
253
|
const float* x,
|
|
162
254
|
const idx_t* assign) {
|
|
163
255
|
FAISS_THROW_IF_NOT(n > 0);
|
|
164
|
-
FAISS_THROW_IF_NOT(x
|
|
165
|
-
|
|
256
|
+
FAISS_THROW_IF_NOT(x);
|
|
257
|
+
FAISS_THROW_IF_MSG(
|
|
258
|
+
assign == nullptr && by_residual,
|
|
259
|
+
"assign is required when by_residual is set");
|
|
166
260
|
|
|
167
261
|
rabitq.train(n, x);
|
|
168
262
|
is_trained = true;
|
|
@@ -176,9 +270,9 @@ void IndexIVFRaBitQFastScan::encode_vectors(
|
|
|
176
270
|
uint8_t* codes,
|
|
177
271
|
bool include_listnos) const {
|
|
178
272
|
FAISS_THROW_IF_NOT(n > 0);
|
|
179
|
-
FAISS_THROW_IF_NOT(x
|
|
180
|
-
FAISS_THROW_IF_NOT(list_nos
|
|
181
|
-
FAISS_THROW_IF_NOT(codes
|
|
273
|
+
FAISS_THROW_IF_NOT(x);
|
|
274
|
+
FAISS_THROW_IF_NOT(list_nos);
|
|
275
|
+
FAISS_THROW_IF_NOT(codes);
|
|
182
276
|
FAISS_THROW_IF_NOT(is_trained);
|
|
183
277
|
|
|
184
278
|
size_t coarse_size = include_listnos ? coarse_code_size() : 0;
|
|
@@ -416,9 +510,9 @@ void IndexIVFRaBitQFastScan::search_preassigned(
|
|
|
416
510
|
IndexIVFStats* stats) const {
|
|
417
511
|
FAISS_THROW_IF_NOT(is_trained);
|
|
418
512
|
FAISS_THROW_IF_NOT(k > 0);
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
513
|
+
FAISS_THROW_IF_MSG(
|
|
514
|
+
store_pairs, "store_pairs not supported for RaBitQFastScan");
|
|
515
|
+
FAISS_THROW_IF_MSG(stats, "stats not supported for this index");
|
|
422
516
|
|
|
423
517
|
size_t cur_nprobe = this->nprobe;
|
|
424
518
|
uint8_t used_qb = qb;
|
|
@@ -453,6 +547,7 @@ void IndexIVFRaBitQFastScan::compute_LUT(
|
|
|
453
547
|
const FastScanDistancePostProcessing& context) const {
|
|
454
548
|
FAISS_THROW_IF_NOT(is_trained);
|
|
455
549
|
FAISS_THROW_IF_NOT(by_residual);
|
|
550
|
+
FAISS_ASSERT(ksub == 16);
|
|
456
551
|
|
|
457
552
|
// Use overridden qb/centered from context if provided, else index defaults
|
|
458
553
|
const uint8_t used_qb = context.qb > 0 ? context.qb : qb;
|
|
@@ -515,6 +610,7 @@ void IndexIVFRaBitQFastScan::compute_LUT_uint8(
|
|
|
515
610
|
const FastScanDistancePostProcessing& context) const {
|
|
516
611
|
FAISS_THROW_IF_NOT(is_trained);
|
|
517
612
|
FAISS_THROW_IF_NOT(by_residual);
|
|
613
|
+
FAISS_ASSERT(ksub == 16);
|
|
518
614
|
|
|
519
615
|
const uint8_t used_qb = context.qb > 0 ? context.qb : qb;
|
|
520
616
|
const bool used_centered = context.qb > 0 ? context.centered : centered;
|
|
@@ -572,45 +668,53 @@ void IndexIVFRaBitQFastScan::compute_LUT_uint8(
|
|
|
572
668
|
float glob_max_span = -HUGE_VAL;
|
|
573
669
|
float glob_max_dis = -HUGE_VAL;
|
|
574
670
|
float glob_b = HUGE_VAL;
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
671
|
+
float a;
|
|
672
|
+
with_selected_simd_levels<rabitq::RABITQ_QUANTIZATION_SIMD_LEVELS>(
|
|
673
|
+
[&]<SIMDLevel SL>() {
|
|
674
|
+
for (size_t j2 = 0; j2 < cur_nprobe; j2++) {
|
|
675
|
+
float b_j = 0;
|
|
676
|
+
float span_j = 0;
|
|
677
|
+
for (size_t m = 0; m < M; m++) {
|
|
678
|
+
const float* tab =
|
|
679
|
+
lut_float.get() + j2 * dim12 + m * ksub;
|
|
680
|
+
float mn, mx;
|
|
681
|
+
rabitq::lut_minmax_16<SL>(tab, mn, mx);
|
|
682
|
+
all_mins[j2 * M + m] = mn;
|
|
683
|
+
float span = mx - mn;
|
|
684
|
+
glob_max_span = std::max(glob_max_span, span);
|
|
685
|
+
b_j += mn;
|
|
686
|
+
span_j += span;
|
|
687
|
+
}
|
|
688
|
+
probe_b[j2] = b_j;
|
|
689
|
+
glob_max_dis = std::max(glob_max_dis, span_j);
|
|
690
|
+
glob_b = std::min(glob_b, b_j);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
a = std::min(
|
|
694
|
+
255.0f / glob_max_span,
|
|
695
|
+
65535.0f / glob_max_dis);
|
|
696
|
+
|
|
697
|
+
// Second pass: quantize LUT and compute biasq.
|
|
698
|
+
uint8_t* out_base =
|
|
699
|
+
dis_tables.get() + i * cur_nprobe * dim12_2;
|
|
700
|
+
uint16_t* bq = biases.get() + i * cur_nprobe;
|
|
701
|
+
for (size_t j2 = 0; j2 < cur_nprobe; j2++) {
|
|
702
|
+
for (size_t m = 0; m < M; m++) {
|
|
703
|
+
const float* tab =
|
|
704
|
+
lut_float.get() + j2 * dim12 + m * ksub;
|
|
705
|
+
const float mn = all_mins[j2 * M + m];
|
|
706
|
+
uint8_t* out =
|
|
707
|
+
out_base + j2 * dim12_2 + m * ksub;
|
|
708
|
+
rabitq::lut_quantize_16_to_uint8<SL>(
|
|
709
|
+
tab, mn, a, out);
|
|
710
|
+
}
|
|
711
|
+
memset(out_base + j2 * dim12_2 + M * ksub,
|
|
712
|
+
0,
|
|
713
|
+
(M2 - M) * ksub);
|
|
714
|
+
bq[j2] = round_nonnegative_to_uint16(
|
|
715
|
+
a * (probe_b[j2] - glob_b));
|
|
716
|
+
}
|
|
717
|
+
});
|
|
614
718
|
normalizers[2 * i] = a;
|
|
615
719
|
normalizers[2 * i + 1] = glob_b;
|
|
616
720
|
}
|
|
@@ -676,8 +780,8 @@ void IndexIVFRaBitQFastScan::sa_decode(idx_t n, const uint8_t* bytes, float* x)
|
|
|
676
780
|
const {
|
|
677
781
|
FAISS_THROW_IF_NOT(is_trained);
|
|
678
782
|
FAISS_THROW_IF_NOT(n > 0);
|
|
679
|
-
FAISS_THROW_IF_NOT(bytes
|
|
680
|
-
FAISS_THROW_IF_NOT(x
|
|
783
|
+
FAISS_THROW_IF_NOT(bytes);
|
|
784
|
+
FAISS_THROW_IF_NOT(x);
|
|
681
785
|
|
|
682
786
|
size_t coarse_size = coarse_code_size();
|
|
683
787
|
size_t total_code_size = code_size + coarse_size;
|
|
@@ -826,35 +930,35 @@ struct IVFRaBitQFastScanScanner : InvertedListScanner {
|
|
|
826
930
|
const size_t M = index.M;
|
|
827
931
|
const size_t M2 = index.M2;
|
|
828
932
|
const size_t ksub = index.ksub;
|
|
933
|
+
FAISS_ASSERT(ksub == 16);
|
|
829
934
|
|
|
830
935
|
float max_span = -HUGE_VAL;
|
|
831
936
|
float max_dis = 0;
|
|
832
937
|
float b = 0;
|
|
833
938
|
float* mins = mins_buf.data();
|
|
834
939
|
|
|
835
|
-
|
|
836
|
-
const float* tab = lut_float.get() + m * ksub;
|
|
837
|
-
float mn = tab[0], mx = tab[0];
|
|
838
|
-
for (size_t s = 1; s < ksub; s++) {
|
|
839
|
-
mn = std::min(mn, tab[s]);
|
|
840
|
-
mx = std::max(mx, tab[s]);
|
|
841
|
-
}
|
|
842
|
-
mins[m] = mn;
|
|
843
|
-
float span = mx - mn;
|
|
844
|
-
max_span = std::max(max_span, span);
|
|
845
|
-
max_dis += span;
|
|
846
|
-
b += mn;
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
float a = std::min(255.0f / max_span, 65535.0f / max_dis);
|
|
940
|
+
float a;
|
|
850
941
|
uint8_t* out = dis_tables.get();
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
942
|
+
with_selected_simd_levels<rabitq::RABITQ_QUANTIZATION_SIMD_LEVELS>(
|
|
943
|
+
[&]<SIMDLevel SL>() {
|
|
944
|
+
for (size_t m = 0; m < M; m++) {
|
|
945
|
+
const float* tab = lut_float.get() + m * ksub;
|
|
946
|
+
float mn, mx;
|
|
947
|
+
rabitq::lut_minmax_16<SL>(tab, mn, mx);
|
|
948
|
+
mins[m] = mn;
|
|
949
|
+
float span = mx - mn;
|
|
950
|
+
max_span = std::max(max_span, span);
|
|
951
|
+
max_dis += span;
|
|
952
|
+
b += mn;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
a = std::min(255.0f / max_span, 65535.0f / max_dis);
|
|
956
|
+
for (size_t m = 0; m < M; m++) {
|
|
957
|
+
const float* tab = lut_float.get() + m * ksub;
|
|
958
|
+
rabitq::lut_quantize_16_to_uint8<SL>(
|
|
959
|
+
tab, mins[m], a, out + m * ksub);
|
|
960
|
+
}
|
|
961
|
+
});
|
|
858
962
|
memset(out + M * ksub, 0, (M2 - M) * ksub);
|
|
859
963
|
biases[0] = 0;
|
|
860
964
|
normalizers[0] = a;
|
|
@@ -267,11 +267,12 @@ void IVFRaBitQHeapHandler<C, SL>::handle(
|
|
|
267
267
|
}
|
|
268
268
|
const size_t max_positions = std::min<size_t>(32, this->ntotal - idx_base);
|
|
269
269
|
|
|
270
|
-
// Hoist aux pointer base out of loop:
|
|
271
|
-
// the
|
|
272
|
-
// varies.
|
|
270
|
+
// Hoist aux pointer base out of loop: it points at this 32-lane sub-block's
|
|
271
|
+
// factors, i.e. the bbs block base plus the loop-invariant intra-block
|
|
272
|
+
// offset ((idx_base % bbs)). Only the per-element j term varies below.
|
|
273
273
|
const uint8_t* aux_base = this->list_codes_ptr +
|
|
274
|
-
(idx_base / index->bbs) * full_block_size + packed_block_size
|
|
274
|
+
(idx_base / index->bbs) * full_block_size + packed_block_size +
|
|
275
|
+
(idx_base % index->bbs) * storage_size;
|
|
275
276
|
|
|
276
277
|
// Cache index fields used in the inner loop.
|
|
277
278
|
// Use overridden qb/centered from context if provided, else index defaults.
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
29
29
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
30
30
|
#include <faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h>
|
|
31
|
-
#include <faiss/utils/hamming_distance/hamming_computer-generic.h>
|
|
32
31
|
#undef THE_SIMD_LEVEL
|
|
33
32
|
|
|
34
33
|
namespace faiss {
|
|
@@ -88,7 +87,7 @@ void IndexIVFSpectralHash::train_encoder(
|
|
|
88
87
|
if (!vt->is_trained) {
|
|
89
88
|
vt->train(n, x);
|
|
90
89
|
}
|
|
91
|
-
|
|
90
|
+
FAISS_THROW_IF_MSG(by_residual, "by_residual not supported for this index");
|
|
92
91
|
|
|
93
92
|
if (threshold_type == Thresh_global) {
|
|
94
93
|
// nothing to do
|
|
@@ -185,7 +184,7 @@ void IndexIVFSpectralHash::encode_vectors(
|
|
|
185
184
|
uint8_t* codes,
|
|
186
185
|
bool include_listnos) const {
|
|
187
186
|
FAISS_THROW_IF_NOT(is_trained);
|
|
188
|
-
|
|
187
|
+
FAISS_THROW_IF_MSG(by_residual, "by_residual not supported for this index");
|
|
189
188
|
float freq = 2.0 / period;
|
|
190
189
|
size_t coarse_size = include_listnos ? coarse_code_size() : 0;
|
|
191
190
|
|
|
@@ -222,7 +221,7 @@ InvertedListScanner* IndexIVFSpectralHash::get_InvertedListScanner(
|
|
|
222
221
|
bool store_pairs,
|
|
223
222
|
const IDSelector* sel,
|
|
224
223
|
const IVFSearchParameters*) const {
|
|
225
|
-
|
|
224
|
+
FAISS_THROW_IF_MSG(sel, "id selector not supported for this index");
|
|
226
225
|
return with_simd_level([&]<SIMDLevel SL>() {
|
|
227
226
|
return make_spectral_hash_scanner_fixSL<SL>(
|
|
228
227
|
code_size, this, store_pairs);
|
|
@@ -254,8 +253,11 @@ void IndexIVFSpectralHash::replace_vt(IndexPreTransform* encoder, bool own) {
|
|
|
254
253
|
auto sub_index = dynamic_cast<IndexLSH*>(encoder->index);
|
|
255
254
|
FAISS_THROW_IF_NOT_MSG(sub_index, "final index should be LSH");
|
|
256
255
|
FAISS_THROW_IF_NOT(sub_index->nbits == nbit);
|
|
257
|
-
|
|
258
|
-
|
|
256
|
+
FAISS_THROW_IF_MSG(
|
|
257
|
+
sub_index->rotate_data, "LSH sub-index must not rotate data");
|
|
258
|
+
FAISS_THROW_IF_MSG(
|
|
259
|
+
sub_index->train_thresholds,
|
|
260
|
+
"LSH sub-index thresholds must already be trained");
|
|
259
261
|
replace_vt(encoder->chain[0], own);
|
|
260
262
|
}
|
|
261
263
|
|
|
@@ -119,8 +119,7 @@ void IndexLSH::search(
|
|
|
119
119
|
float* distances,
|
|
120
120
|
idx_t* labels,
|
|
121
121
|
const SearchParameters* params) const {
|
|
122
|
-
|
|
123
|
-
!params, "search params not supported for this index");
|
|
122
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
124
123
|
FAISS_THROW_IF_NOT(k > 0);
|
|
125
124
|
FAISS_THROW_IF_NOT(is_trained);
|
|
126
125
|
const float* xt = apply_preprocess(n, x);
|
|
@@ -151,7 +150,7 @@ void IndexLSH::transfer_thresholds(LinearTransform* vt) {
|
|
|
151
150
|
vt->b.resize(nbits, 0);
|
|
152
151
|
vt->have_bias = true;
|
|
153
152
|
}
|
|
154
|
-
|
|
153
|
+
FAISS_THROW_IF_MSG(vt->b.empty(), "bias vector must not be empty");
|
|
155
154
|
for (int i = 0; i < nbits; i++) {
|
|
156
155
|
vt->b[i] -= thresholds[i];
|
|
157
156
|
}
|
|
@@ -26,6 +26,11 @@ IndexLattice::IndexLattice(idx_t d_in, int nsq_in, int scale_nbit_in, int r2)
|
|
|
26
26
|
lattice_nbit = 0;
|
|
27
27
|
while (!(((uint64_t)1 << lattice_nbit) >= zn_sphere_codec.nv)) {
|
|
28
28
|
lattice_nbit++;
|
|
29
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
30
|
+
lattice_nbit < 64,
|
|
31
|
+
"IndexLattice: nv=%zu too large, lattice code would exceed "
|
|
32
|
+
"63 bits (likely corrupt r2/dsq)",
|
|
33
|
+
(size_t)zn_sphere_codec.nv);
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
int total_nbit = (lattice_nbit + scale_nbit_in) * nsq_in;
|
|
@@ -101,8 +101,7 @@ void IndexNNDescent::search(
|
|
|
101
101
|
float* distances,
|
|
102
102
|
idx_t* labels,
|
|
103
103
|
const SearchParameters* params) const {
|
|
104
|
-
|
|
105
|
-
!params, "search params not supported for this index");
|
|
104
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
106
105
|
FAISS_THROW_IF_NOT_MSG(
|
|
107
106
|
storage,
|
|
108
107
|
"Please use IndexNNDescentFlat (or variants) "
|
|
@@ -183,11 +182,19 @@ void IndexNNDescent::add(idx_t n, const float* x) {
|
|
|
183
182
|
|
|
184
183
|
void IndexNNDescent::reset() {
|
|
185
184
|
nndescent.reset();
|
|
185
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
186
|
+
storage,
|
|
187
|
+
"Please use IndexNNDescentFlat (or variants) "
|
|
188
|
+
"instead of IndexNNDescent directly");
|
|
186
189
|
storage->reset();
|
|
187
190
|
ntotal = 0;
|
|
188
191
|
}
|
|
189
192
|
|
|
190
193
|
void IndexNNDescent::reconstruct(idx_t key, float* recons) const {
|
|
194
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
195
|
+
storage,
|
|
196
|
+
"Please use IndexNNDescentFlat (or variants) "
|
|
197
|
+
"instead of IndexNNDescent directly");
|
|
191
198
|
storage->reconstruct(key, recons);
|
|
192
199
|
}
|
|
193
200
|
|
|
@@ -62,8 +62,7 @@ void IndexNSG::search(
|
|
|
62
62
|
float* distances,
|
|
63
63
|
idx_t* labels,
|
|
64
64
|
const SearchParameters* params) const {
|
|
65
|
-
|
|
66
|
-
!params, "search params not supported for this index");
|
|
65
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
67
66
|
FAISS_THROW_IF_NOT_MSG(
|
|
68
67
|
storage,
|
|
69
68
|
"Please use IndexNSGFlat (or variants) instead of IndexNSG directly");
|
|
@@ -245,12 +244,18 @@ void IndexNSG::add(idx_t n, const float* x) {
|
|
|
245
244
|
|
|
246
245
|
void IndexNSG::reset() {
|
|
247
246
|
nsg.reset();
|
|
247
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
248
|
+
storage,
|
|
249
|
+
"Please use IndexNSGFlat (or variants) instead of IndexNSG directly");
|
|
248
250
|
storage->reset();
|
|
249
251
|
ntotal = 0;
|
|
250
252
|
is_built = false;
|
|
251
253
|
}
|
|
252
254
|
|
|
253
255
|
void IndexNSG::reconstruct(idx_t key, float* recons) const {
|
|
256
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
257
|
+
storage,
|
|
258
|
+
"Please use IndexNSGFlat (or variants) instead of IndexNSG directly");
|
|
254
259
|
storage->reconstruct(key, recons);
|
|
255
260
|
}
|
|
256
261
|
|
|
@@ -107,7 +107,7 @@ void IndexPQ::search(
|
|
|
107
107
|
if (iparams) {
|
|
108
108
|
params = dynamic_cast<const SearchParametersPQ*>(iparams);
|
|
109
109
|
FAISS_THROW_IF_NOT_MSG(params, "invalid search params");
|
|
110
|
-
|
|
110
|
+
FAISS_THROW_IF_MSG(params->sel, "selector not supported");
|
|
111
111
|
param_search_type = params->search_type;
|
|
112
112
|
}
|
|
113
113
|
|
|
@@ -459,7 +459,7 @@ struct SortedArray {
|
|
|
459
459
|
|
|
460
460
|
void init(const T* x_2) {
|
|
461
461
|
this->x = x_2;
|
|
462
|
-
|
|
462
|
+
FAISS_THROW_IF_MSG(perm.empty(), "permutation array must not be empty");
|
|
463
463
|
for (int n = 0; n < N; n++) {
|
|
464
464
|
perm[n] = n;
|
|
465
465
|
}
|
|
@@ -543,7 +543,7 @@ struct SemiSortedArray {
|
|
|
543
543
|
|
|
544
544
|
void init(const T* x_2) {
|
|
545
545
|
this->x = x_2;
|
|
546
|
-
|
|
546
|
+
FAISS_THROW_IF_MSG(perm.empty(), "permutation array must not be empty");
|
|
547
547
|
for (int n = 0; n < N; n++) {
|
|
548
548
|
perm[n] = n;
|
|
549
549
|
}
|
|
@@ -665,7 +665,7 @@ struct MinSumK {
|
|
|
665
665
|
|
|
666
666
|
void mark_seen(int64_t i) {
|
|
667
667
|
if (use_seen) {
|
|
668
|
-
|
|
668
|
+
FAISS_THROW_IF_MSG(seen.empty(), "seen bitmap must not be empty");
|
|
669
669
|
seen[i >> 3] |= 1 << (i & 7);
|
|
670
670
|
}
|
|
671
671
|
}
|
|
@@ -795,8 +795,7 @@ void MultiIndexQuantizer::search(
|
|
|
795
795
|
float* distances,
|
|
796
796
|
idx_t* labels,
|
|
797
797
|
const SearchParameters* params) const {
|
|
798
|
-
|
|
799
|
-
!params, "search params not supported for this index");
|
|
798
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
800
799
|
if (n == 0) {
|
|
801
800
|
return;
|
|
802
801
|
}
|
|
@@ -943,8 +942,7 @@ void MultiIndexQuantizer2::search(
|
|
|
943
942
|
float* distances,
|
|
944
943
|
idx_t* labels,
|
|
945
944
|
const SearchParameters* params) const {
|
|
946
|
-
|
|
947
|
-
!params, "search params not supported for this index");
|
|
945
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
948
946
|
|
|
949
947
|
if (n == 0) {
|
|
950
948
|
return;
|
|
@@ -229,6 +229,7 @@ size_t IndexPreTransform::remove_ids(const IDSelector& sel) {
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
void IndexPreTransform::reconstruct(idx_t key, float* recons) const {
|
|
232
|
+
FAISS_THROW_IF_NOT_MSG(index, "IndexPreTransform: null sub-index");
|
|
232
233
|
float* x = chain.empty() ? recons : new float[index->d];
|
|
233
234
|
std::unique_ptr<float[]> del(recons == x ? nullptr : x);
|
|
234
235
|
// Initial reconstruction
|
|
@@ -239,6 +240,7 @@ void IndexPreTransform::reconstruct(idx_t key, float* recons) const {
|
|
|
239
240
|
}
|
|
240
241
|
|
|
241
242
|
void IndexPreTransform::reconstruct_n(idx_t i0, idx_t ni, float* recons) const {
|
|
243
|
+
FAISS_THROW_IF_NOT_MSG(index, "IndexPreTransform: null sub-index");
|
|
242
244
|
float* x = chain.empty() ? recons : new float[ni * index->d];
|
|
243
245
|
std::unique_ptr<float[]> del(recons == x ? nullptr : x);
|
|
244
246
|
// Initial reconstruction
|
|
@@ -345,6 +347,19 @@ struct PreTransformDistanceComputer : DistanceComputer {
|
|
|
345
347
|
float operator()(idx_t i) override {
|
|
346
348
|
return (*sub_dc)(i);
|
|
347
349
|
}
|
|
350
|
+
|
|
351
|
+
void distances_batch_4(
|
|
352
|
+
const idx_t idx0,
|
|
353
|
+
const idx_t idx1,
|
|
354
|
+
const idx_t idx2,
|
|
355
|
+
const idx_t idx3,
|
|
356
|
+
float& dis0,
|
|
357
|
+
float& dis1,
|
|
358
|
+
float& dis2,
|
|
359
|
+
float& dis3) override {
|
|
360
|
+
sub_dc->distances_batch_4(
|
|
361
|
+
idx0, idx1, idx2, idx3, dis0, dis1, dis2, dis3);
|
|
362
|
+
}
|
|
348
363
|
};
|
|
349
364
|
|
|
350
365
|
} // anonymous namespace
|
|
@@ -122,8 +122,8 @@ struct Run_search_with_dc_res {
|
|
|
122
122
|
// RaBitQuantizer.cpp for details.
|
|
123
123
|
auto* dc = dynamic_cast<RaBitQDistanceComputer*>(
|
|
124
124
|
dc_base.get());
|
|
125
|
-
|
|
126
|
-
dc
|
|
125
|
+
FAISS_THROW_IF_MSG(
|
|
126
|
+
dc == nullptr,
|
|
127
127
|
"Failed to cast to RaBitQDistanceComputer for two-stage search");
|
|
128
128
|
|
|
129
129
|
bool is_similarity =
|
|
@@ -512,8 +512,7 @@ void IndexRaBitQFastScan::search(
|
|
|
512
512
|
float* distances,
|
|
513
513
|
idx_t* labels,
|
|
514
514
|
const SearchParameters* params) const {
|
|
515
|
-
|
|
516
|
-
!params, "search params not supported for this index");
|
|
515
|
+
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
517
516
|
|
|
518
517
|
// Create query factors array on stack - memory managed by caller
|
|
519
518
|
std::vector<rabitq_utils::QueryFactorsData> query_factors_storage(n);
|
|
@@ -209,8 +209,12 @@ struct RaBitQHeapHandler
|
|
|
209
209
|
: 0;
|
|
210
210
|
|
|
211
211
|
const size_t block_idx = base_db_idx / rabitq_index->bbs;
|
|
212
|
+
// aux_base points at this 32-lane sub-block's factors: the bbs block
|
|
213
|
+
// base plus the loop-invariant intra-block offset
|
|
214
|
+
// ((base_db_idx % bbs)). Only the per-element i term varies below.
|
|
212
215
|
const uint8_t* aux_base = rabitq_index->codes.get() +
|
|
213
|
-
block_idx * full_block_size + packed_block_size
|
|
216
|
+
block_idx * full_block_size + packed_block_size +
|
|
217
|
+
(base_db_idx % rabitq_index->bbs) * storage_size;
|
|
214
218
|
|
|
215
219
|
for (size_t i = 0; i < max_vectors; i++) {
|
|
216
220
|
const size_t db_idx = base_db_idx + i;
|