faiss 0.3.0 → 0.3.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 +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
|
|