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
|
@@ -8,13 +8,15 @@
|
|
|
8
8
|
#include <faiss/impl/RaBitQuantizer.h>
|
|
9
9
|
|
|
10
10
|
#include <faiss/impl/FaissAssert.h>
|
|
11
|
+
#include <faiss/impl/IDSelector.h>
|
|
11
12
|
#include <faiss/impl/RaBitQUtils.h>
|
|
12
13
|
#include <faiss/impl/RaBitQuantizerMultiBit.h>
|
|
14
|
+
#include <faiss/impl/ResultHandler.h>
|
|
13
15
|
#include <faiss/impl/simd_dispatch.h>
|
|
16
|
+
#include <faiss/invlists/DirectMap.h>
|
|
14
17
|
#include <faiss/utils/distances.h>
|
|
15
18
|
#include <faiss/utils/rabitq_simd.h>
|
|
16
19
|
|
|
17
|
-
#include <algorithm>
|
|
18
20
|
#include <cmath>
|
|
19
21
|
#include <cstring>
|
|
20
22
|
#include <memory>
|
|
@@ -183,8 +185,10 @@ void RaBitQuantizer::decode_core(
|
|
|
183
185
|
float* x,
|
|
184
186
|
size_t n,
|
|
185
187
|
const float* centroid_in) const {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
+
FAISS_THROW_IF_MSG(
|
|
189
|
+
codes == nullptr, "RaBitQuantizer::decode_core: null codes buffer");
|
|
190
|
+
FAISS_THROW_IF_MSG(
|
|
191
|
+
x == nullptr, "RaBitQuantizer::decode_core: null output buffer");
|
|
188
192
|
|
|
189
193
|
const float inv_d_sqrt = (d == 0) ? 1.0f : (1.0f / std::sqrt((float)d));
|
|
190
194
|
const size_t ex_bits = nb_bits - 1;
|
|
@@ -228,7 +232,7 @@ namespace {
|
|
|
228
232
|
// directly to the SIMD-specialized code.
|
|
229
233
|
|
|
230
234
|
template <SIMDLevel SL>
|
|
231
|
-
struct RaBitQDistanceComputerNotQ : RaBitQDistanceComputer {
|
|
235
|
+
struct RaBitQDistanceComputerNotQ final : RaBitQDistanceComputer {
|
|
232
236
|
// the rotated query (qr - c)
|
|
233
237
|
std::vector<float> rotated_q;
|
|
234
238
|
// some additional numbers for the query
|
|
@@ -237,26 +241,9 @@ struct RaBitQDistanceComputerNotQ : RaBitQDistanceComputer {
|
|
|
237
241
|
RaBitQDistanceComputerNotQ() = default;
|
|
238
242
|
|
|
239
243
|
// Compute distance using only 1-bit codes (fast)
|
|
240
|
-
float
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
(metric_type == MetricType::METRIC_L2 ||
|
|
244
|
-
metric_type == MetricType::METRIC_INNER_PRODUCT));
|
|
245
|
-
FAISS_ASSERT(rotated_q.size() == d);
|
|
246
|
-
|
|
247
|
-
// split the code into parts
|
|
248
|
-
const uint8_t* binary_data = code;
|
|
249
|
-
|
|
250
|
-
// Cast to appropriate type based on nb_bits
|
|
251
|
-
// For 1-bit: use SignBitFactors (8 bytes)
|
|
252
|
-
// For multi-bit: use SignBitFactorsWithError (12 bytes) which includes
|
|
253
|
-
// f_error
|
|
254
|
-
size_t ex_bits = nb_bits - 1;
|
|
255
|
-
const SignBitFactors* base_fac = (ex_bits == 0)
|
|
256
|
-
? reinterpret_cast<const SignBitFactors*>(code + (d + 7) / 8)
|
|
257
|
-
: reinterpret_cast<const SignBitFactorsWithError*>(
|
|
258
|
-
code + (d + 7) / 8);
|
|
259
|
-
|
|
244
|
+
float distance_to_code_1bit_impl(
|
|
245
|
+
const uint8_t* binary_data,
|
|
246
|
+
const SignBitFactors* base_fac) const {
|
|
260
247
|
// this is the baseline code
|
|
261
248
|
//
|
|
262
249
|
// compute <q,o> using floats
|
|
@@ -286,7 +273,7 @@ struct RaBitQDistanceComputerNotQ : RaBitQDistanceComputer {
|
|
|
286
273
|
|
|
287
274
|
if (metric_type == MetricType::METRIC_L2) {
|
|
288
275
|
// ||or - q||^ 2
|
|
289
|
-
return pre_dist;
|
|
276
|
+
return std::max(0.0f, pre_dist);
|
|
290
277
|
} else {
|
|
291
278
|
// metric == MetricType::METRIC_INNER_PRODUCT
|
|
292
279
|
// 2 * (or, q) = (||or - q||^2 - ||q||^2 - ||or||^2)
|
|
@@ -294,8 +281,24 @@ struct RaBitQDistanceComputerNotQ : RaBitQDistanceComputer {
|
|
|
294
281
|
}
|
|
295
282
|
}
|
|
296
283
|
|
|
284
|
+
float distance_to_code_1bit(const uint8_t* code) final {
|
|
285
|
+
FAISS_ASSERT(code != nullptr);
|
|
286
|
+
FAISS_ASSERT(
|
|
287
|
+
(metric_type == MetricType::METRIC_L2 ||
|
|
288
|
+
metric_type == MetricType::METRIC_INNER_PRODUCT));
|
|
289
|
+
FAISS_ASSERT(rotated_q.size() == d);
|
|
290
|
+
|
|
291
|
+
const size_t code_size_base = (d + 7) / 8;
|
|
292
|
+
const size_t ex_bits = nb_bits - 1;
|
|
293
|
+
const SignBitFactors* base_fac = (ex_bits == 0)
|
|
294
|
+
? reinterpret_cast<const SignBitFactors*>(code + code_size_base)
|
|
295
|
+
: reinterpret_cast<const SignBitFactorsWithError*>(
|
|
296
|
+
code + code_size_base);
|
|
297
|
+
return distance_to_code_1bit_impl(code, base_fac);
|
|
298
|
+
}
|
|
299
|
+
|
|
297
300
|
// Compute full distance using 1-bit + ex-bits (accurate)
|
|
298
|
-
float distance_to_code_full(const uint8_t* code)
|
|
301
|
+
float distance_to_code_full(const uint8_t* code) final {
|
|
299
302
|
FAISS_ASSERT(code != nullptr);
|
|
300
303
|
FAISS_ASSERT(
|
|
301
304
|
(metric_type == MetricType::METRIC_L2 ||
|
|
@@ -331,7 +334,7 @@ struct RaBitQDistanceComputerNotQ : RaBitQDistanceComputer {
|
|
|
331
334
|
metric_type);
|
|
332
335
|
}
|
|
333
336
|
|
|
334
|
-
void set_query(const float* x)
|
|
337
|
+
void set_query(const float* x) final {
|
|
335
338
|
q = x;
|
|
336
339
|
FAISS_ASSERT(x != nullptr);
|
|
337
340
|
FAISS_ASSERT(
|
|
@@ -372,10 +375,62 @@ struct RaBitQDistanceComputerNotQ : RaBitQDistanceComputer {
|
|
|
372
375
|
centroid ? fvec_inner_product(x, centroid, d) : 0.0f;
|
|
373
376
|
}
|
|
374
377
|
}
|
|
378
|
+
|
|
379
|
+
size_t scan_codes_multibit(
|
|
380
|
+
size_t list_size,
|
|
381
|
+
const uint8_t* codes,
|
|
382
|
+
const idx_t* ids,
|
|
383
|
+
size_t code_size,
|
|
384
|
+
idx_t list_no,
|
|
385
|
+
bool store_pairs,
|
|
386
|
+
const IDSelector* sel,
|
|
387
|
+
bool keep_max,
|
|
388
|
+
ResultHandler& handler) final {
|
|
389
|
+
const size_t code_size_base = (d + 7) / 8;
|
|
390
|
+
const size_t ex_bits = nb_bits - 1;
|
|
391
|
+
FAISS_ASSERT(ex_bits > 0);
|
|
392
|
+
|
|
393
|
+
size_t nup = 0;
|
|
394
|
+
for (size_t j = 0; j < list_size; j++) {
|
|
395
|
+
if (sel != nullptr) {
|
|
396
|
+
idx_t id = store_pairs ? lo_build(list_no, j) : ids[j];
|
|
397
|
+
if (!sel->is_member(id)) {
|
|
398
|
+
codes += code_size;
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const auto* base_fac =
|
|
404
|
+
reinterpret_cast<const SignBitFactorsWithError*>(
|
|
405
|
+
codes + code_size_base);
|
|
406
|
+
const float est_distance =
|
|
407
|
+
distance_to_code_1bit_impl(codes, base_fac);
|
|
408
|
+
|
|
409
|
+
const bool should_refine = rabitq_utils::should_refine_candidate(
|
|
410
|
+
est_distance,
|
|
411
|
+
base_fac->f_error,
|
|
412
|
+
g_error,
|
|
413
|
+
handler.threshold,
|
|
414
|
+
keep_max);
|
|
415
|
+
if (should_refine) {
|
|
416
|
+
handler.stats.scan_cnt++;
|
|
417
|
+
const float dis = distance_to_code_full(codes);
|
|
418
|
+
idx_t id = store_pairs ? lo_build(list_no, j) : ids[j];
|
|
419
|
+
|
|
420
|
+
if (handler.add_result(dis, id)) {
|
|
421
|
+
handler.stats.nheap_updates++;
|
|
422
|
+
nup++;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
codes += code_size;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return nup;
|
|
429
|
+
}
|
|
375
430
|
};
|
|
376
431
|
|
|
377
432
|
template <SIMDLevel SL>
|
|
378
|
-
struct RaBitQDistanceComputerQ : RaBitQDistanceComputer {
|
|
433
|
+
struct RaBitQDistanceComputerQ final : RaBitQDistanceComputer {
|
|
379
434
|
// the rotated and quantized query (qr - c)
|
|
380
435
|
std::vector<float> rotated_q;
|
|
381
436
|
// the rotated and quantized query (qr - c) for fast 1-bit computation
|
|
@@ -395,25 +450,10 @@ struct RaBitQDistanceComputerQ : RaBitQDistanceComputer {
|
|
|
395
450
|
RaBitQDistanceComputerQ() = default;
|
|
396
451
|
|
|
397
452
|
// Compute distance using only 1-bit codes (fast)
|
|
398
|
-
float
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
metric_type == MetricType::METRIC_INNER_PRODUCT));
|
|
403
|
-
|
|
404
|
-
// split the code into parts
|
|
405
|
-
size_t size = (d + 7) / 8;
|
|
406
|
-
const uint8_t* binary_data = code;
|
|
407
|
-
|
|
408
|
-
// Cast to appropriate type based on nb_bits
|
|
409
|
-
// For 1-bit: use SignBitFactors (8 bytes)
|
|
410
|
-
// For multi-bit: use SignBitFactorsWithError (12 bytes) which
|
|
411
|
-
// includes f_error
|
|
412
|
-
size_t ex_bits = nb_bits - 1;
|
|
413
|
-
const SignBitFactors* base_fac = (ex_bits == 0)
|
|
414
|
-
? reinterpret_cast<const SignBitFactors*>(code + size)
|
|
415
|
-
: reinterpret_cast<const SignBitFactorsWithError*>(code + size);
|
|
416
|
-
|
|
453
|
+
float distance_to_code_1bit_impl(
|
|
454
|
+
const uint8_t* binary_data,
|
|
455
|
+
const SignBitFactors* base_fac,
|
|
456
|
+
size_t size) const {
|
|
417
457
|
// this is ||or - c||^2 - (IP ? ||or||^2 : 0)
|
|
418
458
|
float final_dot = 0;
|
|
419
459
|
if (centered) {
|
|
@@ -428,17 +468,16 @@ struct RaBitQDistanceComputerQ : RaBitQDistanceComputer {
|
|
|
428
468
|
qb);
|
|
429
469
|
final_dot += int_dot * query_fac.int_dot_scale;
|
|
430
470
|
} else {
|
|
431
|
-
auto
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
auto sum_q = rabitq::popcount<SL>(binary_data, size);
|
|
471
|
+
auto bitwise_result =
|
|
472
|
+
rabitq::bitwise_and_dot_product_with_popcount<SL>(
|
|
473
|
+
rearranged_rotated_qq.data(),
|
|
474
|
+
binary_data,
|
|
475
|
+
size,
|
|
476
|
+
qb);
|
|
438
477
|
// dot-product itself
|
|
439
|
-
final_dot += query_fac.c1 *
|
|
478
|
+
final_dot += query_fac.c1 * bitwise_result.dot_product;
|
|
440
479
|
// normalizer coefficients
|
|
441
|
-
final_dot += query_fac.c2 *
|
|
480
|
+
final_dot += query_fac.c2 * bitwise_result.popcount;
|
|
442
481
|
// normalizer coefficients
|
|
443
482
|
final_dot -= query_fac.c34;
|
|
444
483
|
}
|
|
@@ -449,7 +488,7 @@ struct RaBitQDistanceComputerQ : RaBitQDistanceComputer {
|
|
|
449
488
|
|
|
450
489
|
if (metric_type == MetricType::METRIC_L2) {
|
|
451
490
|
// ||or - q||^ 2
|
|
452
|
-
return pre_dist;
|
|
491
|
+
return std::max(0.0f, pre_dist);
|
|
453
492
|
} else {
|
|
454
493
|
// metric == MetricType::METRIC_INNER_PRODUCT
|
|
455
494
|
// 2 * (or, q) = (||or - q||^2 - ||q||^2 - ||or||^2)
|
|
@@ -457,8 +496,22 @@ struct RaBitQDistanceComputerQ : RaBitQDistanceComputer {
|
|
|
457
496
|
}
|
|
458
497
|
}
|
|
459
498
|
|
|
499
|
+
float distance_to_code_1bit(const uint8_t* code) final {
|
|
500
|
+
FAISS_ASSERT(code != nullptr);
|
|
501
|
+
FAISS_ASSERT(
|
|
502
|
+
(metric_type == MetricType::METRIC_L2 ||
|
|
503
|
+
metric_type == MetricType::METRIC_INNER_PRODUCT));
|
|
504
|
+
|
|
505
|
+
const size_t size = (d + 7) / 8;
|
|
506
|
+
const size_t ex_bits = nb_bits - 1;
|
|
507
|
+
const SignBitFactors* base_fac = (ex_bits == 0)
|
|
508
|
+
? reinterpret_cast<const SignBitFactors*>(code + size)
|
|
509
|
+
: reinterpret_cast<const SignBitFactorsWithError*>(code + size);
|
|
510
|
+
return distance_to_code_1bit_impl(code, base_fac, size);
|
|
511
|
+
}
|
|
512
|
+
|
|
460
513
|
// Compute full distance using 1-bit + ex-bits (accurate)
|
|
461
|
-
float distance_to_code_full(const uint8_t* code)
|
|
514
|
+
float distance_to_code_full(const uint8_t* code) final {
|
|
462
515
|
FAISS_ASSERT(code != nullptr);
|
|
463
516
|
FAISS_ASSERT(
|
|
464
517
|
(metric_type == MetricType::METRIC_L2 ||
|
|
@@ -494,7 +547,7 @@ struct RaBitQDistanceComputerQ : RaBitQDistanceComputer {
|
|
|
494
547
|
metric_type);
|
|
495
548
|
}
|
|
496
549
|
|
|
497
|
-
void set_query(const float* x)
|
|
550
|
+
void set_query(const float* x) final {
|
|
498
551
|
q = x;
|
|
499
552
|
FAISS_ASSERT(x != nullptr);
|
|
500
553
|
FAISS_ASSERT(
|
|
@@ -526,16 +579,64 @@ struct RaBitQDistanceComputerQ : RaBitQDistanceComputer {
|
|
|
526
579
|
size_t offset = (d + 7) / 8;
|
|
527
580
|
|
|
528
581
|
rearranged_rotated_qq.resize(offset * qb);
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
582
|
+
with_selected_simd_levels<
|
|
583
|
+
AVAILABLE_SIMD_LEVELS_NONE | (1 << int(SIMDLevel::AVX2)) |
|
|
584
|
+
(1 << int(SIMDLevel::AVX512))>([&]<SIMDLevel RSL>() {
|
|
585
|
+
rabitq::rearrange_bit_planes<RSL>(
|
|
586
|
+
rotated_qq.data(), d, qb, rearranged_rotated_qq.data());
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
size_t scan_codes_multibit(
|
|
591
|
+
size_t list_size,
|
|
592
|
+
const uint8_t* codes,
|
|
593
|
+
const idx_t* ids,
|
|
594
|
+
size_t code_size,
|
|
595
|
+
idx_t list_no,
|
|
596
|
+
bool store_pairs,
|
|
597
|
+
const IDSelector* sel,
|
|
598
|
+
bool keep_max,
|
|
599
|
+
ResultHandler& handler) final {
|
|
600
|
+
const size_t code_size_base = (d + 7) / 8;
|
|
601
|
+
const size_t ex_bits = nb_bits - 1;
|
|
602
|
+
FAISS_ASSERT(ex_bits > 0);
|
|
603
|
+
|
|
604
|
+
size_t nup = 0;
|
|
605
|
+
for (size_t j = 0; j < list_size; j++) {
|
|
606
|
+
if (sel != nullptr) {
|
|
607
|
+
idx_t id = store_pairs ? lo_build(list_no, j) : ids[j];
|
|
608
|
+
if (!sel->is_member(id)) {
|
|
609
|
+
codes += code_size;
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
537
612
|
}
|
|
613
|
+
|
|
614
|
+
const auto* base_fac =
|
|
615
|
+
reinterpret_cast<const SignBitFactorsWithError*>(
|
|
616
|
+
codes + code_size_base);
|
|
617
|
+
const float est_distance =
|
|
618
|
+
distance_to_code_1bit_impl(codes, base_fac, code_size_base);
|
|
619
|
+
|
|
620
|
+
const bool should_refine = rabitq_utils::should_refine_candidate(
|
|
621
|
+
est_distance,
|
|
622
|
+
base_fac->f_error,
|
|
623
|
+
g_error,
|
|
624
|
+
handler.threshold,
|
|
625
|
+
keep_max);
|
|
626
|
+
if (should_refine) {
|
|
627
|
+
handler.stats.scan_cnt++;
|
|
628
|
+
const float dis = distance_to_code_full(codes);
|
|
629
|
+
idx_t id = store_pairs ? lo_build(list_no, j) : ids[j];
|
|
630
|
+
|
|
631
|
+
if (handler.add_result(dis, id)) {
|
|
632
|
+
handler.stats.nheap_updates++;
|
|
633
|
+
nup++;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
codes += code_size;
|
|
538
637
|
}
|
|
638
|
+
|
|
639
|
+
return nup;
|
|
539
640
|
}
|
|
540
641
|
};
|
|
541
642
|
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
|
|
17
17
|
namespace faiss {
|
|
18
18
|
|
|
19
|
+
struct IDSelector;
|
|
20
|
+
template <typename T, typename TI>
|
|
21
|
+
struct ResultHandlerUnordered;
|
|
22
|
+
|
|
19
23
|
// the reference implementation of the https://arxiv.org/pdf/2405.12497
|
|
20
24
|
// Jianyang Gao, Cheng Long, "RaBitQ: Quantizing High-Dimensional Vectors
|
|
21
25
|
// with a Theoretical Error Bound for Approximate Nearest Neighbor Search".
|
|
@@ -129,6 +133,21 @@ struct RaBitQDistanceComputer : FlatCodesDistanceComputer {
|
|
|
129
133
|
// Compute full multi-bit distance (accurate)
|
|
130
134
|
virtual float distance_to_code_full(const uint8_t* code) = 0;
|
|
131
135
|
|
|
136
|
+
virtual void set_centroid(const float* centroid_in) {
|
|
137
|
+
centroid = centroid_in;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
virtual size_t scan_codes_multibit(
|
|
141
|
+
size_t list_size,
|
|
142
|
+
const uint8_t* codes,
|
|
143
|
+
const idx_t* ids,
|
|
144
|
+
size_t code_size,
|
|
145
|
+
idx_t list_no,
|
|
146
|
+
bool store_pairs,
|
|
147
|
+
const IDSelector* sel,
|
|
148
|
+
bool keep_max,
|
|
149
|
+
ResultHandlerUnordered<float, idx_t>& handler) = 0;
|
|
150
|
+
|
|
132
151
|
// Override from FlatCodesDistanceComputer
|
|
133
152
|
// Delegates to distance_to_code_full() for multi-bit distance computation
|
|
134
153
|
float distance_to_code(const uint8_t* code) final {
|
|
@@ -257,8 +257,8 @@ void quantize_ex_bits(
|
|
|
257
257
|
const size_t ex_bits = nb_bits - 1;
|
|
258
258
|
FAISS_THROW_IF_NOT_MSG(
|
|
259
259
|
ex_bits >= 1 && ex_bits <= 8, "ex_bits must be in range [1, 8]");
|
|
260
|
-
|
|
261
|
-
|
|
260
|
+
FAISS_THROW_IF_MSG(residual == nullptr, "residual cannot be null");
|
|
261
|
+
FAISS_THROW_IF_MSG(ex_code == nullptr, "ex_code cannot be null");
|
|
262
262
|
|
|
263
263
|
// Step 1: Compute L2 norm of residual
|
|
264
264
|
float norm_sqr = fvec_norm_L2sqr(residual, d);
|
|
@@ -312,15 +312,6 @@ void quantize_ex_bits(
|
|
|
312
312
|
// Step 7: Pack codes into byte array
|
|
313
313
|
pack_multibit_codes(tmp_code.data(), ex_code, d, nb_bits);
|
|
314
314
|
|
|
315
|
-
// Step 8: Compute factors for distance computation
|
|
316
|
-
// Reconstruct total_code for factor computation
|
|
317
|
-
std::vector<int> total_code(d);
|
|
318
|
-
for (size_t i = 0; i < d; i++) {
|
|
319
|
-
// Form total_code = (sign << ex_bits) + ex_code
|
|
320
|
-
bool sign_bit = (residual[i] >= 0);
|
|
321
|
-
total_code[i] = tmp_code[i] + ((sign_bit ? 1 : 0) << ex_bits);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
315
|
// Compute ex-factors; centroid is needed for IP metric correction
|
|
325
316
|
compute_ex_factors(
|
|
326
317
|
residual,
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
#include <faiss/impl/InvertedListScannerStats.h>
|
|
19
19
|
#include <faiss/utils/Heap.h>
|
|
20
20
|
#include <faiss/utils/partitioning.h>
|
|
21
|
+
#include <faiss/utils/simd_levels.h>
|
|
21
22
|
#include <algorithm>
|
|
22
23
|
#include <iostream>
|
|
23
24
|
|
|
@@ -234,23 +235,9 @@ struct Top1BlockResultHandler : TopkBlockResultHandler<C, use_sel> {
|
|
|
234
235
|
}
|
|
235
236
|
|
|
236
237
|
/// add results for query i0..i1 and j0..j1
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
auto& min_distance = this->dis_tab[i];
|
|
242
|
-
auto& min_index = this->ids_tab[i];
|
|
243
|
-
|
|
244
|
-
for (size_t j = j0; j < j1; j++) {
|
|
245
|
-
const T distance = dis_tab_i[j];
|
|
246
|
-
|
|
247
|
-
if (C::cmp(min_distance, distance)) {
|
|
248
|
-
min_distance = distance;
|
|
249
|
-
min_index = j;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
238
|
+
/// Implemented in result_handler.cpp; dispatches via
|
|
239
|
+
/// with_selected_simd_levels to top1_add_results_tpl<C, use_sel, SL>.
|
|
240
|
+
void add_results(size_t j0, size_t j1, const T* dis_tab_2) final;
|
|
254
241
|
|
|
255
242
|
void add_result(const size_t i, const T dis, const TI idx) {
|
|
256
243
|
auto& min_distance = this->dis_tab[i];
|
|
@@ -553,20 +540,9 @@ struct ReservoirBlockResultHandler : TopkBlockResultHandler<C, use_sel> {
|
|
|
553
540
|
}
|
|
554
541
|
|
|
555
542
|
/// add results for query i0..i1 and j0..j1
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
i++) {
|
|
560
|
-
ReservoirTopN<C>& reservoir =
|
|
561
|
-
reservoirs[i - static_cast<int64_t>(i0)];
|
|
562
|
-
const T* dis_tab_i =
|
|
563
|
-
dis_in + (j1 - j0) * (i - static_cast<int64_t>(i0)) - j0;
|
|
564
|
-
for (size_t j = j0; j < j1; j++) {
|
|
565
|
-
T dis = dis_tab_i[j];
|
|
566
|
-
reservoir.add_result(dis, j);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
543
|
+
/// Implemented in result_handler.cpp; dispatches via
|
|
544
|
+
/// with_selected_simd_levels to reservoir_add_results_tpl<C, use_sel, SL>.
|
|
545
|
+
void add_results(size_t j0, size_t j1, const T* dis_in);
|
|
570
546
|
|
|
571
547
|
/// series of results for queries i0..i1 is done
|
|
572
548
|
void end_multiple() final {
|
|
@@ -799,4 +775,22 @@ typename Consumer::T dispatch_range_ResultHandler(
|
|
|
799
775
|
#undef DISPATCH_C_SEL
|
|
800
776
|
}
|
|
801
777
|
|
|
778
|
+
// ------------------------------------------------------------------
|
|
779
|
+
// SIMD-dispatch entry points for Top1 and Reservoir add_results.
|
|
780
|
+
// ------------------------------------------------------------------
|
|
781
|
+
|
|
782
|
+
template <class C, bool use_sel, SIMDLevel SL>
|
|
783
|
+
void top1_add_results_tpl(
|
|
784
|
+
Top1BlockResultHandler<C, use_sel>* self,
|
|
785
|
+
size_t j0,
|
|
786
|
+
size_t j1,
|
|
787
|
+
const typename C::T* dis_tab);
|
|
788
|
+
|
|
789
|
+
template <class C, bool use_sel, SIMDLevel SL>
|
|
790
|
+
void reservoir_add_results_tpl(
|
|
791
|
+
ReservoirBlockResultHandler<C, use_sel>* self,
|
|
792
|
+
size_t j0,
|
|
793
|
+
size_t j1,
|
|
794
|
+
const typename C::T* dis_in);
|
|
795
|
+
|
|
802
796
|
} // namespace faiss
|