faiss 0.3.0 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/ext/faiss/extconf.rb +9 -2
- data/ext/faiss/index.cpp +1 -1
- data/ext/faiss/index_binary.cpp +2 -2
- data/ext/faiss/product_quantizer.cpp +1 -1
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +7 -7
- data/vendor/faiss/faiss/AutoTune.h +1 -2
- data/vendor/faiss/faiss/Clustering.cpp +39 -22
- data/vendor/faiss/faiss/Clustering.h +40 -21
- data/vendor/faiss/faiss/IVFlib.cpp +26 -12
- data/vendor/faiss/faiss/Index.cpp +1 -1
- data/vendor/faiss/faiss/Index.h +40 -10
- data/vendor/faiss/faiss/Index2Layer.cpp +7 -7
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +176 -166
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +15 -15
- data/vendor/faiss/faiss/IndexBinary.cpp +9 -4
- data/vendor/faiss/faiss/IndexBinary.h +8 -19
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +2 -1
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +24 -31
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +1 -1
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +25 -50
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +107 -188
- data/vendor/faiss/faiss/IndexFastScan.cpp +95 -146
- data/vendor/faiss/faiss/IndexFastScan.h +9 -8
- data/vendor/faiss/faiss/IndexFlat.cpp +206 -10
- data/vendor/faiss/faiss/IndexFlat.h +20 -1
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +170 -5
- data/vendor/faiss/faiss/IndexFlatCodes.h +23 -4
- data/vendor/faiss/faiss/IndexHNSW.cpp +231 -382
- data/vendor/faiss/faiss/IndexHNSW.h +62 -49
- data/vendor/faiss/faiss/IndexIDMap.cpp +69 -28
- data/vendor/faiss/faiss/IndexIDMap.h +24 -2
- data/vendor/faiss/faiss/IndexIVF.cpp +162 -56
- data/vendor/faiss/faiss/IndexIVF.h +46 -6
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +33 -26
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +6 -2
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +19 -46
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +4 -3
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +502 -401
- data/vendor/faiss/faiss/IndexIVFFastScan.h +63 -26
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +15 -5
- data/vendor/faiss/faiss/IndexIVFFlat.h +3 -2
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +172 -0
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.h +56 -0
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +79 -125
- data/vendor/faiss/faiss/IndexIVFPQ.h +6 -7
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +39 -52
- data/vendor/faiss/faiss/IndexIVFPQFastScan.h +4 -3
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +45 -29
- data/vendor/faiss/faiss/IndexIVFPQR.h +5 -2
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +25 -27
- data/vendor/faiss/faiss/IndexIVFSpectralHash.h +6 -6
- data/vendor/faiss/faiss/IndexLSH.cpp +14 -16
- data/vendor/faiss/faiss/IndexLattice.cpp +1 -19
- data/vendor/faiss/faiss/IndexLattice.h +3 -22
- data/vendor/faiss/faiss/IndexNNDescent.cpp +3 -33
- data/vendor/faiss/faiss/IndexNNDescent.h +1 -1
- data/vendor/faiss/faiss/IndexNSG.cpp +11 -27
- data/vendor/faiss/faiss/IndexNSG.h +11 -11
- data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +56 -0
- data/vendor/faiss/faiss/IndexNeuralNetCodec.h +49 -0
- data/vendor/faiss/faiss/IndexPQ.cpp +72 -88
- data/vendor/faiss/faiss/IndexPQ.h +1 -4
- data/vendor/faiss/faiss/IndexPQFastScan.cpp +1 -1
- data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -31
- data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
- data/vendor/faiss/faiss/IndexRefine.cpp +54 -24
- data/vendor/faiss/faiss/IndexRefine.h +7 -0
- data/vendor/faiss/faiss/IndexReplicas.cpp +23 -26
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +25 -17
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +6 -4
- data/vendor/faiss/faiss/IndexShards.cpp +21 -29
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +1 -2
- data/vendor/faiss/faiss/MatrixStats.cpp +17 -32
- data/vendor/faiss/faiss/MatrixStats.h +21 -9
- data/vendor/faiss/faiss/MetaIndexes.cpp +35 -35
- data/vendor/faiss/faiss/MetricType.h +7 -2
- data/vendor/faiss/faiss/VectorTransform.cpp +13 -26
- data/vendor/faiss/faiss/VectorTransform.h +7 -7
- data/vendor/faiss/faiss/clone_index.cpp +15 -10
- data/vendor/faiss/faiss/clone_index.h +3 -0
- data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +95 -17
- data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +152 -0
- data/vendor/faiss/faiss/cppcontrib/factory_tools.h +24 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +83 -30
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +123 -8
- data/vendor/faiss/faiss/gpu/GpuCloner.h +22 -0
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +13 -0
- data/vendor/faiss/faiss/gpu/GpuDistance.h +46 -38
- data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -1
- data/vendor/faiss/faiss/gpu/GpuIndex.h +30 -12
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +282 -0
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +4 -4
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +14 -9
- data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +20 -3
- data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +22 -11
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +1 -3
- data/vendor/faiss/faiss/gpu/GpuResources.cpp +24 -3
- data/vendor/faiss/faiss/gpu/GpuResources.h +39 -11
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +142 -17
- data/vendor/faiss/faiss/gpu/StandardGpuResources.h +57 -3
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +26 -21
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +7 -1
- data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +8 -5
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +25 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +129 -9
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +332 -40
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +299 -208
- data/vendor/faiss/faiss/gpu/test/TestGpuMemoryException.cpp +1 -0
- 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/gpu/utils/RaftUtils.h +75 -0
- data/vendor/faiss/faiss/gpu/utils/Timer.cpp +4 -1
- data/vendor/faiss/faiss/gpu/utils/Timer.h +1 -1
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +3 -1
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +5 -5
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +26 -1
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +10 -3
- data/vendor/faiss/faiss/impl/DistanceComputer.h +70 -1
- data/vendor/faiss/faiss/impl/FaissAssert.h +4 -2
- data/vendor/faiss/faiss/impl/FaissException.h +13 -34
- data/vendor/faiss/faiss/impl/HNSW.cpp +605 -186
- data/vendor/faiss/faiss/impl/HNSW.h +52 -30
- data/vendor/faiss/faiss/impl/IDSelector.h +4 -4
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +11 -9
- data/vendor/faiss/faiss/impl/LookupTableScaler.h +34 -0
- data/vendor/faiss/faiss/impl/NNDescent.cpp +42 -27
- data/vendor/faiss/faiss/impl/NSG.cpp +0 -29
- data/vendor/faiss/faiss/impl/NSG.h +1 -1
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +14 -12
- data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +1 -1
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +25 -22
- data/vendor/faiss/faiss/impl/ProductQuantizer.h +6 -2
- data/vendor/faiss/faiss/impl/Quantizer.h +1 -1
- data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +27 -1015
- data/vendor/faiss/faiss/impl/ResidualQuantizer.h +5 -63
- data/vendor/faiss/faiss/impl/ResultHandler.h +347 -172
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +1104 -147
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +3 -8
- data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +285 -42
- data/vendor/faiss/faiss/impl/code_distance/code_distance-avx512.h +248 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +21 -14
- data/vendor/faiss/faiss/impl/code_distance/code_distance.h +22 -12
- data/vendor/faiss/faiss/impl/index_read.cpp +74 -34
- data/vendor/faiss/faiss/impl/index_read_utils.h +37 -0
- data/vendor/faiss/faiss/impl/index_write.cpp +88 -51
- data/vendor/faiss/faiss/impl/io.cpp +23 -15
- data/vendor/faiss/faiss/impl/io.h +4 -4
- data/vendor/faiss/faiss/impl/io_macros.h +6 -0
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -1
- data/vendor/faiss/faiss/impl/platform_macros.h +40 -1
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +14 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +7 -6
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +52 -38
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +487 -49
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +960 -0
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +176 -0
- data/vendor/faiss/faiss/impl/simd_result_handlers.h +481 -225
- data/vendor/faiss/faiss/index_factory.cpp +41 -20
- data/vendor/faiss/faiss/index_io.h +12 -5
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +28 -8
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +3 -0
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +10 -2
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +73 -17
- data/vendor/faiss/faiss/invlists/InvertedLists.h +26 -8
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +24 -9
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +2 -1
- data/vendor/faiss/faiss/python/python_callbacks.cpp +4 -4
- data/vendor/faiss/faiss/utils/Heap.cpp +3 -1
- data/vendor/faiss/faiss/utils/Heap.h +105 -0
- data/vendor/faiss/faiss/utils/NeuralNet.cpp +342 -0
- data/vendor/faiss/faiss/utils/NeuralNet.h +147 -0
- data/vendor/faiss/faiss/utils/WorkerThread.h +1 -0
- data/vendor/faiss/faiss/utils/bf16.h +36 -0
- data/vendor/faiss/faiss/utils/distances.cpp +147 -123
- data/vendor/faiss/faiss/utils/distances.h +86 -9
- data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +5 -5
- data/vendor/faiss/faiss/utils/distances_fused/avx512.h +2 -2
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +2 -2
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +1 -1
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +5 -5
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.h +1 -1
- data/vendor/faiss/faiss/utils/distances_simd.cpp +1589 -243
- data/vendor/faiss/faiss/utils/extra_distances-inl.h +70 -0
- data/vendor/faiss/faiss/utils/extra_distances.cpp +85 -137
- data/vendor/faiss/faiss/utils/extra_distances.h +3 -2
- data/vendor/faiss/faiss/utils/fp16-arm.h +29 -0
- data/vendor/faiss/faiss/utils/fp16.h +2 -0
- data/vendor/faiss/faiss/utils/hamming.cpp +163 -111
- data/vendor/faiss/faiss/utils/hamming.h +58 -0
- data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +16 -89
- data/vendor/faiss/faiss/utils/hamming_distance/common.h +1 -0
- data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +19 -88
- data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +58 -0
- data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +14 -104
- data/vendor/faiss/faiss/utils/partitioning.cpp +3 -4
- data/vendor/faiss/faiss/utils/prefetch.h +77 -0
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +0 -14
- data/vendor/faiss/faiss/utils/random.cpp +43 -0
- data/vendor/faiss/faiss/utils/random.h +25 -0
- data/vendor/faiss/faiss/utils/simdlib.h +10 -1
- data/vendor/faiss/faiss/utils/simdlib_avx2.h +0 -6
- data/vendor/faiss/faiss/utils/simdlib_avx512.h +296 -0
- data/vendor/faiss/faiss/utils/simdlib_neon.h +77 -79
- data/vendor/faiss/faiss/utils/simdlib_ppc64.h +1084 -0
- data/vendor/faiss/faiss/utils/sorting.cpp +140 -5
- data/vendor/faiss/faiss/utils/sorting.h +27 -0
- data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +176 -0
- data/vendor/faiss/faiss/utils/utils.cpp +120 -7
- data/vendor/faiss/faiss/utils/utils.h +60 -20
- metadata +23 -4
- data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +0 -102
@@ -24,29 +24,29 @@ namespace faiss {
|
|
24
24
|
* link structure built on top */
|
25
25
|
|
26
26
|
struct IndexNSG : Index {
|
27
|
-
/// the link
|
27
|
+
/// the link structure
|
28
28
|
NSG nsg;
|
29
29
|
|
30
30
|
/// the sequential storage
|
31
|
-
bool own_fields;
|
32
|
-
Index* storage;
|
31
|
+
bool own_fields = false;
|
32
|
+
Index* storage = nullptr;
|
33
33
|
|
34
34
|
/// the index is built or not
|
35
|
-
bool is_built;
|
35
|
+
bool is_built = false;
|
36
36
|
|
37
37
|
/// K of KNN graph for building
|
38
|
-
int GK;
|
38
|
+
int GK = 64;
|
39
39
|
|
40
40
|
/// indicate how to build a knn graph
|
41
41
|
/// - 0: build NSG with brute force search
|
42
42
|
/// - 1: build NSG with NNDescent
|
43
|
-
char build_type;
|
43
|
+
char build_type = 0;
|
44
44
|
|
45
45
|
/// parameters for nndescent
|
46
|
-
int nndescent_S;
|
47
|
-
int nndescent_R;
|
48
|
-
int nndescent_L;
|
49
|
-
int nndescent_iter;
|
46
|
+
int nndescent_S = 10;
|
47
|
+
int nndescent_R = 100;
|
48
|
+
int nndescent_L; // set to GK + 50
|
49
|
+
int nndescent_iter = 10;
|
50
50
|
|
51
51
|
explicit IndexNSG(int d = 0, int R = 32, MetricType metric = METRIC_L2);
|
52
52
|
explicit IndexNSG(Index* storage, int R = 32);
|
@@ -90,7 +90,7 @@ struct IndexNSGFlat : IndexNSG {
|
|
90
90
|
*/
|
91
91
|
struct IndexNSGPQ : IndexNSG {
|
92
92
|
IndexNSGPQ();
|
93
|
-
IndexNSGPQ(int d, int pq_m, int M);
|
93
|
+
IndexNSGPQ(int d, int pq_m, int M, int pq_nbits = 8);
|
94
94
|
void train(idx_t n, const float* x) override;
|
95
95
|
};
|
96
96
|
|
@@ -0,0 +1,56 @@
|
|
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/IndexNeuralNetCodec.h>
|
9
|
+
#include <faiss/impl/FaissAssert.h>
|
10
|
+
#include <faiss/utils/hamming.h>
|
11
|
+
|
12
|
+
namespace faiss {
|
13
|
+
|
14
|
+
/*********************************************************
|
15
|
+
* IndexNeuralNetCodec implementation
|
16
|
+
*********************************************************/
|
17
|
+
|
18
|
+
IndexNeuralNetCodec::IndexNeuralNetCodec(
|
19
|
+
int d,
|
20
|
+
int M,
|
21
|
+
int nbits,
|
22
|
+
MetricType metric)
|
23
|
+
: IndexFlatCodes((M * nbits + 7) / 8, d, metric), M(M), nbits(nbits) {
|
24
|
+
is_trained = false;
|
25
|
+
}
|
26
|
+
|
27
|
+
void IndexNeuralNetCodec::train(idx_t n, const float* x) {
|
28
|
+
FAISS_THROW_MSG("Training not implemented in C++, use Pytorch");
|
29
|
+
}
|
30
|
+
|
31
|
+
void IndexNeuralNetCodec::sa_encode(idx_t n, const float* x, uint8_t* codes)
|
32
|
+
const {
|
33
|
+
nn::Tensor2D x_tensor(n, d, x);
|
34
|
+
nn::Int32Tensor2D codes_tensor = net->encode(x_tensor);
|
35
|
+
pack_bitstrings(n, M, nbits, codes_tensor.data(), codes, code_size);
|
36
|
+
}
|
37
|
+
|
38
|
+
void IndexNeuralNetCodec::sa_decode(idx_t n, const uint8_t* codes, float* x)
|
39
|
+
const {
|
40
|
+
nn::Int32Tensor2D codes_tensor(n, M);
|
41
|
+
unpack_bitstrings(n, M, nbits, codes, code_size, codes_tensor.data());
|
42
|
+
nn::Tensor2D x_tensor = net->decode(codes_tensor);
|
43
|
+
memcpy(x, x_tensor.data(), d * n * sizeof(float));
|
44
|
+
}
|
45
|
+
|
46
|
+
/*********************************************************
|
47
|
+
* IndexQINeuralNetCodec implementation
|
48
|
+
*********************************************************/
|
49
|
+
|
50
|
+
IndexQINCo::IndexQINCo(int d, int M, int nbits, int L, int h, MetricType metric)
|
51
|
+
: IndexNeuralNetCodec(d, M, nbits, metric),
|
52
|
+
qinco(d, 1 << nbits, L, M, h) {
|
53
|
+
net = &qinco;
|
54
|
+
}
|
55
|
+
|
56
|
+
} // namespace faiss
|
@@ -0,0 +1,49 @@
|
|
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 <vector>
|
11
|
+
|
12
|
+
#include <faiss/IndexFlatCodes.h>
|
13
|
+
#include <faiss/utils/NeuralNet.h>
|
14
|
+
|
15
|
+
namespace faiss {
|
16
|
+
|
17
|
+
struct IndexNeuralNetCodec : IndexFlatCodes {
|
18
|
+
NeuralNetCodec* net = nullptr;
|
19
|
+
size_t M, nbits;
|
20
|
+
|
21
|
+
explicit IndexNeuralNetCodec(
|
22
|
+
int d = 0,
|
23
|
+
int M = 0,
|
24
|
+
int nbits = 0,
|
25
|
+
MetricType metric = METRIC_L2);
|
26
|
+
|
27
|
+
void train(idx_t n, const float* x) override;
|
28
|
+
|
29
|
+
void sa_encode(idx_t n, const float* x, uint8_t* codes) const override;
|
30
|
+
void sa_decode(idx_t n, const uint8_t* codes, float* x) const override;
|
31
|
+
|
32
|
+
~IndexNeuralNetCodec() {}
|
33
|
+
};
|
34
|
+
|
35
|
+
struct IndexQINCo : IndexNeuralNetCodec {
|
36
|
+
QINCo qinco;
|
37
|
+
|
38
|
+
IndexQINCo(
|
39
|
+
int d,
|
40
|
+
int M,
|
41
|
+
int nbits,
|
42
|
+
int L,
|
43
|
+
int h,
|
44
|
+
MetricType metric = METRIC_L2);
|
45
|
+
|
46
|
+
~IndexQINCo() {}
|
47
|
+
};
|
48
|
+
|
49
|
+
} // namespace faiss
|
@@ -14,6 +14,7 @@
|
|
14
14
|
#include <cstring>
|
15
15
|
|
16
16
|
#include <algorithm>
|
17
|
+
#include <memory>
|
17
18
|
|
18
19
|
#include <faiss/impl/DistanceComputer.h>
|
19
20
|
#include <faiss/impl/FaissAssert.h>
|
@@ -86,7 +87,7 @@ struct PQDistanceComputer : FlatCodesDistanceComputer {
|
|
86
87
|
ndis++;
|
87
88
|
|
88
89
|
float dis = distance_single_code<PQDecoder>(
|
89
|
-
pq, precomputed_table.data(), code);
|
90
|
+
pq.M, pq.nbits, precomputed_table.data(), code);
|
90
91
|
return dis;
|
91
92
|
}
|
92
93
|
|
@@ -198,17 +199,16 @@ void IndexPQ::search(
|
|
198
199
|
|
199
200
|
} else { // code-to-code distances
|
200
201
|
|
201
|
-
uint8_t
|
202
|
-
ScopeDeleter<uint8_t> del(q_codes);
|
202
|
+
std::unique_ptr<uint8_t[]> q_codes(new uint8_t[n * pq.code_size]);
|
203
203
|
|
204
204
|
if (!encode_signs) {
|
205
|
-
pq.compute_codes(x, q_codes, n);
|
205
|
+
pq.compute_codes(x, q_codes.get(), n);
|
206
206
|
} else {
|
207
207
|
FAISS_THROW_IF_NOT(d == pq.nbits * pq.M);
|
208
|
-
memset(q_codes, 0, n * pq.code_size);
|
208
|
+
memset(q_codes.get(), 0, n * pq.code_size);
|
209
209
|
for (size_t i = 0; i < n; i++) {
|
210
210
|
const float* xi = x + i * d;
|
211
|
-
uint8_t* code = q_codes + i * pq.code_size;
|
211
|
+
uint8_t* code = q_codes.get() + i * pq.code_size;
|
212
212
|
for (int j = 0; j < d; j++)
|
213
213
|
if (xi[j] > 0)
|
214
214
|
code[j >> 3] |= 1 << (j & 7);
|
@@ -219,19 +219,18 @@ void IndexPQ::search(
|
|
219
219
|
float_maxheap_array_t res = {
|
220
220
|
size_t(n), size_t(k), labels, distances};
|
221
221
|
|
222
|
-
pq.search_sdc(q_codes, n, codes.data(), ntotal, &res, true);
|
222
|
+
pq.search_sdc(q_codes.get(), n, codes.data(), ntotal, &res, true);
|
223
223
|
|
224
224
|
} else {
|
225
|
-
int
|
226
|
-
ScopeDeleter<int> del(idistances);
|
225
|
+
std::unique_ptr<int[]> idistances(new int[n * k]);
|
227
226
|
|
228
227
|
int_maxheap_array_t res = {
|
229
|
-
size_t(n), size_t(k), labels, idistances};
|
228
|
+
size_t(n), size_t(k), labels, idistances.get()};
|
230
229
|
|
231
230
|
if (search_type == ST_HE) {
|
232
231
|
hammings_knn_hc(
|
233
232
|
&res,
|
234
|
-
q_codes,
|
233
|
+
q_codes.get(),
|
235
234
|
codes.data(),
|
236
235
|
ntotal,
|
237
236
|
pq.code_size,
|
@@ -240,7 +239,7 @@ void IndexPQ::search(
|
|
240
239
|
} else if (search_type == ST_generalized_HE) {
|
241
240
|
generalized_hammings_knn_hc(
|
242
241
|
&res,
|
243
|
-
q_codes,
|
242
|
+
q_codes.get(),
|
244
243
|
codes.data(),
|
245
244
|
ntotal,
|
246
245
|
pq.code_size,
|
@@ -263,21 +262,23 @@ void IndexPQStats::reset() {
|
|
263
262
|
|
264
263
|
IndexPQStats indexPQ_stats;
|
265
264
|
|
265
|
+
namespace {
|
266
|
+
|
266
267
|
template <class HammingComputer>
|
267
|
-
|
268
|
-
const IndexPQ
|
268
|
+
size_t polysemous_inner_loop(
|
269
|
+
const IndexPQ* index,
|
269
270
|
const float* dis_table_qi,
|
270
271
|
const uint8_t* q_code,
|
271
272
|
size_t k,
|
272
273
|
float* heap_dis,
|
273
274
|
int64_t* heap_ids,
|
274
275
|
int ht) {
|
275
|
-
int M = index
|
276
|
-
int code_size = index
|
277
|
-
int ksub = index
|
278
|
-
size_t ntotal = index
|
276
|
+
int M = index->pq.M;
|
277
|
+
int code_size = index->pq.code_size;
|
278
|
+
int ksub = index->pq.ksub;
|
279
|
+
size_t ntotal = index->ntotal;
|
279
280
|
|
280
|
-
const uint8_t* b_code = index
|
281
|
+
const uint8_t* b_code = index->codes.data();
|
281
282
|
|
282
283
|
size_t n_pass_i = 0;
|
283
284
|
|
@@ -305,6 +306,16 @@ static size_t polysemous_inner_loop(
|
|
305
306
|
return n_pass_i;
|
306
307
|
}
|
307
308
|
|
309
|
+
struct Run_polysemous_inner_loop {
|
310
|
+
using T = size_t;
|
311
|
+
template <class HammingComputer, class... Types>
|
312
|
+
size_t f(Types... args) {
|
313
|
+
return polysemous_inner_loop<HammingComputer>(args...);
|
314
|
+
}
|
315
|
+
};
|
316
|
+
|
317
|
+
} // anonymous namespace
|
318
|
+
|
308
319
|
void IndexPQ::search_core_polysemous(
|
309
320
|
idx_t n,
|
310
321
|
const float* x,
|
@@ -321,22 +332,20 @@ void IndexPQ::search_core_polysemous(
|
|
321
332
|
}
|
322
333
|
|
323
334
|
// PQ distance tables
|
324
|
-
float
|
325
|
-
|
326
|
-
pq.compute_distance_tables(n, x, dis_tables);
|
335
|
+
std::unique_ptr<float[]> dis_tables(new float[n * pq.ksub * pq.M]);
|
336
|
+
pq.compute_distance_tables(n, x, dis_tables.get());
|
327
337
|
|
328
338
|
// Hamming embedding queries
|
329
|
-
uint8_t
|
330
|
-
ScopeDeleter<uint8_t> del2(q_codes);
|
339
|
+
std::unique_ptr<uint8_t[]> q_codes(new uint8_t[n * pq.code_size]);
|
331
340
|
|
332
341
|
if (false) {
|
333
|
-
pq.compute_codes(x, q_codes, n);
|
342
|
+
pq.compute_codes(x, q_codes.get(), n);
|
334
343
|
} else {
|
335
344
|
#pragma omp parallel for
|
336
345
|
for (idx_t qi = 0; qi < n; qi++) {
|
337
346
|
pq.compute_code_from_distance_table(
|
338
|
-
dis_tables + qi * pq.M * pq.ksub,
|
339
|
-
q_codes + qi * pq.code_size);
|
347
|
+
dis_tables.get() + qi * pq.M * pq.ksub,
|
348
|
+
q_codes.get() + qi * pq.code_size);
|
340
349
|
}
|
341
350
|
}
|
342
351
|
|
@@ -346,54 +355,33 @@ void IndexPQ::search_core_polysemous(
|
|
346
355
|
|
347
356
|
#pragma omp parallel for reduction(+ : n_pass, bad_code_size)
|
348
357
|
for (idx_t qi = 0; qi < n; qi++) {
|
349
|
-
const uint8_t* q_code = q_codes + qi * pq.code_size;
|
358
|
+
const uint8_t* q_code = q_codes.get() + qi * pq.code_size;
|
350
359
|
|
351
|
-
const float* dis_table_qi = dis_tables + qi * pq.M * pq.ksub;
|
360
|
+
const float* dis_table_qi = dis_tables.get() + qi * pq.M * pq.ksub;
|
352
361
|
|
353
362
|
int64_t* heap_ids = labels + qi * k;
|
354
363
|
float* heap_dis = distances + qi * k;
|
355
364
|
maxheap_heapify(k, heap_dis, heap_ids);
|
356
365
|
|
357
366
|
if (!generalized_hamming) {
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
DISPATCH(4)
|
371
|
-
DISPATCH(8)
|
372
|
-
DISPATCH(16)
|
373
|
-
DISPATCH(32)
|
374
|
-
DISPATCH(20)
|
375
|
-
default:
|
376
|
-
if (pq.code_size % 4 == 0) {
|
377
|
-
n_pass += polysemous_inner_loop<HammingComputerDefault>(
|
378
|
-
*this,
|
379
|
-
dis_table_qi,
|
380
|
-
q_code,
|
381
|
-
k,
|
382
|
-
heap_dis,
|
383
|
-
heap_ids,
|
384
|
-
polysemous_ht);
|
385
|
-
} else {
|
386
|
-
bad_code_size++;
|
387
|
-
}
|
388
|
-
break;
|
389
|
-
}
|
390
|
-
#undef DISPATCH
|
367
|
+
Run_polysemous_inner_loop r;
|
368
|
+
n_pass += dispatch_HammingComputer(
|
369
|
+
pq.code_size,
|
370
|
+
r,
|
371
|
+
this,
|
372
|
+
dis_table_qi,
|
373
|
+
q_code,
|
374
|
+
k,
|
375
|
+
heap_dis,
|
376
|
+
heap_ids,
|
377
|
+
polysemous_ht);
|
378
|
+
|
391
379
|
} else { // generalized hamming
|
392
380
|
switch (pq.code_size) {
|
393
381
|
#define DISPATCH(cs) \
|
394
382
|
case cs: \
|
395
383
|
n_pass += polysemous_inner_loop<GenHammingComputer##cs>( \
|
396
|
-
|
384
|
+
this, \
|
397
385
|
dis_table_qi, \
|
398
386
|
q_code, \
|
399
387
|
k, \
|
@@ -407,7 +395,7 @@ void IndexPQ::search_core_polysemous(
|
|
407
395
|
default:
|
408
396
|
if (pq.code_size % 8 == 0) {
|
409
397
|
n_pass += polysemous_inner_loop<GenHammingComputerM8>(
|
410
|
-
|
398
|
+
this,
|
411
399
|
dis_table_qi,
|
412
400
|
q_code,
|
413
401
|
k,
|
@@ -450,12 +438,11 @@ void IndexPQ::sa_decode(idx_t n, const uint8_t* bytes, float* x) const {
|
|
450
438
|
|
451
439
|
void IndexPQ::hamming_distance_table(idx_t n, const float* x, int32_t* dis)
|
452
440
|
const {
|
453
|
-
uint8_t
|
454
|
-
ScopeDeleter<uint8_t> del(q_codes);
|
441
|
+
std::unique_ptr<uint8_t[]> q_codes(new uint8_t[n * pq.code_size]);
|
455
442
|
|
456
|
-
pq.compute_codes(x, q_codes, n);
|
443
|
+
pq.compute_codes(x, q_codes.get(), n);
|
457
444
|
|
458
|
-
hammings(q_codes, codes.data(), n, ntotal, pq.code_size, dis);
|
445
|
+
hammings(q_codes.get(), codes.data(), n, ntotal, pq.code_size, dis);
|
459
446
|
}
|
460
447
|
|
461
448
|
void IndexPQ::hamming_distance_histogram(
|
@@ -469,16 +456,15 @@ void IndexPQ::hamming_distance_histogram(
|
|
469
456
|
FAISS_THROW_IF_NOT(pq.nbits == 8);
|
470
457
|
|
471
458
|
// Hamming embedding queries
|
472
|
-
uint8_t
|
473
|
-
|
474
|
-
pq.compute_codes(x, q_codes, n);
|
459
|
+
std::unique_ptr<uint8_t[]> q_codes(new uint8_t[n * pq.code_size]);
|
460
|
+
pq.compute_codes(x, q_codes.get(), n);
|
475
461
|
|
476
462
|
uint8_t* b_codes;
|
477
|
-
|
463
|
+
std::unique_ptr<uint8_t[]> del_b_codes;
|
478
464
|
|
479
465
|
if (xb) {
|
480
466
|
b_codes = new uint8_t[nb * pq.code_size];
|
481
|
-
del_b_codes.
|
467
|
+
del_b_codes.reset(b_codes);
|
482
468
|
pq.compute_codes(xb, b_codes, nb);
|
483
469
|
} else {
|
484
470
|
nb = ntotal;
|
@@ -491,8 +477,7 @@ void IndexPQ::hamming_distance_histogram(
|
|
491
477
|
#pragma omp parallel
|
492
478
|
{
|
493
479
|
std::vector<int64_t> histi(nbits + 1);
|
494
|
-
hamdis_t
|
495
|
-
ScopeDeleter<hamdis_t> del(distances);
|
480
|
+
std::unique_ptr<hamdis_t[]> distances(new hamdis_t[nb * bs]);
|
496
481
|
#pragma omp for
|
497
482
|
for (idx_t q0 = 0; q0 < n; q0 += bs) {
|
498
483
|
// printf ("dis stats: %zd/%zd\n", q0, n);
|
@@ -501,12 +486,12 @@ void IndexPQ::hamming_distance_histogram(
|
|
501
486
|
q1 = n;
|
502
487
|
|
503
488
|
hammings(
|
504
|
-
q_codes + q0 * pq.code_size,
|
489
|
+
q_codes.get() + q0 * pq.code_size,
|
505
490
|
b_codes,
|
506
491
|
q1 - q0,
|
507
492
|
nb,
|
508
493
|
pq.code_size,
|
509
|
-
distances);
|
494
|
+
distances.get());
|
510
495
|
|
511
496
|
for (size_t i = 0; i < nb * (q1 - q0); i++)
|
512
497
|
histi[distances[i]]++;
|
@@ -639,7 +624,7 @@ struct SemiSortedArray {
|
|
639
624
|
int N;
|
640
625
|
|
641
626
|
// type of the heap: CMax = sort ascending
|
642
|
-
|
627
|
+
using HC = CMax<T, int>;
|
643
628
|
std::vector<int> perm;
|
644
629
|
|
645
630
|
int k; // k elements are sorted
|
@@ -733,7 +718,7 @@ struct MinSumK {
|
|
733
718
|
* We use a heap to maintain a queue of sums, with the associated
|
734
719
|
* terms involved in the sum.
|
735
720
|
*/
|
736
|
-
|
721
|
+
using HC = CMin<T, int64_t>;
|
737
722
|
size_t heap_capacity, heap_size;
|
738
723
|
T* bh_val;
|
739
724
|
int64_t* bh_ids;
|
@@ -827,7 +812,7 @@ struct MinSumK {
|
|
827
812
|
// enqueue followers
|
828
813
|
int64_t ii = ti;
|
829
814
|
for (int m = 0; m < M; m++) {
|
830
|
-
int64_t n = ii & ((
|
815
|
+
int64_t n = ii & (((int64_t)1 << nbit) - 1);
|
831
816
|
ii >>= nbit;
|
832
817
|
if (n + 1 >= N)
|
833
818
|
continue;
|
@@ -851,7 +836,7 @@ struct MinSumK {
|
|
851
836
|
}
|
852
837
|
int64_t ti = 0;
|
853
838
|
for (int m = 0; m < M; m++) {
|
854
|
-
int64_t n = ii & ((
|
839
|
+
int64_t n = ii & (((int64_t)1 << nbit) - 1);
|
855
840
|
ti += int64_t(ssx[m].get_ord(n)) << (nbit * m);
|
856
841
|
ii >>= nbit;
|
857
842
|
}
|
@@ -923,17 +908,16 @@ void MultiIndexQuantizer::search(
|
|
923
908
|
return;
|
924
909
|
}
|
925
910
|
|
926
|
-
float
|
927
|
-
ScopeDeleter<float> del(dis_tables);
|
911
|
+
std::unique_ptr<float[]> dis_tables(new float[n * pq.ksub * pq.M]);
|
928
912
|
|
929
|
-
pq.compute_distance_tables(n, x, dis_tables);
|
913
|
+
pq.compute_distance_tables(n, x, dis_tables.get());
|
930
914
|
|
931
915
|
if (k == 1) {
|
932
916
|
// simple version that just finds the min in each table
|
933
917
|
|
934
918
|
#pragma omp parallel for
|
935
919
|
for (int i = 0; i < n; i++) {
|
936
|
-
const float* dis_table = dis_tables + i * pq.ksub * pq.M;
|
920
|
+
const float* dis_table = dis_tables.get() + i * pq.ksub * pq.M;
|
937
921
|
float dis = 0;
|
938
922
|
idx_t label = 0;
|
939
923
|
|
@@ -963,7 +947,7 @@ void MultiIndexQuantizer::search(
|
|
963
947
|
k, pq.M, pq.nbits, pq.ksub);
|
964
948
|
#pragma omp for
|
965
949
|
for (int i = 0; i < n; i++) {
|
966
|
-
msk.run(dis_tables + i * pq.ksub * pq.M,
|
950
|
+
msk.run(dis_tables.get() + i * pq.ksub * pq.M,
|
967
951
|
pq.ksub,
|
968
952
|
distances + i * k,
|
969
953
|
labels + i * k);
|
@@ -975,7 +959,7 @@ void MultiIndexQuantizer::search(
|
|
975
959
|
void MultiIndexQuantizer::reconstruct(idx_t key, float* recons) const {
|
976
960
|
int64_t jj = key;
|
977
961
|
for (int m = 0; m < pq.M; m++) {
|
978
|
-
int64_t n = jj & ((
|
962
|
+
int64_t n = jj & (((int64_t)1 << pq.nbits) - 1);
|
979
963
|
jj >>= pq.nbits;
|
980
964
|
memcpy(recons, pq.get_centroids(m, n), sizeof(recons[0]) * pq.dsub);
|
981
965
|
recons += pq.dsub;
|
@@ -1107,7 +1091,7 @@ void MultiIndexQuantizer2::search(
|
|
1107
1091
|
|
1108
1092
|
const idx_t* idmap0 = sub_ids.data() + i * k2;
|
1109
1093
|
int64_t ld_idmap = k2 * n;
|
1110
|
-
int64_t mask1 = ksub -
|
1094
|
+
int64_t mask1 = ksub - (int64_t)1;
|
1111
1095
|
|
1112
1096
|
for (int k = 0; k < K; k++) {
|
1113
1097
|
const idx_t* idmap = idmap0;
|
@@ -31,10 +31,7 @@ struct IndexPQ : IndexFlatCodes {
|
|
31
31
|
* @param M number of subquantizers
|
32
32
|
* @param nbits number of bit per subvector index
|
33
33
|
*/
|
34
|
-
IndexPQ(int d,
|
35
|
-
size_t M, ///< number of subquantizers
|
36
|
-
size_t nbits, ///< number of bit per subvector index
|
37
|
-
MetricType metric = METRIC_L2);
|
34
|
+
IndexPQ(int d, size_t M, size_t nbits, MetricType metric = METRIC_L2);
|
38
35
|
|
39
36
|
IndexPQ();
|
40
37
|
|