faiss 0.2.6 → 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/ext/faiss/extconf.rb +1 -1
- data/lib/faiss/version.rb +1 -1
- data/lib/faiss.rb +2 -2
- data/vendor/faiss/faiss/AutoTune.cpp +15 -4
- data/vendor/faiss/faiss/AutoTune.h +0 -1
- data/vendor/faiss/faiss/Clustering.cpp +1 -5
- data/vendor/faiss/faiss/Clustering.h +0 -2
- data/vendor/faiss/faiss/IVFlib.h +0 -2
- data/vendor/faiss/faiss/Index.h +1 -2
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +17 -3
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +10 -1
- data/vendor/faiss/faiss/IndexBinary.h +0 -1
- data/vendor/faiss/faiss/IndexBinaryFlat.cpp +2 -1
- data/vendor/faiss/faiss/IndexBinaryFlat.h +4 -0
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +1 -3
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +273 -48
- data/vendor/faiss/faiss/IndexBinaryIVF.h +18 -11
- data/vendor/faiss/faiss/IndexFastScan.cpp +13 -10
- data/vendor/faiss/faiss/IndexFastScan.h +5 -1
- data/vendor/faiss/faiss/IndexFlat.cpp +16 -3
- data/vendor/faiss/faiss/IndexFlat.h +1 -1
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +5 -0
- data/vendor/faiss/faiss/IndexFlatCodes.h +7 -2
- data/vendor/faiss/faiss/IndexHNSW.cpp +3 -6
- data/vendor/faiss/faiss/IndexHNSW.h +0 -1
- data/vendor/faiss/faiss/IndexIDMap.cpp +4 -4
- data/vendor/faiss/faiss/IndexIDMap.h +0 -2
- data/vendor/faiss/faiss/IndexIVF.cpp +155 -129
- data/vendor/faiss/faiss/IndexIVF.h +121 -61
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +12 -11
- data/vendor/faiss/faiss/IndexIVFFastScan.h +6 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +221 -165
- data/vendor/faiss/faiss/IndexIVFPQ.h +1 -0
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +6 -1
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +0 -2
- data/vendor/faiss/faiss/IndexNNDescent.cpp +1 -2
- data/vendor/faiss/faiss/IndexNNDescent.h +0 -1
- data/vendor/faiss/faiss/IndexNSG.cpp +1 -2
- data/vendor/faiss/faiss/IndexPQ.cpp +7 -9
- data/vendor/faiss/faiss/IndexRefine.cpp +1 -1
- data/vendor/faiss/faiss/IndexReplicas.cpp +3 -4
- data/vendor/faiss/faiss/IndexReplicas.h +0 -1
- data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +8 -1
- data/vendor/faiss/faiss/IndexRowwiseMinMax.h +7 -0
- data/vendor/faiss/faiss/IndexShards.cpp +26 -109
- data/vendor/faiss/faiss/IndexShards.h +2 -3
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +246 -0
- data/vendor/faiss/faiss/IndexShardsIVF.h +42 -0
- data/vendor/faiss/faiss/MetaIndexes.cpp +86 -0
- data/vendor/faiss/faiss/MetaIndexes.h +29 -0
- data/vendor/faiss/faiss/MetricType.h +14 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +8 -10
- data/vendor/faiss/faiss/VectorTransform.h +1 -3
- data/vendor/faiss/faiss/clone_index.cpp +232 -18
- data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +25 -3
- data/vendor/faiss/faiss/cppcontrib/detail/CoarseBitType.h +7 -0
- data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +78 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +20 -6
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +7 -1
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +21 -7
- data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMax-inl.h +7 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMaxFP16-inl.h +7 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +10 -3
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +7 -1
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +11 -3
- data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +25 -2
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +76 -29
- data/vendor/faiss/faiss/gpu/GpuCloner.h +2 -2
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +14 -13
- data/vendor/faiss/faiss/gpu/GpuDistance.h +18 -6
- data/vendor/faiss/faiss/gpu/GpuIndex.h +23 -21
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +10 -10
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -12
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +29 -50
- data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +3 -3
- data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +8 -8
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +4 -4
- data/vendor/faiss/faiss/gpu/impl/IndexUtils.h +2 -5
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +9 -7
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +4 -4
- data/vendor/faiss/faiss/gpu/perf/IndexWrapper-inl.h +2 -2
- data/vendor/faiss/faiss/gpu/perf/IndexWrapper.h +1 -1
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +55 -6
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +20 -6
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +95 -25
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +67 -16
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +4 -4
- data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +7 -7
- data/vendor/faiss/faiss/gpu/test/TestUtils.h +4 -4
- data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +1 -1
- data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +6 -0
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +0 -7
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +9 -9
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +1 -1
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +2 -7
- data/vendor/faiss/faiss/impl/CodePacker.cpp +67 -0
- data/vendor/faiss/faiss/impl/CodePacker.h +71 -0
- data/vendor/faiss/faiss/impl/DistanceComputer.h +0 -2
- data/vendor/faiss/faiss/impl/HNSW.cpp +3 -7
- data/vendor/faiss/faiss/impl/HNSW.h +6 -9
- data/vendor/faiss/faiss/impl/IDSelector.cpp +1 -1
- data/vendor/faiss/faiss/impl/IDSelector.h +39 -1
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +62 -51
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +11 -12
- data/vendor/faiss/faiss/impl/NNDescent.cpp +3 -9
- data/vendor/faiss/faiss/impl/NNDescent.h +10 -10
- data/vendor/faiss/faiss/impl/NSG.cpp +1 -6
- data/vendor/faiss/faiss/impl/NSG.h +4 -7
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +1 -15
- data/vendor/faiss/faiss/impl/PolysemousTraining.h +11 -10
- data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +0 -7
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +25 -12
- data/vendor/faiss/faiss/impl/ProductQuantizer.h +2 -4
- data/vendor/faiss/faiss/impl/Quantizer.h +6 -3
- data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +796 -174
- data/vendor/faiss/faiss/impl/ResidualQuantizer.h +16 -8
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +3 -5
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +4 -4
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +3 -3
- data/vendor/faiss/faiss/impl/ThreadedIndex.h +4 -4
- data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +291 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +74 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance.h +123 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +102 -0
- data/vendor/faiss/faiss/impl/index_read.cpp +13 -10
- data/vendor/faiss/faiss/impl/index_write.cpp +3 -4
- data/vendor/faiss/faiss/impl/kmeans1d.cpp +0 -1
- data/vendor/faiss/faiss/impl/kmeans1d.h +3 -3
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -1
- data/vendor/faiss/faiss/impl/platform_macros.h +61 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +48 -4
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +18 -4
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +2 -2
- data/vendor/faiss/faiss/index_factory.cpp +8 -10
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +29 -12
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +8 -2
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
- data/vendor/faiss/faiss/invlists/DirectMap.h +2 -4
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +118 -18
- data/vendor/faiss/faiss/invlists/InvertedLists.h +44 -4
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +3 -3
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
- data/vendor/faiss/faiss/python/python_callbacks.cpp +1 -1
- data/vendor/faiss/faiss/python/python_callbacks.h +1 -1
- data/vendor/faiss/faiss/utils/AlignedTable.h +3 -1
- data/vendor/faiss/faiss/utils/Heap.cpp +139 -3
- data/vendor/faiss/faiss/utils/Heap.h +35 -1
- data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +84 -0
- data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +196 -0
- data/vendor/faiss/faiss/utils/approx_topk/generic.h +138 -0
- data/vendor/faiss/faiss/utils/approx_topk/mode.h +34 -0
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +367 -0
- data/vendor/faiss/faiss/utils/distances.cpp +61 -7
- data/vendor/faiss/faiss/utils/distances.h +11 -0
- data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +346 -0
- data/vendor/faiss/faiss/utils/distances_fused/avx512.h +36 -0
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +42 -0
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +40 -0
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +352 -0
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.h +32 -0
- data/vendor/faiss/faiss/utils/distances_simd.cpp +515 -327
- data/vendor/faiss/faiss/utils/extra_distances-inl.h +17 -1
- data/vendor/faiss/faiss/utils/extra_distances.cpp +37 -8
- data/vendor/faiss/faiss/utils/extra_distances.h +2 -1
- data/vendor/faiss/faiss/utils/fp16-fp16c.h +7 -0
- data/vendor/faiss/faiss/utils/fp16-inl.h +7 -0
- data/vendor/faiss/faiss/utils/fp16.h +7 -0
- data/vendor/faiss/faiss/utils/hamming-inl.h +0 -456
- data/vendor/faiss/faiss/utils/hamming.cpp +104 -120
- data/vendor/faiss/faiss/utils/hamming.h +21 -10
- data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +535 -0
- data/vendor/faiss/faiss/utils/hamming_distance/common.h +48 -0
- data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +519 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +26 -0
- data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +614 -0
- data/vendor/faiss/faiss/utils/partitioning.cpp +21 -25
- data/vendor/faiss/faiss/utils/simdlib_avx2.h +344 -3
- data/vendor/faiss/faiss/utils/simdlib_emulated.h +390 -0
- data/vendor/faiss/faiss/utils/simdlib_neon.h +655 -130
- data/vendor/faiss/faiss/utils/sorting.cpp +692 -0
- data/vendor/faiss/faiss/utils/sorting.h +71 -0
- data/vendor/faiss/faiss/utils/transpose/transpose-avx2-inl.h +165 -0
- data/vendor/faiss/faiss/utils/utils.cpp +4 -176
- data/vendor/faiss/faiss/utils/utils.h +2 -9
- metadata +29 -3
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.cpp +0 -26
@@ -18,7 +18,7 @@
|
|
18
18
|
#include <mutex>
|
19
19
|
#include <vector>
|
20
20
|
|
21
|
-
#include <faiss/
|
21
|
+
#include <faiss/MetricType.h>
|
22
22
|
#include <faiss/impl/platform_macros.h>
|
23
23
|
|
24
24
|
namespace faiss {
|
@@ -31,15 +31,13 @@ struct RangeSearchResult {
|
|
31
31
|
size_t nq; ///< nb of queries
|
32
32
|
size_t* lims; ///< size (nq + 1)
|
33
33
|
|
34
|
-
typedef Index::idx_t idx_t;
|
35
|
-
|
36
34
|
idx_t* labels; ///< result for query i is labels[lims[i]:lims[i+1]]
|
37
35
|
float* distances; ///< corresponding distances (not sorted)
|
38
36
|
|
39
37
|
size_t buffer_size; ///< size of the result buffers used
|
40
38
|
|
41
39
|
/// lims must be allocated on input to range_search.
|
42
|
-
explicit RangeSearchResult(
|
40
|
+
explicit RangeSearchResult(size_t nq, bool alloc_lims = true);
|
43
41
|
|
44
42
|
/// called when lims contains the nb of elements result entries
|
45
43
|
/// for each query
|
@@ -62,8 +60,6 @@ struct RangeSearchResult {
|
|
62
60
|
/** List of temporary buffers used to store results before they are
|
63
61
|
* copied to the RangeSearchResult object. */
|
64
62
|
struct BufferList {
|
65
|
-
typedef Index::idx_t idx_t;
|
66
|
-
|
67
63
|
// buffer sizes in # entries
|
68
64
|
size_t buffer_size;
|
69
65
|
|
@@ -94,7 +90,6 @@ struct RangeSearchPartialResult;
|
|
94
90
|
|
95
91
|
/// result structure for a single query
|
96
92
|
struct RangeQueryResult {
|
97
|
-
using idx_t = Index::idx_t;
|
98
93
|
idx_t qno; //< id of the query
|
99
94
|
size_t nres; //< nb of results for this query
|
100
95
|
RangeSearchPartialResult* pres;
|
@@ -0,0 +1,67 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
3
|
+
*
|
4
|
+
* This source code is licensed under the MIT license found in the
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include <faiss/impl/CodePacker.h>
|
9
|
+
|
10
|
+
#include <cassert>
|
11
|
+
#include <cstring>
|
12
|
+
|
13
|
+
namespace faiss {
|
14
|
+
|
15
|
+
/*********************************************
|
16
|
+
* CodePacker
|
17
|
+
* default of pack_all / unpack_all loops over the _1 versions
|
18
|
+
*/
|
19
|
+
|
20
|
+
void CodePacker::pack_all(const uint8_t* flat_codes, uint8_t* block) const {
|
21
|
+
for (size_t i = 0; i < nvec; i++) {
|
22
|
+
pack_1(flat_codes + code_size * i, i, block);
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
void CodePacker::unpack_all(const uint8_t* block, uint8_t* flat_codes) const {
|
27
|
+
for (size_t i = 0; i < nvec; i++) {
|
28
|
+
unpack_1(block, i, flat_codes + code_size * i);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
/*********************************************
|
33
|
+
* CodePackerFlat
|
34
|
+
*/
|
35
|
+
|
36
|
+
CodePackerFlat::CodePackerFlat(size_t code_size) {
|
37
|
+
this->code_size = code_size;
|
38
|
+
nvec = 1;
|
39
|
+
block_size = code_size;
|
40
|
+
}
|
41
|
+
|
42
|
+
void CodePackerFlat::pack_all(const uint8_t* flat_codes, uint8_t* block) const {
|
43
|
+
memcpy(block, flat_codes, code_size);
|
44
|
+
}
|
45
|
+
|
46
|
+
void CodePackerFlat::unpack_all(const uint8_t* block, uint8_t* flat_codes)
|
47
|
+
const {
|
48
|
+
memcpy(flat_codes, block, code_size);
|
49
|
+
}
|
50
|
+
|
51
|
+
void CodePackerFlat::pack_1(
|
52
|
+
const uint8_t* flat_code,
|
53
|
+
size_t offset,
|
54
|
+
uint8_t* block) const {
|
55
|
+
assert(offset == 0);
|
56
|
+
pack_all(flat_code, block);
|
57
|
+
}
|
58
|
+
|
59
|
+
void CodePackerFlat::unpack_1(
|
60
|
+
const uint8_t* block,
|
61
|
+
size_t offset,
|
62
|
+
uint8_t* flat_code) const {
|
63
|
+
assert(offset == 0);
|
64
|
+
unpack_all(block, flat_code);
|
65
|
+
}
|
66
|
+
|
67
|
+
} // namespace faiss
|
@@ -0,0 +1,71 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
3
|
+
*
|
4
|
+
* This source code is licensed under the MIT license found in the
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#pragma once
|
9
|
+
|
10
|
+
#include <faiss/MetricType.h>
|
11
|
+
|
12
|
+
namespace faiss {
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Packing consists in combining a fixed number of codes of constant size
|
16
|
+
* (code_size) into a block of data where they may (or may not) be interleaved
|
17
|
+
* for efficient consumption by distance computation kernels. This exists for
|
18
|
+
* the "fast_scan" indexes on CPU and for some GPU kernels.
|
19
|
+
*/
|
20
|
+
struct CodePacker {
|
21
|
+
size_t code_size; // input code size in bytes
|
22
|
+
size_t nvec; // number of vectors per block
|
23
|
+
size_t block_size; // size of one block in bytes (>= code_size * nvec)
|
24
|
+
|
25
|
+
// pack a single code to a block
|
26
|
+
virtual void pack_1(
|
27
|
+
const uint8_t*
|
28
|
+
flat_code, // code to write to the block, size code_size
|
29
|
+
size_t offset, // offset in the block (0 <= offset < nvec)
|
30
|
+
uint8_t* block // block to write to (size block_size)
|
31
|
+
) const = 0;
|
32
|
+
|
33
|
+
// unpack a single code from a block
|
34
|
+
virtual void unpack_1(
|
35
|
+
const uint8_t* block, // block to read from (size block_size)
|
36
|
+
size_t offset, // offset in the block (0 <= offset < nvec)
|
37
|
+
uint8_t* flat_code // where to write the resulting code, size
|
38
|
+
// code_size
|
39
|
+
) const = 0;
|
40
|
+
|
41
|
+
// pack all code in a block
|
42
|
+
virtual void pack_all(
|
43
|
+
const uint8_t* flat_codes, // codes to write to the block, size
|
44
|
+
// (nvec * code_size)
|
45
|
+
uint8_t* block // block to write to (size block_size)
|
46
|
+
) const;
|
47
|
+
|
48
|
+
// unpack all code in a block
|
49
|
+
virtual void unpack_all(
|
50
|
+
const uint8_t* block, // block to read from (size block_size)
|
51
|
+
uint8_t* flat_codes // where to write the resulting codes size (nvec
|
52
|
+
// * code_size)
|
53
|
+
) const;
|
54
|
+
|
55
|
+
virtual ~CodePacker() {}
|
56
|
+
};
|
57
|
+
|
58
|
+
/** Trivial code packer where codes are stored one by one */
|
59
|
+
struct CodePackerFlat : CodePacker {
|
60
|
+
explicit CodePackerFlat(size_t code_size);
|
61
|
+
|
62
|
+
void pack_1(const uint8_t* flat_code, size_t offset, uint8_t* block)
|
63
|
+
const final;
|
64
|
+
void unpack_1(const uint8_t* block, size_t offset, uint8_t* flat_code)
|
65
|
+
const final;
|
66
|
+
|
67
|
+
void pack_all(const uint8_t* flat_codes, uint8_t* block) const final;
|
68
|
+
void unpack_all(const uint8_t* block, uint8_t* flat_codes) const final;
|
69
|
+
};
|
70
|
+
|
71
|
+
} // namespace faiss
|
@@ -23,8 +23,6 @@ namespace faiss {
|
|
23
23
|
* that has additional methods to handle the inverted list context.
|
24
24
|
***********************************************************/
|
25
25
|
struct DistanceComputer {
|
26
|
-
using idx_t = Index::idx_t;
|
27
|
-
|
28
26
|
/// called before computing distances. Pointer x should remain valid
|
29
27
|
/// while operator () is called
|
30
28
|
virtual void set_query(const float* x) = 0;
|
@@ -47,11 +47,6 @@ void HNSW::neighbor_range(idx_t no, int layer_no, size_t* begin, size_t* end)
|
|
47
47
|
|
48
48
|
HNSW::HNSW(int M) : rng(12345) {
|
49
49
|
set_default_probas(M, 1.0 / log(M));
|
50
|
-
max_level = -1;
|
51
|
-
entry_point = -1;
|
52
|
-
efSearch = 16;
|
53
|
-
efConstruction = 40;
|
54
|
-
upper_beam = 1;
|
55
50
|
offsets.push_back(0);
|
56
51
|
}
|
57
52
|
|
@@ -509,7 +504,6 @@ void HNSW::add_with_locks(
|
|
509
504
|
|
510
505
|
namespace {
|
511
506
|
|
512
|
-
using idx_t = HNSW::idx_t;
|
513
507
|
using MinimaxHeap = HNSW::MinimaxHeap;
|
514
508
|
using Node = HNSW::Node;
|
515
509
|
/** Do a BFS on the candidates list */
|
@@ -837,8 +831,10 @@ void HNSW::MinimaxHeap::push(storage_idx_t i, float v) {
|
|
837
831
|
if (k == n) {
|
838
832
|
if (v >= dis[0])
|
839
833
|
return;
|
834
|
+
if (ids[0] != -1) {
|
835
|
+
--nvalid;
|
836
|
+
}
|
840
837
|
faiss::heap_pop<HC>(k--, dis.data(), ids.data());
|
841
|
-
--nvalid;
|
842
838
|
}
|
843
839
|
faiss::heap_push<HC>(++k, dis.data(), ids.data(), v, i);
|
844
840
|
++nvalid;
|
@@ -52,10 +52,7 @@ struct SearchParametersHNSW : SearchParameters {
|
|
52
52
|
|
53
53
|
struct HNSW {
|
54
54
|
/// internal storage of vectors (32 bits: this is expensive)
|
55
|
-
|
56
|
-
|
57
|
-
/// Faiss results are 64-bit
|
58
|
-
typedef Index::idx_t idx_t;
|
55
|
+
using storage_idx_t = int32_t;
|
59
56
|
|
60
57
|
typedef std::pair<float, storage_idx_t> Node;
|
61
58
|
|
@@ -124,25 +121,25 @@ struct HNSW {
|
|
124
121
|
|
125
122
|
/// entry point in the search structure (one of the points with maximum
|
126
123
|
/// level
|
127
|
-
storage_idx_t entry_point;
|
124
|
+
storage_idx_t entry_point = -1;
|
128
125
|
|
129
126
|
faiss::RandomGenerator rng;
|
130
127
|
|
131
128
|
/// maximum level
|
132
|
-
int max_level;
|
129
|
+
int max_level = -1;
|
133
130
|
|
134
131
|
/// expansion factor at construction time
|
135
|
-
int efConstruction;
|
132
|
+
int efConstruction = 40;
|
136
133
|
|
137
134
|
/// expansion factor at search time
|
138
|
-
int efSearch;
|
135
|
+
int efSearch = 16;
|
139
136
|
|
140
137
|
/// during search: do we check whether the next best distance is good
|
141
138
|
/// enough?
|
142
139
|
bool check_relative_distance = true;
|
143
140
|
|
144
141
|
/// number of entry points in levels > 0.
|
145
|
-
int upper_beam;
|
142
|
+
int upper_beam = 1;
|
146
143
|
|
147
144
|
/// use bounded queue during exploration
|
148
145
|
bool search_bounded_queue = true;
|
@@ -92,7 +92,7 @@ IDSelectorBatch::IDSelectorBatch(size_t n, const idx_t* indices) {
|
|
92
92
|
mask = ((idx_t)1 << nbits) - 1;
|
93
93
|
bloom.resize((idx_t)1 << (nbits - 3), 0);
|
94
94
|
for (idx_t i = 0; i < n; i++) {
|
95
|
-
|
95
|
+
idx_t id = indices[i];
|
96
96
|
set.insert(id);
|
97
97
|
id &= mask;
|
98
98
|
bloom[id >> 3] |= 1 << (id & 7);
|
@@ -19,7 +19,6 @@ namespace faiss {
|
|
19
19
|
|
20
20
|
/** Encapsulates a set of ids to handle. */
|
21
21
|
struct IDSelector {
|
22
|
-
using idx_t = Index::idx_t;
|
23
22
|
virtual bool is_member(idx_t id) const = 0;
|
24
23
|
virtual ~IDSelector() {}
|
25
24
|
};
|
@@ -132,4 +131,43 @@ struct IDSelectorAll : IDSelector {
|
|
132
131
|
virtual ~IDSelectorAll() {}
|
133
132
|
};
|
134
133
|
|
134
|
+
/// does an AND operation on the the two given IDSelector's is_membership
|
135
|
+
/// results.
|
136
|
+
struct IDSelectorAnd : IDSelector {
|
137
|
+
const IDSelector* lhs;
|
138
|
+
const IDSelector* rhs;
|
139
|
+
IDSelectorAnd(const IDSelector* lhs, const IDSelector* rhs)
|
140
|
+
: lhs(lhs), rhs(rhs) {}
|
141
|
+
bool is_member(idx_t id) const final {
|
142
|
+
return lhs->is_member(id) && rhs->is_member(id);
|
143
|
+
};
|
144
|
+
virtual ~IDSelectorAnd() {}
|
145
|
+
};
|
146
|
+
|
147
|
+
/// does an OR operation on the the two given IDSelector's is_membership
|
148
|
+
/// results.
|
149
|
+
struct IDSelectorOr : IDSelector {
|
150
|
+
const IDSelector* lhs;
|
151
|
+
const IDSelector* rhs;
|
152
|
+
IDSelectorOr(const IDSelector* lhs, const IDSelector* rhs)
|
153
|
+
: lhs(lhs), rhs(rhs) {}
|
154
|
+
bool is_member(idx_t id) const final {
|
155
|
+
return lhs->is_member(id) || rhs->is_member(id);
|
156
|
+
};
|
157
|
+
virtual ~IDSelectorOr() {}
|
158
|
+
};
|
159
|
+
|
160
|
+
/// does an XOR operation on the the two given IDSelector's is_membership
|
161
|
+
/// results.
|
162
|
+
struct IDSelectorXOr : IDSelector {
|
163
|
+
const IDSelector* lhs;
|
164
|
+
const IDSelector* rhs;
|
165
|
+
IDSelectorXOr(const IDSelector* lhs, const IDSelector* rhs)
|
166
|
+
: lhs(lhs), rhs(rhs) {}
|
167
|
+
bool is_member(idx_t id) const final {
|
168
|
+
return lhs->is_member(id) ^ rhs->is_member(id);
|
169
|
+
};
|
170
|
+
virtual ~IDSelectorXOr() {}
|
171
|
+
};
|
172
|
+
|
135
173
|
} // namespace faiss
|
@@ -21,6 +21,15 @@
|
|
21
21
|
#include <faiss/utils/hamming.h> // BitstringWriter
|
22
22
|
#include <faiss/utils/utils.h>
|
23
23
|
|
24
|
+
#include <faiss/utils/approx_topk/approx_topk.h>
|
25
|
+
|
26
|
+
// this is needed for prefetching
|
27
|
+
#include <faiss/impl/platform_macros.h>
|
28
|
+
|
29
|
+
#ifdef __AVX2__
|
30
|
+
#include <xmmintrin.h>
|
31
|
+
#endif
|
32
|
+
|
24
33
|
extern "C" {
|
25
34
|
// LU decomoposition of a general matrix
|
26
35
|
void sgetrf_(
|
@@ -151,23 +160,7 @@ LocalSearchQuantizer::LocalSearchQuantizer(
|
|
151
160
|
Search_type_t search_type)
|
152
161
|
: AdditiveQuantizer(d, std::vector<size_t>(M, nbits), search_type) {
|
153
162
|
K = (1 << nbits);
|
154
|
-
|
155
|
-
train_iters = 25;
|
156
|
-
train_ils_iters = 8;
|
157
|
-
icm_iters = 4;
|
158
|
-
|
159
|
-
encode_ils_iters = 16;
|
160
|
-
|
161
|
-
p = 0.5f;
|
162
|
-
lambd = 1e-2f;
|
163
|
-
|
164
|
-
chunk_size = 10000;
|
165
|
-
nperts = 4;
|
166
|
-
|
167
|
-
random_seed = 0x12345;
|
168
163
|
std::srand(random_seed);
|
169
|
-
|
170
|
-
icm_encoder_factory = nullptr;
|
171
164
|
}
|
172
165
|
|
173
166
|
LocalSearchQuantizer::~LocalSearchQuantizer() {
|
@@ -192,7 +185,7 @@ void LocalSearchQuantizer::train(size_t n, const float* x) {
|
|
192
185
|
// allocate memory for codebooks, size [M, K, d]
|
193
186
|
codebooks.resize(M * K * d);
|
194
187
|
|
195
|
-
// randomly
|
188
|
+
// randomly initialize codes
|
196
189
|
std::mt19937 gen(random_seed);
|
197
190
|
std::vector<int32_t> codes(n * M); // [n, M]
|
198
191
|
random_int32(codes, 0, K - 1, gen);
|
@@ -604,54 +597,72 @@ void LocalSearchQuantizer::icm_encode_step(
|
|
604
597
|
FAISS_THROW_IF_NOT(M != 0 && K != 0);
|
605
598
|
FAISS_THROW_IF_NOT(binaries != nullptr);
|
606
599
|
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
std::vector<float> objs(n * K);
|
611
|
-
#pragma omp parallel for
|
612
|
-
for (int64_t i = 0; i < n; i++) {
|
613
|
-
auto u = unaries + m * n * K + i * K;
|
614
|
-
memcpy(objs.data() + i * K, u, sizeof(float) * K);
|
615
|
-
}
|
600
|
+
#pragma omp parallel for schedule(dynamic)
|
601
|
+
for (int64_t i = 0; i < n; i++) {
|
602
|
+
std::vector<float> objs(K);
|
616
603
|
|
617
|
-
|
618
|
-
//
|
619
|
-
for (size_t
|
620
|
-
|
621
|
-
|
604
|
+
for (size_t iter = 0; iter < n_iters; iter++) {
|
605
|
+
// condition on the m-th subcode
|
606
|
+
for (size_t m = 0; m < M; m++) {
|
607
|
+
// copy
|
608
|
+
auto u = unaries + m * n * K + i * K;
|
609
|
+
for (size_t code = 0; code < K; code++) {
|
610
|
+
objs[code] = u[code];
|
622
611
|
}
|
623
612
|
|
624
|
-
|
625
|
-
|
613
|
+
// compute objective function by adding unary
|
614
|
+
// and binary terms together
|
615
|
+
for (size_t other_m = 0; other_m < M; other_m++) {
|
616
|
+
if (other_m == m) {
|
617
|
+
continue;
|
618
|
+
}
|
619
|
+
|
620
|
+
#ifdef __AVX2__
|
621
|
+
// TODO: add platform-independent compiler-independent
|
622
|
+
// prefetch utilities.
|
623
|
+
if (other_m + 1 < M) {
|
624
|
+
// do a single prefetch
|
625
|
+
int32_t code2 = codes[i * M + other_m + 1];
|
626
|
+
// for (int32_t code = 0; code < K; code += 64) {
|
627
|
+
int32_t code = 0;
|
628
|
+
{
|
629
|
+
size_t binary_idx = (other_m + 1) * M * K * K +
|
630
|
+
m * K * K + code2 * K + code;
|
631
|
+
_mm_prefetch(binaries + binary_idx, _MM_HINT_T0);
|
632
|
+
}
|
633
|
+
}
|
634
|
+
#endif
|
635
|
+
|
626
636
|
for (int32_t code = 0; code < K; code++) {
|
627
637
|
int32_t code2 = codes[i * M + other_m];
|
628
|
-
size_t binary_idx =
|
629
|
-
|
630
|
-
// binaries[m, other_m, code, code2]
|
631
|
-
|
638
|
+
size_t binary_idx = other_m * M * K * K + m * K * K +
|
639
|
+
code2 * K + code;
|
640
|
+
// binaries[m, other_m, code, code2].
|
641
|
+
// It is symmetric over (m <-> other_m)
|
642
|
+
// and (code <-> code2).
|
643
|
+
// So, replace the op with
|
644
|
+
// binaries[other_m, m, code2, code].
|
645
|
+
objs[code] += binaries[binary_idx];
|
632
646
|
}
|
633
647
|
}
|
634
|
-
}
|
635
648
|
|
636
|
-
|
637
|
-
#pragma omp parallel for
|
638
|
-
for (int64_t i = 0; i < n; i++) {
|
649
|
+
// find the optimal value of the m-th subcode
|
639
650
|
float best_obj = HUGE_VALF;
|
640
651
|
int32_t best_code = 0;
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
652
|
+
|
653
|
+
// find one using SIMD. The following operation is similar
|
654
|
+
// to the search of the smallest element in objs
|
655
|
+
using C = CMax<float, int>;
|
656
|
+
HeapWithBuckets<C, 16, 1>::addn(
|
657
|
+
K, objs.data(), 1, &best_obj, &best_code);
|
658
|
+
|
659
|
+
// done
|
648
660
|
codes[i * M + m] = best_code;
|
649
|
-
}
|
650
661
|
|
651
|
-
|
662
|
+
} // loop M
|
663
|
+
}
|
652
664
|
}
|
653
665
|
}
|
654
|
-
|
655
666
|
void LocalSearchQuantizer::perturb_codes(
|
656
667
|
int32_t* codes,
|
657
668
|
size_t n,
|
@@ -45,22 +45,21 @@ struct IcmEncoderFactory;
|
|
45
45
|
struct LocalSearchQuantizer : AdditiveQuantizer {
|
46
46
|
size_t K; ///< number of codes per codebook
|
47
47
|
|
48
|
-
size_t train_iters;
|
48
|
+
size_t train_iters = 25; ///< number of iterations in training
|
49
|
+
size_t encode_ils_iters = 16; ///< iterations of local search in encoding
|
50
|
+
size_t train_ils_iters = 8; ///< iterations of local search in training
|
51
|
+
size_t icm_iters = 4; ///< number of iterations in icm
|
49
52
|
|
50
|
-
|
51
|
-
|
52
|
-
size_t icm_iters; ///< number of iterations in icm
|
53
|
+
float p = 0.5f; ///< temperature factor
|
54
|
+
float lambd = 1e-2f; ///< regularization factor
|
53
55
|
|
54
|
-
|
55
|
-
float lambd; ///< regularization factor
|
56
|
+
size_t chunk_size = 10000; ///< nb of vectors to encode at a time
|
56
57
|
|
57
|
-
|
58
|
+
int random_seed = 0x12345; ///< seed for random generator
|
59
|
+
size_t nperts = 4; ///< number of perturbation in each code
|
58
60
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
///< if non-NULL, use this encoder to encode
|
63
|
-
lsq::IcmEncoderFactory* icm_encoder_factory;
|
61
|
+
///< if non-NULL, use this encoder to encode (owned by the object)
|
62
|
+
lsq::IcmEncoderFactory* icm_encoder_factory = nullptr;
|
64
63
|
|
65
64
|
bool update_codebooks_with_double = true;
|
66
65
|
|
@@ -147,14 +147,8 @@ using namespace nndescent;
|
|
147
147
|
|
148
148
|
constexpr int NUM_EVAL_POINTS = 100;
|
149
149
|
|
150
|
-
NNDescent::NNDescent(const int d, const int K) : K(K),
|
151
|
-
ntotal = 0;
|
152
|
-
has_built = false;
|
153
|
-
S = 10;
|
154
|
-
R = 100;
|
150
|
+
NNDescent::NNDescent(const int d, const int K) : K(K), d(d) {
|
155
151
|
L = K + 50;
|
156
|
-
iter = 10;
|
157
|
-
search_L = 0;
|
158
152
|
}
|
159
153
|
|
160
154
|
NNDescent::~NNDescent() {}
|
@@ -311,7 +305,7 @@ void NNDescent::generate_eval_set(
|
|
311
305
|
for (int i = 0; i < c.size(); i++) {
|
312
306
|
std::vector<Neighbor> tmp;
|
313
307
|
for (int j = 0; j < N; j++) {
|
314
|
-
if (i == j)
|
308
|
+
if (c[i] == j)
|
315
309
|
continue; // skip itself
|
316
310
|
float dist = qdis.symmetric_dis(c[i], j);
|
317
311
|
tmp.push_back(Neighbor(j, dist, true));
|
@@ -425,7 +419,7 @@ void NNDescent::search(
|
|
425
419
|
// candidate pool, the K best items is the result.
|
426
420
|
std::vector<Neighbor> retset(L + 1);
|
427
421
|
|
428
|
-
// Randomly choose L points to
|
422
|
+
// Randomly choose L points to initialize the candidate pool
|
429
423
|
std::vector<int> init_ids(L);
|
430
424
|
std::mt19937 rng(random_seed);
|
431
425
|
|
@@ -90,7 +90,6 @@ struct Nhood {
|
|
90
90
|
|
91
91
|
struct NNDescent {
|
92
92
|
using storage_idx_t = int;
|
93
|
-
using idx_t = Index::idx_t;
|
94
93
|
|
95
94
|
using KNNGraph = std::vector<nndescent::Nhood>;
|
96
95
|
|
@@ -133,19 +132,20 @@ struct NNDescent {
|
|
133
132
|
std::vector<int>& ctrl_points,
|
134
133
|
std::vector<std::vector<int>>& acc_eval_set);
|
135
134
|
|
136
|
-
bool has_built;
|
135
|
+
bool has_built = false;
|
137
136
|
|
138
|
-
int
|
139
|
-
int
|
140
|
-
|
141
|
-
int
|
142
|
-
int
|
143
|
-
int
|
144
|
-
int random_seed; // random seed for generators
|
137
|
+
int S = 10; // number of sample neighbors to be updated for each node
|
138
|
+
int R = 100; // size of reverse links, 0 means the reverse links will not be
|
139
|
+
// used
|
140
|
+
int iter = 10; // number of iterations to iterate over
|
141
|
+
int search_L = 0; // size of candidate pool in searching
|
142
|
+
int random_seed = 2021; // random seed for generators
|
145
143
|
|
144
|
+
int K; // K in KNN graph
|
146
145
|
int d; // dimensions
|
146
|
+
int L; // size of the candidate pool in building
|
147
147
|
|
148
|
-
int ntotal;
|
148
|
+
int ntotal = 0;
|
149
149
|
|
150
150
|
KNNGraph graph;
|
151
151
|
std::vector<int> final_graph;
|
@@ -29,8 +29,6 @@ constexpr int EMPTY_ID = -1;
|
|
29
29
|
distances. This makes supporting INNER_PRODUCE search easier */
|
30
30
|
|
31
31
|
struct NegativeDistanceComputer : DistanceComputer {
|
32
|
-
using idx_t = Index::idx_t;
|
33
|
-
|
34
32
|
/// owned by this
|
35
33
|
DistanceComputer* basedis;
|
36
34
|
|
@@ -59,7 +57,7 @@ struct NegativeDistanceComputer : DistanceComputer {
|
|
59
57
|
} // namespace
|
60
58
|
|
61
59
|
DistanceComputer* storage_distance_computer(const Index* storage) {
|
62
|
-
if (storage->metric_type
|
60
|
+
if (is_similarity_metric(storage->metric_type)) {
|
63
61
|
return new NegativeDistanceComputer(storage->get_distance_computer());
|
64
62
|
} else {
|
65
63
|
return storage->get_distance_computer();
|
@@ -140,9 +138,6 @@ inline int insert_into_pool(Neighbor* addr, int K, Neighbor nn) {
|
|
140
138
|
NSG::NSG(int R) : R(R), rng(0x0903) {
|
141
139
|
L = R + 32;
|
142
140
|
C = R + 100;
|
143
|
-
search_L = 16;
|
144
|
-
ntotal = 0;
|
145
|
-
is_built = false;
|
146
141
|
srand(0x1998);
|
147
142
|
}
|
148
143
|
|
@@ -98,12 +98,9 @@ DistanceComputer* storage_distance_computer(const Index* storage);
|
|
98
98
|
|
99
99
|
struct NSG {
|
100
100
|
/// internal storage of vectors (32 bits: this is expensive)
|
101
|
-
using storage_idx_t =
|
101
|
+
using storage_idx_t = int32_t;
|
102
102
|
|
103
|
-
|
104
|
-
using idx_t = Index::idx_t;
|
105
|
-
|
106
|
-
int ntotal; ///< nb of nodes
|
103
|
+
int ntotal = 0; ///< nb of nodes
|
107
104
|
|
108
105
|
// construction-time parameters
|
109
106
|
int R; ///< nb of neighbors per node
|
@@ -111,13 +108,13 @@ struct NSG {
|
|
111
108
|
int C; ///< candidate pool size at construction time
|
112
109
|
|
113
110
|
// search-time parameters
|
114
|
-
int search_L; ///< length of the search path
|
111
|
+
int search_L = 16; ///< length of the search path
|
115
112
|
|
116
113
|
int enterpoint; ///< enterpoint
|
117
114
|
|
118
115
|
std::shared_ptr<nsg::Graph<int>> final_graph; ///< NSG graph structure
|
119
116
|
|
120
|
-
bool is_built; ///< NSG is built or not
|
117
|
+
bool is_built = false; ///< NSG is built or not
|
121
118
|
|
122
119
|
RandomGenerator rng; ///< random generator
|
123
120
|
|