faiss 0.5.2 → 0.6.0
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 +16 -0
- data/LICENSE.txt +1 -1
- data/ext/faiss/ext.cpp +1 -1
- data/ext/faiss/extconf.rb +5 -6
- data/ext/faiss/index_binary.cpp +76 -17
- data/ext/faiss/{index.cpp → index_rb.cpp} +108 -35
- data/ext/faiss/kmeans.cpp +12 -9
- data/ext/faiss/numo.hpp +11 -9
- data/ext/faiss/pca_matrix.cpp +10 -8
- data/ext/faiss/product_quantizer.cpp +14 -12
- data/ext/faiss/{utils.cpp → utils_rb.cpp} +10 -3
- data/ext/faiss/{utils.h → utils_rb.h} +6 -0
- data/lib/faiss/version.rb +1 -1
- data/lib/faiss.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +130 -11
- data/vendor/faiss/faiss/AutoTune.h +14 -1
- data/vendor/faiss/faiss/Clustering.cpp +59 -10
- data/vendor/faiss/faiss/Clustering.h +12 -0
- data/vendor/faiss/faiss/IVFlib.cpp +31 -28
- data/vendor/faiss/faiss/Index.cpp +20 -8
- data/vendor/faiss/faiss/Index.h +25 -3
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +19 -24
- data/vendor/faiss/faiss/IndexBinary.cpp +1 -0
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +9 -4
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +45 -11
- data/vendor/faiss/faiss/IndexFastScan.cpp +35 -22
- data/vendor/faiss/faiss/IndexFastScan.h +10 -1
- data/vendor/faiss/faiss/IndexFlat.cpp +193 -136
- data/vendor/faiss/faiss/IndexFlat.h +16 -1
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +46 -22
- data/vendor/faiss/faiss/IndexFlatCodes.h +7 -1
- data/vendor/faiss/faiss/IndexHNSW.cpp +24 -50
- data/vendor/faiss/faiss/IndexHNSW.h +14 -12
- data/vendor/faiss/faiss/IndexIDMap.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVF.cpp +76 -49
- data/vendor/faiss/faiss/IndexIVF.h +14 -4
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +11 -8
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +2 -2
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +25 -14
- data/vendor/faiss/faiss/IndexIVFFastScan.h +26 -22
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +10 -61
- data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +39 -111
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +89 -147
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +37 -5
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +2 -1
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +42 -30
- data/vendor/faiss/faiss/IndexIVFRaBitQ.h +2 -2
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +246 -97
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +32 -29
- data/vendor/faiss/faiss/IndexLSH.cpp +8 -6
- data/vendor/faiss/faiss/IndexLattice.cpp +29 -24
- data/vendor/faiss/faiss/IndexNNDescent.cpp +1 -0
- data/vendor/faiss/faiss/IndexNSG.cpp +2 -1
- data/vendor/faiss/faiss/IndexNSG.h +0 -2
- data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +1 -1
- data/vendor/faiss/faiss/IndexPQ.cpp +19 -10
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +26 -13
- data/vendor/faiss/faiss/IndexRaBitQ.h +2 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +132 -78
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +14 -12
- data/vendor/faiss/faiss/IndexRefine.cpp +0 -30
- data/vendor/faiss/faiss/IndexShards.cpp +3 -4
- data/vendor/faiss/faiss/MetricType.h +16 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +120 -0
- data/vendor/faiss/faiss/VectorTransform.h +23 -0
- data/vendor/faiss/faiss/clone_index.cpp +7 -4
- data/vendor/faiss/faiss/{cppcontrib/factory_tools.cpp → factory_tools.cpp} +1 -1
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +1 -1
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +37 -11
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +0 -28
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +367 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.h +107 -0
- data/vendor/faiss/faiss/impl/CodePacker.cpp +4 -0
- data/vendor/faiss/faiss/impl/CodePacker.h +11 -3
- data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +83 -0
- data/vendor/faiss/faiss/impl/CodePackerRaBitQ.h +47 -0
- data/vendor/faiss/faiss/impl/FaissAssert.h +60 -2
- data/vendor/faiss/faiss/impl/HNSW.cpp +25 -34
- data/vendor/faiss/faiss/impl/HNSW.h +8 -6
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +34 -27
- data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -1
- data/vendor/faiss/faiss/impl/NSG.cpp +6 -5
- data/vendor/faiss/faiss/impl/NSG.h +17 -7
- data/vendor/faiss/faiss/impl/Panorama.cpp +53 -46
- data/vendor/faiss/faiss/impl/Panorama.h +22 -6
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +16 -5
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +70 -58
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +92 -0
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +93 -31
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +12 -28
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +3 -10
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +15 -41
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.h +0 -4
- data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +14 -9
- data/vendor/faiss/faiss/impl/ResultHandler.h +131 -50
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +67 -2358
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +0 -2
- data/vendor/faiss/faiss/impl/VisitedTable.cpp +42 -0
- data/vendor/faiss/faiss/impl/VisitedTable.h +69 -0
- data/vendor/faiss/faiss/impl/expanded_scanners.h +158 -0
- data/vendor/faiss/faiss/impl/index_read.cpp +829 -471
- data/vendor/faiss/faiss/impl/index_read_utils.h +0 -1
- data/vendor/faiss/faiss/impl/index_write.cpp +17 -8
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +47 -20
- data/vendor/faiss/faiss/impl/mapped_io.cpp +9 -2
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +7 -2
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +11 -3
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +19 -13
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +29 -21
- data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx2.h → pq_code_distance/pq_code_distance-avx2.cpp} +42 -215
- data/vendor/faiss/faiss/impl/{code_distance/code_distance-avx512.h → pq_code_distance/pq_code_distance-avx512.cpp} +68 -107
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +141 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +23 -0
- data/vendor/faiss/faiss/impl/{code_distance/code_distance-sve.h → pq_code_distance/pq_code_distance-sve.cpp} +57 -144
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +9 -6
- data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +121 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +136 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +280 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +164 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +94 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +455 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +430 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +329 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +467 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +203 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +42 -0
- data/vendor/faiss/faiss/impl/simd_dispatch.h +139 -0
- data/vendor/faiss/faiss/impl/simd_result_handlers.h +18 -18
- data/vendor/faiss/faiss/index_factory.cpp +35 -16
- data/vendor/faiss/faiss/index_io.h +29 -3
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +7 -4
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +9 -19
- data/vendor/faiss/faiss/svs/IndexSVSFlat.h +2 -0
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +2 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +9 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +9 -0
- data/vendor/faiss/faiss/utils/Heap.cpp +46 -0
- data/vendor/faiss/faiss/utils/Heap.h +21 -0
- data/vendor/faiss/faiss/utils/NeuralNet.cpp +10 -7
- data/vendor/faiss/faiss/utils/distances.cpp +141 -23
- data/vendor/faiss/faiss/utils/distances.h +98 -0
- data/vendor/faiss/faiss/utils/distances_dispatch.h +170 -0
- data/vendor/faiss/faiss/utils/distances_simd.cpp +74 -3511
- data/vendor/faiss/faiss/utils/extra_distances-inl.h +164 -157
- data/vendor/faiss/faiss/utils/extra_distances.cpp +52 -95
- data/vendor/faiss/faiss/utils/extra_distances.h +47 -1
- data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +0 -1
- data/vendor/faiss/faiss/utils/partitioning.cpp +1 -1
- data/vendor/faiss/faiss/utils/pq_code_distance.h +251 -0
- data/vendor/faiss/faiss/utils/rabitq_simd.h +260 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +150 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +568 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +153 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +1185 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +1092 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_sse-inl.h +391 -0
- data/vendor/faiss/faiss/utils/simd_levels.cpp +322 -0
- data/vendor/faiss/faiss/utils/simd_levels.h +91 -0
- data/vendor/faiss/faiss/utils/simdlib_avx2.h +12 -1
- data/vendor/faiss/faiss/utils/simdlib_avx512.h +69 -0
- data/vendor/faiss/faiss/utils/simdlib_neon.h +6 -0
- data/vendor/faiss/faiss/utils/sorting.cpp +4 -4
- data/vendor/faiss/faiss/utils/utils.cpp +16 -9
- metadata +47 -18
- data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +0 -81
- data/vendor/faiss/faiss/impl/code_distance/code_distance.h +0 -186
- /data/vendor/faiss/faiss/{cppcontrib/factory_tools.h → factory_tools.h} +0 -0
|
@@ -58,36 +58,6 @@ void IndexRefine::reset() {
|
|
|
58
58
|
ntotal = 0;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
namespace {
|
|
62
|
-
|
|
63
|
-
using idx_t = faiss::idx_t;
|
|
64
|
-
|
|
65
|
-
template <class C>
|
|
66
|
-
static void reorder_2_heaps(
|
|
67
|
-
idx_t n,
|
|
68
|
-
idx_t k,
|
|
69
|
-
idx_t* __restrict labels,
|
|
70
|
-
float* __restrict distances,
|
|
71
|
-
idx_t k_base,
|
|
72
|
-
const idx_t* __restrict base_labels,
|
|
73
|
-
const float* __restrict base_distances) {
|
|
74
|
-
#pragma omp parallel for if (n > 1)
|
|
75
|
-
for (idx_t i = 0; i < n; i++) {
|
|
76
|
-
idx_t* idxo = labels + i * k;
|
|
77
|
-
float* diso = distances + i * k;
|
|
78
|
-
const idx_t* idxi = base_labels + i * k_base;
|
|
79
|
-
const float* disi = base_distances + i * k_base;
|
|
80
|
-
|
|
81
|
-
heap_heapify<C>(k, diso, idxo, disi, idxi, k);
|
|
82
|
-
if (k_base != k) { // add remaining elements
|
|
83
|
-
heap_addn<C>(k, diso, idxo, disi + k, idxi + k, k_base - k);
|
|
84
|
-
}
|
|
85
|
-
heap_reorder<C>(k, diso, idxo);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
} // anonymous namespace
|
|
90
|
-
|
|
91
61
|
void IndexRefine::search(
|
|
92
62
|
idx_t n,
|
|
93
63
|
const float* x,
|
|
@@ -22,7 +22,7 @@ namespace {
|
|
|
22
22
|
|
|
23
23
|
// IndexBinary needs to update the code_size when d is set...
|
|
24
24
|
|
|
25
|
-
void sync_d(Index* index) {}
|
|
25
|
+
void sync_d(Index* /*index*/) {}
|
|
26
26
|
|
|
27
27
|
void sync_d(IndexBinary* index) {
|
|
28
28
|
FAISS_THROW_IF_NOT(index->d % 8 == 0);
|
|
@@ -71,13 +71,12 @@ IndexShardsTemplate<IndexT>::IndexShardsTemplate(
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
template <typename IndexT>
|
|
74
|
-
void IndexShardsTemplate<IndexT>::onAfterAddIndex(IndexT* index
|
|
74
|
+
void IndexShardsTemplate<IndexT>::onAfterAddIndex(IndexT* /*index*/) {
|
|
75
75
|
syncWithSubIndexes();
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
template <typename IndexT>
|
|
79
|
-
void IndexShardsTemplate<IndexT>::onAfterRemoveIndex(
|
|
80
|
-
IndexT* index /* unused */) {
|
|
79
|
+
void IndexShardsTemplate<IndexT>::onAfterRemoveIndex(IndexT* /*index*/) {
|
|
81
80
|
syncWithSubIndexes();
|
|
82
81
|
}
|
|
83
82
|
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
|
|
13
13
|
#include <cstdint>
|
|
14
14
|
#include <cstdio>
|
|
15
|
+
#include <cstdlib>
|
|
16
|
+
|
|
17
|
+
#include <faiss/impl/FaissAssert.h>
|
|
15
18
|
|
|
16
19
|
namespace faiss {
|
|
17
20
|
|
|
@@ -20,6 +23,8 @@ namespace faiss {
|
|
|
20
23
|
/// Most algorithms support both inner product and L2, with the flat
|
|
21
24
|
/// (brute-force) indices supporting additional metric types for vector
|
|
22
25
|
/// comparison.
|
|
26
|
+
///
|
|
27
|
+
/// NOTE: when adding or removing values, update metric_type_from_int() below.
|
|
23
28
|
enum MetricType {
|
|
24
29
|
METRIC_INNER_PRODUCT = 0, ///< maximum inner product search
|
|
25
30
|
METRIC_L2 = 1, ///< squared L2 search
|
|
@@ -52,6 +57,17 @@ constexpr bool is_similarity_metric(MetricType metric_type) {
|
|
|
52
57
|
(metric_type == METRIC_Jaccard));
|
|
53
58
|
}
|
|
54
59
|
|
|
60
|
+
/// Convert an integer to MetricType with range validation.
|
|
61
|
+
/// Throws FaissException if the value is not a valid MetricType.
|
|
62
|
+
inline MetricType metric_type_from_int(int x) {
|
|
63
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
64
|
+
(x >= METRIC_INNER_PRODUCT && x <= METRIC_Lp) ||
|
|
65
|
+
(x >= METRIC_Canberra && x <= METRIC_GOWER),
|
|
66
|
+
"invalid metric type %d",
|
|
67
|
+
x);
|
|
68
|
+
return static_cast<MetricType>(x);
|
|
69
|
+
}
|
|
70
|
+
|
|
55
71
|
} // namespace faiss
|
|
56
72
|
|
|
57
73
|
#endif
|
|
@@ -352,6 +352,126 @@ void RandomRotationMatrix::train(idx_t /*n*/, const float* /*x*/) {
|
|
|
352
352
|
init(12345);
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
+
/*********************************************
|
|
356
|
+
* HadamardRotation
|
|
357
|
+
*********************************************/
|
|
358
|
+
|
|
359
|
+
// In-place Fast Walsh-Hadamard Transform. n must be a power of 2.
|
|
360
|
+
// Applies the unnormalized Hadamard butterfly: O(n log n) add/sub, no
|
|
361
|
+
// multiplies.
|
|
362
|
+
static void fwht_inplace(float* buf, size_t n) {
|
|
363
|
+
for (size_t step = 1; step < n; step *= 2) {
|
|
364
|
+
for (size_t i = 0; i < n; i += step * 2) {
|
|
365
|
+
for (size_t j = i; j < i + step; j++) {
|
|
366
|
+
float a = buf[j];
|
|
367
|
+
float b = buf[j + step];
|
|
368
|
+
buf[j] = a + b;
|
|
369
|
+
buf[j + step] = a - b;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Smallest power of 2 >= n.
|
|
376
|
+
static int next_power_of_2(int n) {
|
|
377
|
+
int p = 1;
|
|
378
|
+
while (p < n) {
|
|
379
|
+
p *= 2;
|
|
380
|
+
}
|
|
381
|
+
return p;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Generate three sign-flip vectors from the given seed.
|
|
385
|
+
static void generate_signs(
|
|
386
|
+
uint32_t seed,
|
|
387
|
+
size_t p,
|
|
388
|
+
std::vector<float>& s1,
|
|
389
|
+
std::vector<float>& s2,
|
|
390
|
+
std::vector<float>& s3) {
|
|
391
|
+
FAISS_THROW_IF_NOT(p > 0);
|
|
392
|
+
SplitMix64RandomGenerator rng(seed);
|
|
393
|
+
s1.resize(p);
|
|
394
|
+
s2.resize(p);
|
|
395
|
+
s3.resize(p);
|
|
396
|
+
for (size_t j = 0; j < p; j++) {
|
|
397
|
+
s1[j] = (rng.rand_int(2) == 0) ? -1.0f : 1.0f;
|
|
398
|
+
}
|
|
399
|
+
for (size_t j = 0; j < p; j++) {
|
|
400
|
+
s2[j] = (rng.rand_int(2) == 0) ? -1.0f : 1.0f;
|
|
401
|
+
}
|
|
402
|
+
for (size_t j = 0; j < p; j++) {
|
|
403
|
+
s3[j] = (rng.rand_int(2) == 0) ? -1.0f : 1.0f;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
HadamardRotation::HadamardRotation(int d, uint32_t seed_in)
|
|
408
|
+
: VectorTransform(d, next_power_of_2(d)), seed(seed_in) {
|
|
409
|
+
init(seed_in);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
void HadamardRotation::init(uint32_t seed_in) {
|
|
413
|
+
seed = seed_in;
|
|
414
|
+
is_trained = true;
|
|
415
|
+
generate_signs(seed, d_out, signs1, signs2, signs3);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
void HadamardRotation::train(idx_t, const float*) {
|
|
419
|
+
init(seed != 0 ? seed : 12345);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
void HadamardRotation::apply_noalloc(idx_t n, const float* x, float* xt) const {
|
|
423
|
+
FAISS_THROW_IF_NOT_MSG(is_trained, "Transformation not trained yet");
|
|
424
|
+
|
|
425
|
+
size_t d = d_in;
|
|
426
|
+
size_t p = d_out;
|
|
427
|
+
FAISS_THROW_IF_NOT(signs1.size() == p);
|
|
428
|
+
FAISS_THROW_IF_NOT(signs2.size() == p);
|
|
429
|
+
FAISS_THROW_IF_NOT(signs3.size() == p);
|
|
430
|
+
|
|
431
|
+
// Each unnormalized FWHT scales norms by sqrt(p).
|
|
432
|
+
// Three rounds scale by p^(3/2). Normalize once at the end.
|
|
433
|
+
float total_scale = 1.0f / (p * std::sqrt(static_cast<float>(p)));
|
|
434
|
+
|
|
435
|
+
#pragma omp parallel for schedule(dynamic)
|
|
436
|
+
for (idx_t i = 0; i < n; i++) {
|
|
437
|
+
const float* xi = x + i * d;
|
|
438
|
+
float* xo = xt + i * p;
|
|
439
|
+
|
|
440
|
+
// Round 1: copy + zero-pad + sign-flip + FWHT
|
|
441
|
+
for (size_t j = 0; j < d; j++) {
|
|
442
|
+
xo[j] = xi[j] * signs1[j];
|
|
443
|
+
}
|
|
444
|
+
for (size_t j = d; j < p; j++) {
|
|
445
|
+
xo[j] = 0.0f;
|
|
446
|
+
}
|
|
447
|
+
fwht_inplace(xo, p);
|
|
448
|
+
|
|
449
|
+
// Round 2: sign-flip + FWHT
|
|
450
|
+
for (size_t j = 0; j < p; j++) {
|
|
451
|
+
xo[j] *= signs2[j];
|
|
452
|
+
}
|
|
453
|
+
fwht_inplace(xo, p);
|
|
454
|
+
|
|
455
|
+
// Round 3: sign-flip + FWHT + normalize
|
|
456
|
+
for (size_t j = 0; j < p; j++) {
|
|
457
|
+
xo[j] *= signs3[j];
|
|
458
|
+
}
|
|
459
|
+
fwht_inplace(xo, p);
|
|
460
|
+
|
|
461
|
+
for (size_t j = 0; j < p; j++) {
|
|
462
|
+
xo[j] *= total_scale;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
void HadamardRotation::check_identical(const VectorTransform& other) const {
|
|
468
|
+
auto* hr = dynamic_cast<const HadamardRotation*>(&other);
|
|
469
|
+
FAISS_THROW_IF_NOT(hr);
|
|
470
|
+
FAISS_THROW_IF_NOT(d_in == hr->d_in);
|
|
471
|
+
FAISS_THROW_IF_NOT(d_out == hr->d_out);
|
|
472
|
+
FAISS_THROW_IF_NOT(seed == hr->seed);
|
|
473
|
+
}
|
|
474
|
+
|
|
355
475
|
/*********************************************
|
|
356
476
|
* PCAMatrix
|
|
357
477
|
*********************************************/
|
|
@@ -126,6 +126,29 @@ struct RandomRotationMatrix : LinearTransform {
|
|
|
126
126
|
RandomRotationMatrix() {}
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
+
/** Three rounds of random sign-flip + Fast Walsh-Hadamard Transform.
|
|
130
|
+
* Produces a pseudo-random rotation in O(d log d) time.
|
|
131
|
+
* d_out is the smallest power of 2 >= d_in (zero-padded as needed).
|
|
132
|
+
*/
|
|
133
|
+
struct HadamardRotation : VectorTransform {
|
|
134
|
+
uint32_t seed{};
|
|
135
|
+
|
|
136
|
+
/// Sign-flip vectors, each of size d_out, generated from seed.
|
|
137
|
+
std::vector<float> signs1, signs2, signs3;
|
|
138
|
+
|
|
139
|
+
explicit HadamardRotation(int d, uint32_t seed = 12345);
|
|
140
|
+
|
|
141
|
+
void init(uint32_t seed_in);
|
|
142
|
+
|
|
143
|
+
void train(idx_t n, const float* x) override;
|
|
144
|
+
|
|
145
|
+
void apply_noalloc(idx_t n, const float* x, float* xt) const override;
|
|
146
|
+
|
|
147
|
+
void check_identical(const VectorTransform& other) const override;
|
|
148
|
+
|
|
149
|
+
HadamardRotation() {}
|
|
150
|
+
};
|
|
151
|
+
|
|
129
152
|
/** Applies a principal component analysis on a set of vectors,
|
|
130
153
|
* with optionally whitening and random rotation. */
|
|
131
154
|
struct PCAMatrix : LinearTransform {
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
#include <faiss/IndexIVFPQ.h>
|
|
28
28
|
#include <faiss/IndexIVFPQFastScan.h>
|
|
29
29
|
#include <faiss/IndexIVFPQR.h>
|
|
30
|
+
#include <faiss/IndexIVFRaBitQ.h>
|
|
31
|
+
#include <faiss/IndexIVFRaBitQFastScan.h>
|
|
30
32
|
#include <faiss/IndexIVFSpectralHash.h>
|
|
31
33
|
#include <faiss/IndexLSH.h>
|
|
32
34
|
#include <faiss/IndexLattice.h>
|
|
@@ -41,11 +43,11 @@
|
|
|
41
43
|
#include <faiss/MetaIndexes.h>
|
|
42
44
|
#include <faiss/VectorTransform.h>
|
|
43
45
|
|
|
46
|
+
#include <faiss/impl/CodePacker.h>
|
|
44
47
|
#include <faiss/impl/LocalSearchQuantizer.h>
|
|
45
48
|
#include <faiss/impl/ProductQuantizer.h>
|
|
46
49
|
#include <faiss/impl/ResidualQuantizer.h>
|
|
47
50
|
#include <faiss/impl/ScalarQuantizer.h>
|
|
48
|
-
#include <faiss/impl/pq4_fast_scan.h>
|
|
49
51
|
|
|
50
52
|
#include <faiss/invlists/BlockInvertedLists.h>
|
|
51
53
|
|
|
@@ -96,6 +98,9 @@ IndexIVF* Cloner::clone_IndexIVF(const IndexIVF* ivf) {
|
|
|
96
98
|
TRYCLONE(IndexIVFResidualQuantizerFastScan, ivf)
|
|
97
99
|
TRYCLONE(IndexIVFPQFastScan, ivf)
|
|
98
100
|
|
|
101
|
+
TRYCLONE(IndexIVFRaBitQFastScan, ivf)
|
|
102
|
+
TRYCLONE(IndexIVFRaBitQ, ivf)
|
|
103
|
+
|
|
99
104
|
TRYCLONE(IndexIVFFlatDedup, ivf)
|
|
100
105
|
TRYCLONE(IndexIVFFlat, ivf)
|
|
101
106
|
TRYCLONE(IndexIVFFlatPanorama, ivf)
|
|
@@ -257,9 +262,7 @@ InvertedLists* clone_InvertedLists(const InvertedLists* invlists) {
|
|
|
257
262
|
if (auto* bils = dynamic_cast<const BlockInvertedLists*>(invlists)) {
|
|
258
263
|
auto* bils2 = new BlockInvertedLists(*bils);
|
|
259
264
|
if (bils->packer) {
|
|
260
|
-
|
|
261
|
-
FAISS_THROW_IF_NOT(packerPQ4);
|
|
262
|
-
bils2->packer = new CodePackerPQ4(*packerPQ4);
|
|
265
|
+
bils2->packer = bils->packer->clone();
|
|
263
266
|
}
|
|
264
267
|
return bils2;
|
|
265
268
|
}
|
|
@@ -64,7 +64,7 @@ void ToCPUCloner::merge_index(Index* dst, Index* src, bool successive_ids) {
|
|
|
64
64
|
FAISS_ASSERT(ifl2);
|
|
65
65
|
ifl->merge_from(*ifl2, successive_ids ? ifl->ntotal : 0);
|
|
66
66
|
} else {
|
|
67
|
-
FAISS_ASSERT(
|
|
67
|
+
FAISS_ASSERT(false && "merging not implemented for this type of class");
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
#include <faiss/impl/FaissAssert.h>
|
|
22
22
|
#include <faiss/impl/LocalSearchQuantizer.h>
|
|
23
23
|
#include <faiss/impl/ResidualQuantizer.h>
|
|
24
|
+
#include <faiss/impl/simd_dispatch.h>
|
|
24
25
|
#include <faiss/utils/Heap.h>
|
|
25
26
|
#include <faiss/utils/distances.h>
|
|
26
27
|
#include <faiss/utils/hamming.h>
|
|
@@ -66,8 +67,10 @@ void AdditiveQuantizer::set_derived_values() {
|
|
|
66
67
|
codebook_offsets.resize(M + 1, 0);
|
|
67
68
|
for (int i = 0; i < M; i++) {
|
|
68
69
|
int nbit = nbits[i];
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
FAISS_CHECK_RANGE(nbit, 0, 31);
|
|
71
|
+
size_t k = (size_t)1 << nbit;
|
|
72
|
+
codebook_offsets[i + 1] =
|
|
73
|
+
add_no_overflow(codebook_offsets[i], k, "codebook_offsets");
|
|
71
74
|
tot_bits += nbit;
|
|
72
75
|
if (nbit != 0) {
|
|
73
76
|
only_8bit = false;
|
|
@@ -153,12 +156,24 @@ void AdditiveQuantizer::train_norm(size_t n, const float* norms) {
|
|
|
153
156
|
|
|
154
157
|
void AdditiveQuantizer::compute_codebook_tables() {
|
|
155
158
|
centroid_norms.resize(total_codebook_size);
|
|
159
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
160
|
+
codebooks.size() >=
|
|
161
|
+
mul_no_overflow(
|
|
162
|
+
total_codebook_size, d, "codebooks validation"),
|
|
163
|
+
"codebooks size %zd too small for total_codebook_size=%zd * d=%zd",
|
|
164
|
+
codebooks.size(),
|
|
165
|
+
total_codebook_size,
|
|
166
|
+
d);
|
|
156
167
|
fvec_norms_L2sqr(
|
|
157
168
|
centroid_norms.data(), codebooks.data(), d, total_codebook_size);
|
|
158
169
|
size_t cross_table_size = 0;
|
|
159
170
|
for (int m = 0; m < M; m++) {
|
|
171
|
+
FAISS_CHECK_RANGE(nbits[m], 0, 31);
|
|
160
172
|
size_t K = (size_t)1 << nbits[m];
|
|
161
|
-
|
|
173
|
+
size_t product =
|
|
174
|
+
mul_no_overflow(K, codebook_offsets[m], "cross_table_size");
|
|
175
|
+
cross_table_size = add_no_overflow(
|
|
176
|
+
cross_table_size, product, "cross_table_size accumulation");
|
|
162
177
|
}
|
|
163
178
|
codebook_cross_products.resize(cross_table_size);
|
|
164
179
|
size_t ofs = 0;
|
|
@@ -167,7 +182,16 @@ void AdditiveQuantizer::compute_codebook_tables() {
|
|
|
167
182
|
FINTEGER kk = codebook_offsets[m];
|
|
168
183
|
FINTEGER di = d;
|
|
169
184
|
float zero = 0, one = 1;
|
|
170
|
-
|
|
185
|
+
size_t step_size = (size_t)ki * (size_t)kk;
|
|
186
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
187
|
+
add_no_overflow(ofs, step_size, "cross product table offset") <=
|
|
188
|
+
cross_table_size,
|
|
189
|
+
"cross product table overflow at step %d: "
|
|
190
|
+
"%zd + %zd > %zd",
|
|
191
|
+
m,
|
|
192
|
+
ofs,
|
|
193
|
+
step_size,
|
|
194
|
+
cross_table_size);
|
|
171
195
|
sgemm_("Transposed",
|
|
172
196
|
"Not transposed",
|
|
173
197
|
&ki,
|
|
@@ -181,7 +205,7 @@ void AdditiveQuantizer::compute_codebook_tables() {
|
|
|
181
205
|
&zero,
|
|
182
206
|
codebook_cross_products.data() + ofs,
|
|
183
207
|
&ki);
|
|
184
|
-
ofs +=
|
|
208
|
+
ofs += step_size;
|
|
185
209
|
}
|
|
186
210
|
}
|
|
187
211
|
|
|
@@ -348,15 +372,17 @@ AdditiveQuantizer::~AdditiveQuantizer() {}
|
|
|
348
372
|
void AdditiveQuantizer::compute_centroid_norms(float* norms) const {
|
|
349
373
|
size_t ntotal = (size_t)1 << tot_bits;
|
|
350
374
|
// TODO: make tree of partial sums
|
|
375
|
+
with_simd_level([&]<SIMDLevel SL>() {
|
|
351
376
|
#pragma omp parallel
|
|
352
|
-
|
|
353
|
-
|
|
377
|
+
{
|
|
378
|
+
std::vector<float> tmp(d);
|
|
354
379
|
#pragma omp for
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
380
|
+
for (int64_t i = 0; i < ntotal; i++) {
|
|
381
|
+
decode_64bit(i, tmp.data());
|
|
382
|
+
norms[i] = fvec_norm_L2sqr<SL>(tmp.data(), d);
|
|
383
|
+
}
|
|
358
384
|
}
|
|
359
|
-
}
|
|
385
|
+
});
|
|
360
386
|
}
|
|
361
387
|
|
|
362
388
|
void AdditiveQuantizer::decode_64bit(idx_t bits, float* xi) const {
|
|
@@ -169,34 +169,6 @@ struct TimeoutCallback : InterruptCallback {
|
|
|
169
169
|
static void reset(double timeout_in_seconds);
|
|
170
170
|
};
|
|
171
171
|
|
|
172
|
-
/// set implementation optimized for fast access.
|
|
173
|
-
struct VisitedTable {
|
|
174
|
-
std::vector<uint8_t> visited;
|
|
175
|
-
uint8_t visno;
|
|
176
|
-
|
|
177
|
-
explicit VisitedTable(int size) : visited(size), visno(1) {}
|
|
178
|
-
|
|
179
|
-
/// set flag #no to true
|
|
180
|
-
void set(int no) {
|
|
181
|
-
visited[no] = visno;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/// get flag #no
|
|
185
|
-
bool get(int no) const {
|
|
186
|
-
return visited[no] == visno;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/// reset all flags to false
|
|
190
|
-
void advance() {
|
|
191
|
-
visno++;
|
|
192
|
-
if (visno == 250) {
|
|
193
|
-
// 250 rather than 255 because sometimes we use visno and visno+1
|
|
194
|
-
memset(visited.data(), 0, sizeof(visited[0]) * visited.size());
|
|
195
|
-
visno = 1;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
|
|
200
172
|
} // namespace faiss
|
|
201
173
|
|
|
202
174
|
#endif
|