faiss 0.1.5 → 0.2.2
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 +24 -0
- data/README.md +12 -0
- data/ext/faiss/ext.cpp +1 -1
- data/ext/faiss/extconf.rb +6 -2
- data/ext/faiss/index.cpp +114 -43
- data/ext/faiss/index_binary.cpp +24 -30
- data/ext/faiss/kmeans.cpp +20 -16
- data/ext/faiss/numo.hpp +867 -0
- data/ext/faiss/pca_matrix.cpp +13 -14
- data/ext/faiss/product_quantizer.cpp +23 -24
- data/ext/faiss/utils.cpp +10 -37
- data/ext/faiss/utils.h +2 -13
- data/lib/faiss.rb +0 -5
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +292 -291
- data/vendor/faiss/faiss/AutoTune.h +55 -56
- data/vendor/faiss/faiss/Clustering.cpp +334 -195
- data/vendor/faiss/faiss/Clustering.h +88 -35
- data/vendor/faiss/faiss/IVFlib.cpp +171 -195
- data/vendor/faiss/faiss/IVFlib.h +48 -51
- data/vendor/faiss/faiss/Index.cpp +85 -103
- data/vendor/faiss/faiss/Index.h +54 -48
- data/vendor/faiss/faiss/Index2Layer.cpp +139 -164
- data/vendor/faiss/faiss/Index2Layer.h +22 -22
- data/vendor/faiss/faiss/IndexBinary.cpp +45 -37
- data/vendor/faiss/faiss/IndexBinary.h +140 -132
- data/vendor/faiss/faiss/IndexBinaryFlat.cpp +73 -53
- data/vendor/faiss/faiss/IndexBinaryFlat.h +29 -24
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +46 -43
- data/vendor/faiss/faiss/IndexBinaryFromFloat.h +16 -15
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +215 -232
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +25 -24
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +182 -177
- data/vendor/faiss/faiss/IndexBinaryHash.h +41 -34
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +489 -461
- data/vendor/faiss/faiss/IndexBinaryIVF.h +97 -68
- data/vendor/faiss/faiss/IndexFlat.cpp +116 -147
- data/vendor/faiss/faiss/IndexFlat.h +35 -46
- data/vendor/faiss/faiss/IndexHNSW.cpp +372 -348
- data/vendor/faiss/faiss/IndexHNSW.h +57 -41
- data/vendor/faiss/faiss/IndexIVF.cpp +474 -454
- data/vendor/faiss/faiss/IndexIVF.h +146 -113
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +248 -250
- data/vendor/faiss/faiss/IndexIVFFlat.h +48 -51
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +457 -516
- data/vendor/faiss/faiss/IndexIVFPQ.h +74 -66
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +406 -372
- data/vendor/faiss/faiss/IndexIVFPQFastScan.h +82 -57
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +104 -102
- data/vendor/faiss/faiss/IndexIVFPQR.h +33 -28
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +125 -133
- data/vendor/faiss/faiss/IndexIVFSpectralHash.h +19 -21
- data/vendor/faiss/faiss/IndexLSH.cpp +75 -96
- data/vendor/faiss/faiss/IndexLSH.h +21 -26
- data/vendor/faiss/faiss/IndexLattice.cpp +42 -56
- data/vendor/faiss/faiss/IndexLattice.h +11 -16
- data/vendor/faiss/faiss/IndexNNDescent.cpp +231 -0
- data/vendor/faiss/faiss/IndexNNDescent.h +72 -0
- data/vendor/faiss/faiss/IndexNSG.cpp +303 -0
- data/vendor/faiss/faiss/IndexNSG.h +85 -0
- data/vendor/faiss/faiss/IndexPQ.cpp +405 -464
- data/vendor/faiss/faiss/IndexPQ.h +64 -67
- data/vendor/faiss/faiss/IndexPQFastScan.cpp +143 -170
- data/vendor/faiss/faiss/IndexPQFastScan.h +46 -32
- data/vendor/faiss/faiss/IndexPreTransform.cpp +120 -150
- data/vendor/faiss/faiss/IndexPreTransform.h +33 -36
- data/vendor/faiss/faiss/IndexRefine.cpp +115 -131
- data/vendor/faiss/faiss/IndexRefine.h +22 -23
- data/vendor/faiss/faiss/IndexReplicas.cpp +147 -153
- data/vendor/faiss/faiss/IndexReplicas.h +62 -56
- data/vendor/faiss/faiss/IndexResidual.cpp +291 -0
- data/vendor/faiss/faiss/IndexResidual.h +152 -0
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +120 -155
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +41 -45
- data/vendor/faiss/faiss/IndexShards.cpp +256 -240
- data/vendor/faiss/faiss/IndexShards.h +85 -73
- data/vendor/faiss/faiss/MatrixStats.cpp +112 -97
- data/vendor/faiss/faiss/MatrixStats.h +7 -10
- data/vendor/faiss/faiss/MetaIndexes.cpp +135 -157
- data/vendor/faiss/faiss/MetaIndexes.h +40 -34
- data/vendor/faiss/faiss/MetricType.h +7 -7
- data/vendor/faiss/faiss/VectorTransform.cpp +652 -474
- data/vendor/faiss/faiss/VectorTransform.h +61 -89
- data/vendor/faiss/faiss/clone_index.cpp +77 -73
- data/vendor/faiss/faiss/clone_index.h +4 -9
- data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +33 -38
- data/vendor/faiss/faiss/gpu/GpuAutoTune.h +11 -9
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +197 -170
- data/vendor/faiss/faiss/gpu/GpuCloner.h +53 -35
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.cpp +12 -14
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +27 -25
- data/vendor/faiss/faiss/gpu/GpuDistance.h +116 -112
- data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -2
- data/vendor/faiss/faiss/gpu/GpuIndex.h +134 -137
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +76 -73
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +173 -162
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +67 -64
- data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +89 -86
- data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +150 -141
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +101 -103
- data/vendor/faiss/faiss/gpu/GpuIndicesOptions.h +17 -16
- data/vendor/faiss/faiss/gpu/GpuResources.cpp +116 -128
- data/vendor/faiss/faiss/gpu/GpuResources.h +182 -186
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +433 -422
- data/vendor/faiss/faiss/gpu/StandardGpuResources.h +131 -130
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +468 -456
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.h +25 -19
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +22 -20
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +9 -8
- data/vendor/faiss/faiss/gpu/perf/IndexWrapper-inl.h +39 -44
- data/vendor/faiss/faiss/gpu/perf/IndexWrapper.h +16 -14
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +77 -71
- data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +109 -88
- data/vendor/faiss/faiss/gpu/perf/WriteIndex.cpp +75 -64
- data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +230 -215
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +80 -86
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +284 -277
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +416 -416
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +611 -517
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +166 -164
- data/vendor/faiss/faiss/gpu/test/TestGpuMemoryException.cpp +61 -53
- data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +274 -238
- data/vendor/faiss/faiss/gpu/test/TestUtils.h +73 -57
- data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +47 -50
- data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +79 -72
- data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +140 -146
- data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.h +69 -71
- data/vendor/faiss/faiss/gpu/utils/StaticUtils.h +21 -16
- data/vendor/faiss/faiss/gpu/utils/Timer.cpp +25 -29
- data/vendor/faiss/faiss/gpu/utils/Timer.h +30 -29
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +270 -0
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +115 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +90 -120
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +81 -65
- data/vendor/faiss/faiss/impl/FaissAssert.h +73 -58
- data/vendor/faiss/faiss/impl/FaissException.cpp +56 -48
- data/vendor/faiss/faiss/impl/FaissException.h +41 -29
- data/vendor/faiss/faiss/impl/HNSW.cpp +595 -611
- data/vendor/faiss/faiss/impl/HNSW.h +179 -200
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +672 -0
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +172 -0
- data/vendor/faiss/faiss/impl/NNDescent.cpp +487 -0
- data/vendor/faiss/faiss/impl/NNDescent.h +154 -0
- data/vendor/faiss/faiss/impl/NSG.cpp +682 -0
- data/vendor/faiss/faiss/impl/NSG.h +199 -0
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +484 -454
- data/vendor/faiss/faiss/impl/PolysemousTraining.h +52 -55
- data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +26 -47
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +469 -459
- data/vendor/faiss/faiss/impl/ProductQuantizer.h +76 -87
- data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +448 -0
- data/vendor/faiss/faiss/impl/ResidualQuantizer.h +130 -0
- data/vendor/faiss/faiss/impl/ResultHandler.h +96 -132
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +648 -701
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +48 -46
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +129 -131
- data/vendor/faiss/faiss/impl/ThreadedIndex.h +61 -55
- data/vendor/faiss/faiss/impl/index_read.cpp +547 -479
- data/vendor/faiss/faiss/impl/index_write.cpp +497 -407
- data/vendor/faiss/faiss/impl/io.cpp +75 -94
- data/vendor/faiss/faiss/impl/io.h +31 -41
- data/vendor/faiss/faiss/impl/io_macros.h +40 -29
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +137 -186
- data/vendor/faiss/faiss/impl/lattice_Zn.h +40 -51
- data/vendor/faiss/faiss/impl/platform_macros.h +29 -8
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +77 -124
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +39 -48
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +41 -52
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +80 -117
- data/vendor/faiss/faiss/impl/simd_result_handlers.h +109 -137
- data/vendor/faiss/faiss/index_factory.cpp +269 -218
- data/vendor/faiss/faiss/index_factory.h +6 -7
- data/vendor/faiss/faiss/index_io.h +23 -26
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +67 -75
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +22 -24
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +96 -112
- data/vendor/faiss/faiss/invlists/DirectMap.h +29 -33
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +307 -364
- data/vendor/faiss/faiss/invlists/InvertedLists.h +151 -151
- data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +29 -34
- data/vendor/faiss/faiss/invlists/InvertedListsIOHook.h +17 -18
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +257 -293
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +50 -45
- data/vendor/faiss/faiss/python/python_callbacks.cpp +23 -26
- data/vendor/faiss/faiss/python/python_callbacks.h +9 -16
- data/vendor/faiss/faiss/utils/AlignedTable.h +79 -44
- data/vendor/faiss/faiss/utils/Heap.cpp +40 -48
- data/vendor/faiss/faiss/utils/Heap.h +186 -209
- data/vendor/faiss/faiss/utils/WorkerThread.cpp +67 -76
- data/vendor/faiss/faiss/utils/WorkerThread.h +32 -33
- data/vendor/faiss/faiss/utils/distances.cpp +301 -310
- data/vendor/faiss/faiss/utils/distances.h +133 -118
- data/vendor/faiss/faiss/utils/distances_simd.cpp +456 -516
- data/vendor/faiss/faiss/utils/extra_distances-inl.h +117 -0
- data/vendor/faiss/faiss/utils/extra_distances.cpp +113 -232
- data/vendor/faiss/faiss/utils/extra_distances.h +30 -29
- data/vendor/faiss/faiss/utils/hamming-inl.h +260 -209
- data/vendor/faiss/faiss/utils/hamming.cpp +375 -469
- data/vendor/faiss/faiss/utils/hamming.h +62 -85
- data/vendor/faiss/faiss/utils/ordered_key_value.h +16 -18
- data/vendor/faiss/faiss/utils/partitioning.cpp +393 -318
- data/vendor/faiss/faiss/utils/partitioning.h +26 -21
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +78 -66
- data/vendor/faiss/faiss/utils/quantize_lut.h +22 -20
- data/vendor/faiss/faiss/utils/random.cpp +39 -63
- data/vendor/faiss/faiss/utils/random.h +13 -16
- data/vendor/faiss/faiss/utils/simdlib.h +4 -2
- data/vendor/faiss/faiss/utils/simdlib_avx2.h +88 -85
- data/vendor/faiss/faiss/utils/simdlib_emulated.h +226 -165
- data/vendor/faiss/faiss/utils/simdlib_neon.h +832 -0
- data/vendor/faiss/faiss/utils/utils.cpp +304 -287
- data/vendor/faiss/faiss/utils/utils.h +53 -48
- metadata +24 -10
- data/lib/faiss/index.rb +0 -20
- data/lib/faiss/index_binary.rb +0 -20
- data/lib/faiss/kmeans.rb +0 -15
- data/lib/faiss/pca_matrix.rb +0 -15
- data/lib/faiss/product_quantizer.rb +0 -22
@@ -9,48 +9,49 @@
|
|
9
9
|
|
10
10
|
#pragma once
|
11
11
|
|
12
|
-
#include <faiss/impl/HNSW.h>
|
13
12
|
#include <faiss/IndexBinaryFlat.h>
|
13
|
+
#include <faiss/impl/HNSW.h>
|
14
14
|
#include <faiss/utils/utils.h>
|
15
15
|
|
16
|
-
|
17
16
|
namespace faiss {
|
18
17
|
|
19
|
-
|
20
18
|
/** The HNSW index is a normal random-access index with a HNSW
|
21
19
|
* link structure built on top */
|
22
20
|
|
23
21
|
struct IndexBinaryHNSW : IndexBinary {
|
24
|
-
|
22
|
+
typedef HNSW::storage_idx_t storage_idx_t;
|
25
23
|
|
26
|
-
|
27
|
-
|
24
|
+
// the link strcuture
|
25
|
+
HNSW hnsw;
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
// the sequential storage
|
28
|
+
bool own_fields;
|
29
|
+
IndexBinary* storage;
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
explicit IndexBinaryHNSW();
|
32
|
+
explicit IndexBinaryHNSW(int d, int M = 32);
|
33
|
+
explicit IndexBinaryHNSW(IndexBinary* storage, int M = 32);
|
36
34
|
|
37
|
-
|
35
|
+
~IndexBinaryHNSW() override;
|
38
36
|
|
39
|
-
|
37
|
+
DistanceComputer* get_distance_computer() const;
|
40
38
|
|
41
|
-
|
39
|
+
void add(idx_t n, const uint8_t* x) override;
|
42
40
|
|
43
|
-
|
44
|
-
|
41
|
+
/// Trains the storage if needed
|
42
|
+
void train(idx_t n, const uint8_t* x) override;
|
45
43
|
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
/// entry point for search
|
45
|
+
void search(
|
46
|
+
idx_t n,
|
47
|
+
const uint8_t* x,
|
48
|
+
idx_t k,
|
49
|
+
int32_t* distances,
|
50
|
+
idx_t* labels) const override;
|
49
51
|
|
50
|
-
|
52
|
+
void reconstruct(idx_t key, uint8_t* recons) const override;
|
51
53
|
|
52
|
-
|
54
|
+
void reset() override;
|
53
55
|
};
|
54
56
|
|
55
|
-
|
56
|
-
} // namespace faiss
|
57
|
+
} // namespace faiss
|
@@ -22,44 +22,42 @@
|
|
22
22
|
|
23
23
|
namespace faiss {
|
24
24
|
|
25
|
-
void IndexBinaryHash::InvertedList::add
|
26
|
-
idx_t id,
|
27
|
-
|
25
|
+
void IndexBinaryHash::InvertedList::add(
|
26
|
+
idx_t id,
|
27
|
+
size_t code_size,
|
28
|
+
const uint8_t* code) {
|
28
29
|
ids.push_back(id);
|
29
30
|
vecs.insert(vecs.end(), code, code + code_size);
|
30
31
|
}
|
31
32
|
|
32
|
-
IndexBinaryHash::IndexBinaryHash(int d, int b)
|
33
|
-
|
34
|
-
{
|
33
|
+
IndexBinaryHash::IndexBinaryHash(int d, int b)
|
34
|
+
: IndexBinary(d), b(b), nflip(0) {
|
35
35
|
is_trained = true;
|
36
36
|
}
|
37
37
|
|
38
|
-
IndexBinaryHash::IndexBinaryHash(): b(0), nflip(0)
|
39
|
-
{
|
38
|
+
IndexBinaryHash::IndexBinaryHash() : b(0), nflip(0) {
|
40
39
|
is_trained = true;
|
41
40
|
}
|
42
41
|
|
43
|
-
void IndexBinaryHash::reset()
|
44
|
-
{
|
42
|
+
void IndexBinaryHash::reset() {
|
45
43
|
invlists.clear();
|
46
44
|
ntotal = 0;
|
47
45
|
}
|
48
46
|
|
49
|
-
|
50
|
-
void IndexBinaryHash::add(idx_t n, const uint8_t *x)
|
51
|
-
{
|
47
|
+
void IndexBinaryHash::add(idx_t n, const uint8_t* x) {
|
52
48
|
add_with_ids(n, x, nullptr);
|
53
49
|
}
|
54
50
|
|
55
|
-
void IndexBinaryHash::add_with_ids(
|
56
|
-
|
51
|
+
void IndexBinaryHash::add_with_ids(
|
52
|
+
idx_t n,
|
53
|
+
const uint8_t* x,
|
54
|
+
const idx_t* xids) {
|
57
55
|
uint64_t mask = ((uint64_t)1 << b) - 1;
|
58
56
|
// simplistic add function. Cannot really be parallelized.
|
59
57
|
|
60
58
|
for (idx_t i = 0; i < n; i++) {
|
61
59
|
idx_t id = xids ? xids[i] : ntotal + i;
|
62
|
-
const uint8_t
|
60
|
+
const uint8_t* xi = x + i * code_size;
|
63
61
|
idx_t hash = *((uint64_t*)xi) & mask;
|
64
62
|
invlists[hash].add(id, code_size, xi);
|
65
63
|
}
|
@@ -68,7 +66,6 @@ void IndexBinaryHash::add_with_ids(idx_t n, const uint8_t *x, const idx_t *xids)
|
|
68
66
|
|
69
67
|
namespace {
|
70
68
|
|
71
|
-
|
72
69
|
/** Enumerate all bit vectors of size nbit with up to maxflip 1s
|
73
70
|
* test in P127257851 P127258235
|
74
71
|
*/
|
@@ -76,7 +73,7 @@ struct FlipEnumerator {
|
|
76
73
|
int nbit, nflip, maxflip;
|
77
74
|
uint64_t mask, x;
|
78
75
|
|
79
|
-
FlipEnumerator
|
76
|
+
FlipEnumerator(int nbit, int maxflip) : nbit(nbit), maxflip(maxflip) {
|
80
77
|
nflip = 0;
|
81
78
|
mask = 0;
|
82
79
|
x = 0;
|
@@ -108,128 +105,133 @@ struct FlipEnumerator {
|
|
108
105
|
}
|
109
106
|
return true;
|
110
107
|
}
|
111
|
-
|
112
108
|
};
|
113
109
|
|
114
110
|
using idx_t = Index::idx_t;
|
115
111
|
|
116
|
-
|
117
112
|
struct RangeSearchResults {
|
118
113
|
int radius;
|
119
|
-
RangeQueryResult
|
114
|
+
RangeQueryResult& qres;
|
120
115
|
|
121
|
-
inline void add
|
116
|
+
inline void add(float dis, idx_t id) {
|
122
117
|
if (dis < radius) {
|
123
|
-
qres.add
|
118
|
+
qres.add(dis, id);
|
124
119
|
}
|
125
120
|
}
|
126
|
-
|
127
121
|
};
|
128
122
|
|
129
123
|
struct KnnSearchResults {
|
130
124
|
// heap params
|
131
125
|
idx_t k;
|
132
|
-
int32_t
|
133
|
-
idx_t
|
126
|
+
int32_t* heap_sim;
|
127
|
+
idx_t* heap_ids;
|
134
128
|
|
135
129
|
using C = CMax<int, idx_t>;
|
136
130
|
|
137
|
-
inline void add
|
131
|
+
inline void add(float dis, idx_t id) {
|
138
132
|
if (dis < heap_sim[0]) {
|
139
|
-
heap_replace_top<C>
|
133
|
+
heap_replace_top<C>(k, heap_sim, heap_ids, dis, id);
|
140
134
|
}
|
141
135
|
}
|
142
|
-
|
143
136
|
};
|
144
137
|
|
145
|
-
template<class HammingComputer, class SearchResults>
|
146
|
-
void
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
138
|
+
template <class HammingComputer, class SearchResults>
|
139
|
+
void search_single_query_template(
|
140
|
+
const IndexBinaryHash& index,
|
141
|
+
const uint8_t* q,
|
142
|
+
SearchResults& res,
|
143
|
+
size_t& n0,
|
144
|
+
size_t& nlist,
|
145
|
+
size_t& ndis) {
|
151
146
|
size_t code_size = index.code_size;
|
152
147
|
uint64_t mask = ((uint64_t)1 << index.b) - 1;
|
153
148
|
uint64_t qhash = *((uint64_t*)q) & mask;
|
154
|
-
HammingComputer hc
|
149
|
+
HammingComputer hc(q, code_size);
|
155
150
|
FlipEnumerator fe(index.b, index.nflip);
|
156
151
|
|
157
152
|
// loop over neighbors that are at most at nflip bits
|
158
153
|
do {
|
159
154
|
uint64_t hash = qhash ^ fe.x;
|
160
|
-
auto it = index.invlists.find
|
155
|
+
auto it = index.invlists.find(hash);
|
161
156
|
|
162
157
|
if (it == index.invlists.end()) {
|
163
158
|
continue;
|
164
159
|
}
|
165
160
|
|
166
|
-
const IndexBinaryHash::InvertedList
|
161
|
+
const IndexBinaryHash::InvertedList& il = it->second;
|
167
162
|
|
168
163
|
size_t nv = il.ids.size();
|
169
164
|
|
170
165
|
if (nv == 0) {
|
171
166
|
n0++;
|
172
167
|
} else {
|
173
|
-
const uint8_t
|
168
|
+
const uint8_t* codes = il.vecs.data();
|
174
169
|
for (size_t i = 0; i < nv; i++) {
|
175
|
-
int dis = hc.hamming
|
170
|
+
int dis = hc.hamming(codes);
|
176
171
|
res.add(dis, il.ids[i]);
|
177
172
|
codes += code_size;
|
178
173
|
}
|
179
174
|
ndis += nv;
|
180
175
|
nlist++;
|
181
176
|
}
|
182
|
-
} while(fe.next());
|
177
|
+
} while (fe.next());
|
183
178
|
}
|
184
179
|
|
185
|
-
template<class SearchResults>
|
186
|
-
void
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
HC(
|
201
|
-
|
180
|
+
template <class SearchResults>
|
181
|
+
void search_single_query(
|
182
|
+
const IndexBinaryHash& index,
|
183
|
+
const uint8_t* q,
|
184
|
+
SearchResults& res,
|
185
|
+
size_t& n0,
|
186
|
+
size_t& nlist,
|
187
|
+
size_t& ndis) {
|
188
|
+
#define HC(name) \
|
189
|
+
search_single_query_template<name>(index, q, res, n0, nlist, ndis);
|
190
|
+
switch (index.code_size) {
|
191
|
+
case 4:
|
192
|
+
HC(HammingComputer4);
|
193
|
+
break;
|
194
|
+
case 8:
|
195
|
+
HC(HammingComputer8);
|
196
|
+
break;
|
197
|
+
case 16:
|
198
|
+
HC(HammingComputer16);
|
199
|
+
break;
|
200
|
+
case 20:
|
201
|
+
HC(HammingComputer20);
|
202
|
+
break;
|
203
|
+
case 32:
|
204
|
+
HC(HammingComputer32);
|
205
|
+
break;
|
206
|
+
default:
|
202
207
|
HC(HammingComputerDefault);
|
203
|
-
|
208
|
+
break;
|
204
209
|
}
|
205
210
|
#undef HC
|
206
211
|
}
|
207
212
|
|
208
|
-
|
209
213
|
} // anonymous namespace
|
210
214
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
{
|
216
|
-
|
215
|
+
void IndexBinaryHash::range_search(
|
216
|
+
idx_t n,
|
217
|
+
const uint8_t* x,
|
218
|
+
int radius,
|
219
|
+
RangeSearchResult* result) const {
|
217
220
|
size_t nlist = 0, ndis = 0, n0 = 0;
|
218
221
|
|
219
|
-
#pragma omp parallel if(n > 100) reduction(
|
222
|
+
#pragma omp parallel if (n > 100) reduction(+ : ndis, n0, nlist)
|
220
223
|
{
|
221
|
-
RangeSearchPartialResult pres
|
224
|
+
RangeSearchPartialResult pres(result);
|
222
225
|
|
223
226
|
#pragma omp for
|
224
227
|
for (idx_t i = 0; i < n; i++) { // loop queries
|
225
|
-
RangeQueryResult
|
228
|
+
RangeQueryResult& qres = pres.new_result(i);
|
226
229
|
RangeSearchResults res = {radius, qres};
|
227
|
-
const uint8_t
|
228
|
-
|
229
|
-
search_single_query (*this, q, res, n0, nlist, ndis);
|
230
|
+
const uint8_t* q = x + i * code_size;
|
230
231
|
|
232
|
+
search_single_query(*this, q, res, n0, nlist, ndis);
|
231
233
|
}
|
232
|
-
pres.finalize
|
234
|
+
pres.finalize();
|
233
235
|
}
|
234
236
|
indexBinaryHash_stats.nq += n;
|
235
237
|
indexBinaryHash_stats.n0 += n0;
|
@@ -237,24 +239,29 @@ void IndexBinaryHash::range_search(idx_t n, const uint8_t *x, int radius,
|
|
237
239
|
indexBinaryHash_stats.ndis += ndis;
|
238
240
|
}
|
239
241
|
|
240
|
-
void IndexBinaryHash::search(
|
241
|
-
|
242
|
-
|
242
|
+
void IndexBinaryHash::search(
|
243
|
+
idx_t n,
|
244
|
+
const uint8_t* x,
|
245
|
+
idx_t k,
|
246
|
+
int32_t* distances,
|
247
|
+
idx_t* labels) const {
|
248
|
+
FAISS_THROW_IF_NOT(k > 0);
|
243
249
|
|
244
250
|
using HeapForL2 = CMax<int32_t, idx_t>;
|
245
251
|
size_t nlist = 0, ndis = 0, n0 = 0;
|
246
252
|
|
247
|
-
#pragma omp parallel for if(n > 100) reduction(
|
253
|
+
#pragma omp parallel for if (n > 100) reduction(+ : nlist, ndis, n0)
|
248
254
|
for (idx_t i = 0; i < n; i++) {
|
249
|
-
int32_t
|
250
|
-
idx_t
|
255
|
+
int32_t* simi = distances + k * i;
|
256
|
+
idx_t* idxi = labels + k * i;
|
251
257
|
|
252
|
-
heap_heapify<HeapForL2>
|
258
|
+
heap_heapify<HeapForL2>(k, simi, idxi);
|
253
259
|
KnnSearchResults res = {k, simi, idxi};
|
254
|
-
const uint8_t
|
260
|
+
const uint8_t* q = x + i * code_size;
|
255
261
|
|
256
|
-
search_single_query
|
262
|
+
search_single_query(*this, q, res, n0, nlist, ndis);
|
257
263
|
|
264
|
+
heap_reorder<HeapForL2>(k, simi, idxi);
|
258
265
|
}
|
259
266
|
indexBinaryHash_stats.nq += n;
|
260
267
|
indexBinaryHash_stats.n0 += n0;
|
@@ -262,29 +269,23 @@ void IndexBinaryHash::search(idx_t n, const uint8_t *x, idx_t k,
|
|
262
269
|
indexBinaryHash_stats.ndis += ndis;
|
263
270
|
}
|
264
271
|
|
265
|
-
size_t IndexBinaryHash::hashtable_size() const
|
266
|
-
{
|
272
|
+
size_t IndexBinaryHash::hashtable_size() const {
|
267
273
|
return invlists.size();
|
268
274
|
}
|
269
275
|
|
270
|
-
|
271
|
-
void IndexBinaryHash::display() const
|
272
|
-
{
|
276
|
+
void IndexBinaryHash::display() const {
|
273
277
|
for (auto it = invlists.begin(); it != invlists.end(); ++it) {
|
274
278
|
printf("%" PRId64 ": [", it->first);
|
275
|
-
const std::vector<idx_t
|
276
|
-
for (auto x: v) {
|
279
|
+
const std::vector<idx_t>& v = it->second.ids;
|
280
|
+
for (auto x : v) {
|
277
281
|
printf("%" PRId64 " ", x);
|
278
282
|
}
|
279
283
|
printf("]\n");
|
280
|
-
|
281
284
|
}
|
282
285
|
}
|
283
286
|
|
284
|
-
|
285
|
-
void
|
286
|
-
{
|
287
|
-
memset ((void*)this, 0, sizeof (*this));
|
287
|
+
void IndexBinaryHashStats::reset() {
|
288
|
+
memset((void*)this, 0, sizeof(*this));
|
288
289
|
}
|
289
290
|
|
290
291
|
IndexBinaryHashStats indexBinaryHash_stats;
|
@@ -293,47 +294,43 @@ IndexBinaryHashStats indexBinaryHash_stats;
|
|
293
294
|
* IndexBinaryMultiHash implementation
|
294
295
|
******************************************************/
|
295
296
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
297
|
+
IndexBinaryMultiHash::IndexBinaryMultiHash(int d, int nhash, int b)
|
298
|
+
: IndexBinary(d),
|
299
|
+
storage(new IndexBinaryFlat(d)),
|
300
|
+
own_fields(true),
|
301
|
+
maps(nhash),
|
302
|
+
nhash(nhash),
|
303
|
+
b(b),
|
304
|
+
nflip(0) {
|
302
305
|
FAISS_THROW_IF_NOT(nhash * b <= d);
|
303
306
|
}
|
304
307
|
|
305
|
-
IndexBinaryMultiHash::IndexBinaryMultiHash()
|
306
|
-
|
307
|
-
nhash(0), b(0), nflip(0)
|
308
|
-
{}
|
308
|
+
IndexBinaryMultiHash::IndexBinaryMultiHash()
|
309
|
+
: storage(nullptr), own_fields(true), nhash(0), b(0), nflip(0) {}
|
309
310
|
|
310
|
-
IndexBinaryMultiHash::~IndexBinaryMultiHash()
|
311
|
-
{
|
311
|
+
IndexBinaryMultiHash::~IndexBinaryMultiHash() {
|
312
312
|
if (own_fields) {
|
313
313
|
delete storage;
|
314
314
|
}
|
315
315
|
}
|
316
316
|
|
317
|
-
|
318
|
-
void IndexBinaryMultiHash::reset()
|
319
|
-
{
|
317
|
+
void IndexBinaryMultiHash::reset() {
|
320
318
|
storage->reset();
|
321
319
|
ntotal = 0;
|
322
|
-
for(auto map: maps) {
|
320
|
+
for (auto map : maps) {
|
323
321
|
map.clear();
|
324
322
|
}
|
325
323
|
}
|
326
324
|
|
327
|
-
void IndexBinaryMultiHash::add(idx_t n, const uint8_t
|
328
|
-
{
|
325
|
+
void IndexBinaryMultiHash::add(idx_t n, const uint8_t* x) {
|
329
326
|
storage->add(n, x);
|
330
327
|
// populate maps
|
331
328
|
uint64_t mask = ((uint64_t)1 << b) - 1;
|
332
329
|
|
333
|
-
for(idx_t i = 0; i < n; i++) {
|
334
|
-
const uint8_t
|
330
|
+
for (idx_t i = 0; i < n; i++) {
|
331
|
+
const uint8_t* xi = x + i * code_size;
|
335
332
|
int ho = 0;
|
336
|
-
for(int h = 0; h < nhash; h++) {
|
333
|
+
for (int h = 0; h < nhash; h++) {
|
337
334
|
uint64_t hash = *(uint64_t*)(xi + (ho >> 3)) >> (ho & 7);
|
338
335
|
hash &= mask;
|
339
336
|
maps[h][hash].push_back(i + ntotal);
|
@@ -343,62 +340,60 @@ void IndexBinaryMultiHash::add(idx_t n, const uint8_t *x)
|
|
343
340
|
ntotal += n;
|
344
341
|
}
|
345
342
|
|
346
|
-
|
347
343
|
namespace {
|
348
344
|
|
349
345
|
template <class HammingComputer, class SearchResults>
|
350
|
-
static
|
351
|
-
|
352
|
-
const
|
353
|
-
const
|
354
|
-
|
355
|
-
SearchResults &res)
|
356
|
-
{
|
346
|
+
static void verify_shortlist(
|
347
|
+
const IndexBinaryFlat& index,
|
348
|
+
const uint8_t* q,
|
349
|
+
const std::unordered_set<Index::idx_t>& shortlist,
|
350
|
+
SearchResults& res) {
|
357
351
|
size_t code_size = index.code_size;
|
358
352
|
size_t nlist = 0, ndis = 0, n0 = 0;
|
359
353
|
|
360
|
-
HammingComputer hc
|
361
|
-
const uint8_t
|
354
|
+
HammingComputer hc(q, code_size);
|
355
|
+
const uint8_t* codes = index.xb.data();
|
362
356
|
|
363
|
-
for (auto i: shortlist) {
|
364
|
-
int dis = hc.hamming
|
357
|
+
for (auto i : shortlist) {
|
358
|
+
int dis = hc.hamming(codes + i * code_size);
|
365
359
|
res.add(dis, i);
|
366
360
|
}
|
367
361
|
}
|
368
362
|
|
369
|
-
template<class SearchResults>
|
370
|
-
void
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
363
|
+
template <class SearchResults>
|
364
|
+
void search_1_query_multihash(
|
365
|
+
const IndexBinaryMultiHash& index,
|
366
|
+
const uint8_t* xi,
|
367
|
+
SearchResults& res,
|
368
|
+
size_t& n0,
|
369
|
+
size_t& nlist,
|
370
|
+
size_t& ndis) {
|
376
371
|
std::unordered_set<idx_t> shortlist;
|
377
372
|
int b = index.b;
|
378
373
|
uint64_t mask = ((uint64_t)1 << b) - 1;
|
379
374
|
|
380
375
|
int ho = 0;
|
381
|
-
for(int h = 0; h < index.nhash; h++) {
|
376
|
+
for (int h = 0; h < index.nhash; h++) {
|
382
377
|
uint64_t qhash = *(uint64_t*)(xi + (ho >> 3)) >> (ho & 7);
|
383
378
|
qhash &= mask;
|
384
|
-
const IndexBinaryMultiHash::Map
|
379
|
+
const IndexBinaryMultiHash::Map& map = index.maps[h];
|
385
380
|
|
386
381
|
FlipEnumerator fe(index.b, index.nflip);
|
387
382
|
// loop over neighbors that are at most at nflip bits
|
388
383
|
do {
|
389
384
|
uint64_t hash = qhash ^ fe.x;
|
390
|
-
auto it = map.find
|
385
|
+
auto it = map.find(hash);
|
391
386
|
|
392
387
|
if (it != map.end()) {
|
393
|
-
const std::vector<idx_t
|
394
|
-
for (auto i: v) {
|
388
|
+
const std::vector<idx_t>& v = it->second;
|
389
|
+
for (auto i : v) {
|
395
390
|
shortlist.insert(i);
|
396
391
|
}
|
397
392
|
nlist++;
|
398
393
|
} else {
|
399
394
|
n0++;
|
400
395
|
}
|
401
|
-
} while(fe.next());
|
396
|
+
} while (fe.next());
|
402
397
|
|
403
398
|
ho += b;
|
404
399
|
}
|
@@ -406,45 +401,52 @@ search_1_query_multihash(const IndexBinaryMultiHash & index, const uint8_t *xi,
|
|
406
401
|
|
407
402
|
// verify shortlist
|
408
403
|
|
409
|
-
#define HC(name) verify_shortlist<name>
|
410
|
-
switch(index.code_size) {
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
HC(
|
419
|
-
|
404
|
+
#define HC(name) verify_shortlist<name>(*index.storage, xi, shortlist, res)
|
405
|
+
switch (index.code_size) {
|
406
|
+
case 4:
|
407
|
+
HC(HammingComputer4);
|
408
|
+
break;
|
409
|
+
case 8:
|
410
|
+
HC(HammingComputer8);
|
411
|
+
break;
|
412
|
+
case 16:
|
413
|
+
HC(HammingComputer16);
|
414
|
+
break;
|
415
|
+
case 20:
|
416
|
+
HC(HammingComputer20);
|
417
|
+
break;
|
418
|
+
case 32:
|
419
|
+
HC(HammingComputer32);
|
420
|
+
break;
|
421
|
+
default:
|
420
422
|
HC(HammingComputerDefault);
|
421
|
-
|
423
|
+
break;
|
422
424
|
}
|
423
425
|
#undef HC
|
424
426
|
}
|
425
427
|
|
426
428
|
} // anonymous namespace
|
427
429
|
|
428
|
-
void IndexBinaryMultiHash::range_search(
|
429
|
-
|
430
|
-
|
431
|
-
|
430
|
+
void IndexBinaryMultiHash::range_search(
|
431
|
+
idx_t n,
|
432
|
+
const uint8_t* x,
|
433
|
+
int radius,
|
434
|
+
RangeSearchResult* result) const {
|
432
435
|
size_t nlist = 0, ndis = 0, n0 = 0;
|
433
436
|
|
434
|
-
#pragma omp parallel if(n > 100) reduction(
|
437
|
+
#pragma omp parallel if (n > 100) reduction(+ : ndis, n0, nlist)
|
435
438
|
{
|
436
|
-
RangeSearchPartialResult pres
|
439
|
+
RangeSearchPartialResult pres(result);
|
437
440
|
|
438
441
|
#pragma omp for
|
439
442
|
for (idx_t i = 0; i < n; i++) { // loop queries
|
440
|
-
RangeQueryResult
|
443
|
+
RangeQueryResult& qres = pres.new_result(i);
|
441
444
|
RangeSearchResults res = {radius, qres};
|
442
|
-
const uint8_t
|
443
|
-
|
444
|
-
search_1_query_multihash (*this, q, res, n0, nlist, ndis);
|
445
|
+
const uint8_t* q = x + i * code_size;
|
445
446
|
|
447
|
+
search_1_query_multihash(*this, q, res, n0, nlist, ndis);
|
446
448
|
}
|
447
|
-
pres.finalize
|
449
|
+
pres.finalize();
|
448
450
|
}
|
449
451
|
indexBinaryHash_stats.nq += n;
|
450
452
|
indexBinaryHash_stats.n0 += n0;
|
@@ -452,24 +454,29 @@ void IndexBinaryMultiHash::range_search(idx_t n, const uint8_t *x, int radius,
|
|
452
454
|
indexBinaryHash_stats.ndis += ndis;
|
453
455
|
}
|
454
456
|
|
455
|
-
void IndexBinaryMultiHash::search(
|
456
|
-
|
457
|
-
|
457
|
+
void IndexBinaryMultiHash::search(
|
458
|
+
idx_t n,
|
459
|
+
const uint8_t* x,
|
460
|
+
idx_t k,
|
461
|
+
int32_t* distances,
|
462
|
+
idx_t* labels) const {
|
463
|
+
FAISS_THROW_IF_NOT(k > 0);
|
458
464
|
|
459
465
|
using HeapForL2 = CMax<int32_t, idx_t>;
|
460
466
|
size_t nlist = 0, ndis = 0, n0 = 0;
|
461
467
|
|
462
|
-
#pragma omp parallel for if(n > 100) reduction(
|
468
|
+
#pragma omp parallel for if (n > 100) reduction(+ : nlist, ndis, n0)
|
463
469
|
for (idx_t i = 0; i < n; i++) {
|
464
|
-
int32_t
|
465
|
-
idx_t
|
470
|
+
int32_t* simi = distances + k * i;
|
471
|
+
idx_t* idxi = labels + k * i;
|
466
472
|
|
467
|
-
heap_heapify<HeapForL2>
|
473
|
+
heap_heapify<HeapForL2>(k, simi, idxi);
|
468
474
|
KnnSearchResults res = {k, simi, idxi};
|
469
|
-
const uint8_t
|
475
|
+
const uint8_t* q = x + i * code_size;
|
470
476
|
|
471
|
-
search_1_query_multihash
|
477
|
+
search_1_query_multihash(*this, q, res, n0, nlist, ndis);
|
472
478
|
|
479
|
+
heap_reorder<HeapForL2>(k, simi, idxi);
|
473
480
|
}
|
474
481
|
indexBinaryHash_stats.nq += n;
|
475
482
|
indexBinaryHash_stats.n0 += n0;
|
@@ -477,15 +484,13 @@ void IndexBinaryMultiHash::search(idx_t n, const uint8_t *x, idx_t k,
|
|
477
484
|
indexBinaryHash_stats.ndis += ndis;
|
478
485
|
}
|
479
486
|
|
480
|
-
size_t IndexBinaryMultiHash::hashtable_size() const
|
481
|
-
{
|
487
|
+
size_t IndexBinaryMultiHash::hashtable_size() const {
|
482
488
|
size_t tot = 0;
|
483
|
-
for (auto map: maps) {
|
489
|
+
for (auto map : maps) {
|
484
490
|
tot += map.size();
|
485
491
|
}
|
486
492
|
|
487
493
|
return tot;
|
488
494
|
}
|
489
495
|
|
490
|
-
|
491
|
-
}
|
496
|
+
} // namespace faiss
|