faiss 0.3.1 → 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 +4 -0
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.h +1 -1
- data/vendor/faiss/faiss/Clustering.cpp +35 -4
- data/vendor/faiss/faiss/Clustering.h +10 -1
- data/vendor/faiss/faiss/IVFlib.cpp +4 -1
- data/vendor/faiss/faiss/Index.h +21 -6
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +1 -1
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +1 -1
- data/vendor/faiss/faiss/IndexFastScan.cpp +22 -4
- data/vendor/faiss/faiss/IndexFlat.cpp +11 -7
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +159 -5
- data/vendor/faiss/faiss/IndexFlatCodes.h +20 -3
- data/vendor/faiss/faiss/IndexHNSW.cpp +143 -90
- data/vendor/faiss/faiss/IndexHNSW.h +52 -3
- data/vendor/faiss/faiss/IndexIVF.cpp +3 -3
- data/vendor/faiss/faiss/IndexIVF.h +9 -1
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +15 -0
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +3 -0
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +130 -57
- data/vendor/faiss/faiss/IndexIVFFastScan.h +14 -7
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +1 -3
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +21 -2
- data/vendor/faiss/faiss/IndexLattice.cpp +1 -19
- data/vendor/faiss/faiss/IndexLattice.h +3 -22
- data/vendor/faiss/faiss/IndexNNDescent.cpp +0 -29
- data/vendor/faiss/faiss/IndexNNDescent.h +1 -1
- data/vendor/faiss/faiss/IndexNSG.h +1 -1
- data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +56 -0
- data/vendor/faiss/faiss/IndexNeuralNetCodec.h +49 -0
- data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
- data/vendor/faiss/faiss/IndexRefine.cpp +5 -5
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +3 -1
- data/vendor/faiss/faiss/MetricType.h +7 -2
- 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 +36 -4
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +6 -0
- data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -1
- data/vendor/faiss/faiss/gpu/GpuIndex.h +2 -8
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +282 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +6 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +2 -0
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +25 -0
- data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +26 -21
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +6 -0
- data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +8 -5
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +65 -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/Timer.cpp +4 -1
- data/vendor/faiss/faiss/gpu/utils/Timer.h +1 -1
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +25 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +9 -1
- data/vendor/faiss/faiss/impl/DistanceComputer.h +46 -0
- data/vendor/faiss/faiss/impl/FaissAssert.h +4 -2
- data/vendor/faiss/faiss/impl/HNSW.cpp +358 -190
- data/vendor/faiss/faiss/impl/HNSW.h +43 -22
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +8 -8
- data/vendor/faiss/faiss/impl/LookupTableScaler.h +34 -0
- data/vendor/faiss/faiss/impl/NNDescent.cpp +13 -8
- data/vendor/faiss/faiss/impl/NSG.cpp +0 -29
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +1 -0
- data/vendor/faiss/faiss/impl/ProductQuantizer.h +5 -1
- data/vendor/faiss/faiss/impl/ResultHandler.h +151 -32
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +719 -102
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +3 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +5 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance-avx512.h +248 -0
- data/vendor/faiss/faiss/impl/index_read.cpp +29 -15
- data/vendor/faiss/faiss/impl/index_read_utils.h +37 -0
- data/vendor/faiss/faiss/impl/index_write.cpp +28 -10
- data/vendor/faiss/faiss/impl/io.cpp +13 -5
- data/vendor/faiss/faiss/impl/io.h +4 -4
- data/vendor/faiss/faiss/impl/io_macros.h +6 -0
- data/vendor/faiss/faiss/impl/platform_macros.h +22 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +11 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +1 -1
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +448 -1
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +5 -5
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
- data/vendor/faiss/faiss/impl/simd_result_handlers.h +143 -59
- data/vendor/faiss/faiss/index_factory.cpp +31 -13
- 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 +9 -1
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +55 -17
- data/vendor/faiss/faiss/invlists/InvertedLists.h +18 -9
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +21 -6
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +2 -1
- data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -3
- 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/bf16.h +36 -0
- data/vendor/faiss/faiss/utils/distances.cpp +58 -88
- data/vendor/faiss/faiss/utils/distances.h +5 -5
- data/vendor/faiss/faiss/utils/distances_simd.cpp +997 -9
- 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/hamming.cpp +1 -1
- data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +4 -1
- data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +2 -1
- 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_avx512.h +296 -0
- data/vendor/faiss/faiss/utils/simdlib_neon.h +5 -2
- data/vendor/faiss/faiss/utils/simdlib_ppc64.h +1084 -0
- data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +176 -0
- data/vendor/faiss/faiss/utils/utils.cpp +10 -3
- data/vendor/faiss/faiss/utils/utils.h +3 -0
- metadata +16 -4
- data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +0 -102
|
@@ -58,35 +58,6 @@ using storage_idx_t = NNDescent::storage_idx_t;
|
|
|
58
58
|
|
|
59
59
|
namespace {
|
|
60
60
|
|
|
61
|
-
/* Wrap the distance computer into one that negates the
|
|
62
|
-
distances. This makes supporting INNER_PRODUCE search easier */
|
|
63
|
-
|
|
64
|
-
struct NegativeDistanceComputer : DistanceComputer {
|
|
65
|
-
/// owned by this
|
|
66
|
-
DistanceComputer* basedis;
|
|
67
|
-
|
|
68
|
-
explicit NegativeDistanceComputer(DistanceComputer* basedis)
|
|
69
|
-
: basedis(basedis) {}
|
|
70
|
-
|
|
71
|
-
void set_query(const float* x) override {
|
|
72
|
-
basedis->set_query(x);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/// compute distance of vector i to current query
|
|
76
|
-
float operator()(idx_t i) override {
|
|
77
|
-
return -(*basedis)(i);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/// compute distance between two stored vectors
|
|
81
|
-
float symmetric_dis(idx_t i, idx_t j) override {
|
|
82
|
-
return -basedis->symmetric_dis(i, j);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
~NegativeDistanceComputer() override {
|
|
86
|
-
delete basedis;
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
|
|
90
61
|
DistanceComputer* storage_distance_computer(const Index* storage) {
|
|
91
62
|
if (is_similarity_metric(storage->metric_type)) {
|
|
92
63
|
return new NegativeDistanceComputer(storage->get_distance_computer());
|
|
@@ -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
|
|
@@ -23,7 +23,7 @@ struct SearchParametersPreTransform : SearchParameters {
|
|
|
23
23
|
/** Index that applies a LinearTransform transform on vectors before
|
|
24
24
|
* handing them over to a sub-index */
|
|
25
25
|
struct IndexPreTransform : Index {
|
|
26
|
-
std::vector<VectorTransform*> chain; ///! chain of
|
|
26
|
+
std::vector<VectorTransform*> chain; ///! chain of transforms
|
|
27
27
|
Index* index; ///! the sub-index
|
|
28
28
|
|
|
29
29
|
bool own_fields; ///! whether pointers are deleted in destructor
|
|
@@ -68,12 +68,12 @@ template <class C>
|
|
|
68
68
|
static void reorder_2_heaps(
|
|
69
69
|
idx_t n,
|
|
70
70
|
idx_t k,
|
|
71
|
-
idx_t* labels,
|
|
72
|
-
float* distances,
|
|
71
|
+
idx_t* __restrict labels,
|
|
72
|
+
float* __restrict distances,
|
|
73
73
|
idx_t k_base,
|
|
74
|
-
const idx_t* base_labels,
|
|
75
|
-
const float* base_distances) {
|
|
76
|
-
#pragma omp parallel for
|
|
74
|
+
const idx_t* __restrict base_labels,
|
|
75
|
+
const float* __restrict base_distances) {
|
|
76
|
+
#pragma omp parallel for if (n > 1)
|
|
77
77
|
for (idx_t i = 0; i < n; i++) {
|
|
78
78
|
idx_t* idxo = labels + i * k;
|
|
79
79
|
float* diso = distances + i * k;
|
|
@@ -32,7 +32,9 @@ IndexScalarQuantizer::IndexScalarQuantizer(
|
|
|
32
32
|
MetricType metric)
|
|
33
33
|
: IndexFlatCodes(0, d, metric), sq(d, qtype) {
|
|
34
34
|
is_trained = qtype == ScalarQuantizer::QT_fp16 ||
|
|
35
|
-
qtype == ScalarQuantizer::QT_8bit_direct
|
|
35
|
+
qtype == ScalarQuantizer::QT_8bit_direct ||
|
|
36
|
+
qtype == ScalarQuantizer::QT_bf16 ||
|
|
37
|
+
qtype == ScalarQuantizer::QT_8bit_direct_signed;
|
|
36
38
|
code_size = sq.code_size;
|
|
37
39
|
}
|
|
38
40
|
|
|
@@ -31,8 +31,13 @@ enum MetricType {
|
|
|
31
31
|
METRIC_Canberra = 20,
|
|
32
32
|
METRIC_BrayCurtis,
|
|
33
33
|
METRIC_JensenShannon,
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
|
|
35
|
+
/// sum_i(min(a_i, b_i)) / sum_i(max(a_i, b_i)) where a_i, b_i > 0
|
|
36
|
+
METRIC_Jaccard,
|
|
37
|
+
/// Squared Eucliden distance, ignoring NaNs
|
|
38
|
+
METRIC_NaNEuclidean,
|
|
39
|
+
/// abs(x | y): the distance to a hyperplane
|
|
40
|
+
METRIC_ABS_INNER_PRODUCT,
|
|
36
41
|
};
|
|
37
42
|
|
|
38
43
|
/// all vector indices are this type
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
+
#include <faiss/impl/platform_macros.h>
|
|
10
11
|
#include <cstdint>
|
|
11
12
|
|
|
12
13
|
namespace faiss {
|
|
@@ -31,7 +32,11 @@ struct Uint8Reader {
|
|
|
31
32
|
if (N_ELEMENTS > CPOS + 3) {
|
|
32
33
|
const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
33
34
|
codes + ELEMENT_TO_READ * 4);
|
|
35
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
36
|
+
return (code32) >> 24;
|
|
37
|
+
#else
|
|
34
38
|
return (code32 & 0x000000FF);
|
|
39
|
+
#endif
|
|
35
40
|
} else {
|
|
36
41
|
return codes[CPOS];
|
|
37
42
|
}
|
|
@@ -40,7 +45,11 @@ struct Uint8Reader {
|
|
|
40
45
|
if (N_ELEMENTS > CPOS + 2) {
|
|
41
46
|
const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
42
47
|
codes + ELEMENT_TO_READ * 4);
|
|
48
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
49
|
+
return (code32 & 0x00FF0000) >> 16;
|
|
50
|
+
#else
|
|
43
51
|
return (code32 & 0x0000FF00) >> 8;
|
|
52
|
+
#endif
|
|
44
53
|
} else {
|
|
45
54
|
return codes[CPOS];
|
|
46
55
|
}
|
|
@@ -49,7 +58,11 @@ struct Uint8Reader {
|
|
|
49
58
|
if (N_ELEMENTS > CPOS + 1) {
|
|
50
59
|
const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
51
60
|
codes + ELEMENT_TO_READ * 4);
|
|
61
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
62
|
+
return (code32 & 0x0000FF00) >> 8;
|
|
63
|
+
#else
|
|
52
64
|
return (code32 & 0x00FF0000) >> 16;
|
|
65
|
+
#endif
|
|
53
66
|
} else {
|
|
54
67
|
return codes[CPOS];
|
|
55
68
|
}
|
|
@@ -58,7 +71,11 @@ struct Uint8Reader {
|
|
|
58
71
|
if (N_ELEMENTS > CPOS) {
|
|
59
72
|
const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
60
73
|
codes + ELEMENT_TO_READ * 4);
|
|
74
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
75
|
+
return (code32 & 0x000000FF);
|
|
76
|
+
#else
|
|
61
77
|
return (code32) >> 24;
|
|
78
|
+
#endif
|
|
62
79
|
} else {
|
|
63
80
|
return codes[CPOS];
|
|
64
81
|
}
|
|
@@ -87,40 +104,61 @@ struct Uint10Reader {
|
|
|
87
104
|
switch (SUB_ELEMENT) {
|
|
88
105
|
case 0: {
|
|
89
106
|
if (N_ELEMENTS > CPOS + 2) {
|
|
90
|
-
|
|
107
|
+
uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
91
108
|
codes + ELEMENT_TO_READ * 5);
|
|
109
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
110
|
+
code32 = Swap4Bytes(code32);
|
|
111
|
+
#endif
|
|
92
112
|
return (code32 & 0b0000001111111111);
|
|
93
113
|
} else {
|
|
94
|
-
|
|
114
|
+
uint16_t code16 = *reinterpret_cast<const uint16_t*>(
|
|
95
115
|
codes + ELEMENT_TO_READ * 5 + 0);
|
|
116
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
117
|
+
code16 = Swap2Bytes(code16);
|
|
118
|
+
#endif
|
|
96
119
|
return (code16 & 0b0000001111111111);
|
|
97
120
|
}
|
|
98
121
|
}
|
|
99
122
|
case 1: {
|
|
100
123
|
if (N_ELEMENTS > CPOS + 1) {
|
|
101
|
-
|
|
124
|
+
uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
102
125
|
codes + ELEMENT_TO_READ * 5);
|
|
126
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
127
|
+
code32 = Swap4Bytes(code32);
|
|
128
|
+
#endif
|
|
103
129
|
return (code32 & 0b000011111111110000000000) >> 10;
|
|
104
130
|
} else {
|
|
105
|
-
|
|
131
|
+
uint16_t code16 = *reinterpret_cast<const uint16_t*>(
|
|
106
132
|
codes + ELEMENT_TO_READ * 5 + 1);
|
|
133
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
134
|
+
code16 = Swap2Bytes(code16);
|
|
135
|
+
#endif
|
|
107
136
|
return (code16 & 0b0000111111111100) >> 2;
|
|
108
137
|
}
|
|
109
138
|
}
|
|
110
139
|
case 2: {
|
|
111
140
|
if (N_ELEMENTS > CPOS) {
|
|
112
|
-
|
|
141
|
+
uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
113
142
|
codes + ELEMENT_TO_READ * 5);
|
|
143
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
144
|
+
code32 = Swap4Bytes(code32);
|
|
145
|
+
#endif
|
|
114
146
|
return (code32 & 0b00111111111100000000000000000000) >> 20;
|
|
115
147
|
} else {
|
|
116
|
-
|
|
148
|
+
uint16_t code16 = *reinterpret_cast<const uint16_t*>(
|
|
117
149
|
codes + ELEMENT_TO_READ * 5 + 2);
|
|
150
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
151
|
+
code16 = Swap2Bytes(code16);
|
|
152
|
+
#endif
|
|
118
153
|
return (code16 & 0b0011111111110000) >> 4;
|
|
119
154
|
}
|
|
120
155
|
}
|
|
121
156
|
case 3: {
|
|
122
|
-
|
|
157
|
+
uint16_t code16 = *reinterpret_cast<const uint16_t*>(
|
|
123
158
|
codes + ELEMENT_TO_READ * 5 + 3);
|
|
159
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
160
|
+
code16 = Swap2Bytes(code16);
|
|
161
|
+
#endif
|
|
124
162
|
return (code16 & 0b1111111111000000) >> 6;
|
|
125
163
|
}
|
|
126
164
|
}
|
|
@@ -147,45 +185,69 @@ struct Uint12Reader {
|
|
|
147
185
|
switch (SUB_ELEMENT) {
|
|
148
186
|
case 0: {
|
|
149
187
|
if (N_ELEMENTS > CPOS + 2) {
|
|
150
|
-
|
|
188
|
+
uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
151
189
|
codes + ELEMENT_TO_READ * 6);
|
|
190
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
191
|
+
code32 = Swap4Bytes(code32);
|
|
192
|
+
#endif
|
|
152
193
|
return (code32 & 0b0000111111111111);
|
|
153
194
|
} else {
|
|
154
|
-
|
|
195
|
+
uint16_t code16 = *reinterpret_cast<const uint16_t*>(
|
|
155
196
|
codes + ELEMENT_TO_READ * 6 + 0);
|
|
197
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
198
|
+
code16 = Swap2Bytes(code16);
|
|
199
|
+
#endif
|
|
156
200
|
return (code16 & 0b0000111111111111);
|
|
157
201
|
}
|
|
158
202
|
}
|
|
159
203
|
case 1: {
|
|
160
204
|
if (N_ELEMENTS > CPOS + 1) {
|
|
161
|
-
|
|
205
|
+
uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
162
206
|
codes + ELEMENT_TO_READ * 6);
|
|
207
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
208
|
+
code32 = Swap4Bytes(code32);
|
|
209
|
+
#endif
|
|
163
210
|
return (code32 & 0b111111111111000000000000) >> 12;
|
|
164
211
|
} else {
|
|
165
|
-
|
|
212
|
+
uint16_t code16 = *reinterpret_cast<const uint16_t*>(
|
|
166
213
|
codes + ELEMENT_TO_READ * 6 + 1);
|
|
214
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
215
|
+
code16 = Swap2Bytes(code16);
|
|
216
|
+
#endif
|
|
167
217
|
return (code16 & 0b1111111111110000) >> 4;
|
|
168
218
|
}
|
|
169
219
|
}
|
|
170
220
|
case 2: {
|
|
171
221
|
if (N_ELEMENTS > CPOS + 1) {
|
|
172
|
-
|
|
222
|
+
uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
173
223
|
codes + ELEMENT_TO_READ * 6 + 2);
|
|
224
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
225
|
+
code32 = Swap4Bytes(code32);
|
|
226
|
+
#endif
|
|
174
227
|
return (code32 & 0b000011111111111100000000) >> 8;
|
|
175
228
|
} else {
|
|
176
|
-
|
|
229
|
+
uint16_t code16 = *reinterpret_cast<const uint16_t*>(
|
|
177
230
|
codes + ELEMENT_TO_READ * 6 + 3);
|
|
231
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
232
|
+
code16 = Swap2Bytes(code16);
|
|
233
|
+
#endif
|
|
178
234
|
return (code16 & 0b0000111111111111);
|
|
179
235
|
}
|
|
180
236
|
}
|
|
181
237
|
case 3: {
|
|
182
238
|
if (N_ELEMENTS > CPOS) {
|
|
183
|
-
|
|
239
|
+
uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
184
240
|
codes + ELEMENT_TO_READ * 6 + 2);
|
|
241
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
242
|
+
code32 = Swap4Bytes(code32);
|
|
243
|
+
#endif
|
|
185
244
|
return (code32 & 0b11111111111100000000000000000000) >> 20;
|
|
186
245
|
} else {
|
|
187
|
-
|
|
246
|
+
uint16_t code16 = *reinterpret_cast<const uint16_t*>(
|
|
188
247
|
codes + ELEMENT_TO_READ * 6 + 4);
|
|
248
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
249
|
+
code16 = Swap2Bytes(code16);
|
|
250
|
+
#endif
|
|
189
251
|
return (code16 & 0b1111111111110000) >> 4;
|
|
190
252
|
}
|
|
191
253
|
}
|
|
@@ -208,23 +270,39 @@ struct Uint16Reader {
|
|
|
208
270
|
switch (SUB_ELEMENT) {
|
|
209
271
|
case 0: {
|
|
210
272
|
if (N_ELEMENTS > CPOS + 1) {
|
|
211
|
-
|
|
273
|
+
uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
212
274
|
codes + ELEMENT_TO_READ * 4);
|
|
275
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
276
|
+
code32 = Swap4Bytes(code32);
|
|
277
|
+
#endif
|
|
213
278
|
return (code32 & 0x0000FFFF);
|
|
214
279
|
} else {
|
|
215
280
|
const uint16_t* const __restrict codesFp16 =
|
|
216
281
|
reinterpret_cast<const uint16_t*>(codes);
|
|
282
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
283
|
+
uint16_t rt = codesFp16[CPOS];
|
|
284
|
+
rt = Swap2Bytes(rt);
|
|
285
|
+
return rt;
|
|
286
|
+
#endif
|
|
217
287
|
return codesFp16[CPOS];
|
|
218
288
|
}
|
|
219
289
|
}
|
|
220
290
|
case 1: {
|
|
221
291
|
if (N_ELEMENTS > CPOS) {
|
|
222
|
-
|
|
292
|
+
uint32_t code32 = *reinterpret_cast<const uint32_t*>(
|
|
223
293
|
codes + ELEMENT_TO_READ * 4);
|
|
294
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
295
|
+
code32 = Swap4Bytes(code32);
|
|
296
|
+
#endif
|
|
224
297
|
return code32 >> 16;
|
|
225
298
|
} else {
|
|
226
299
|
const uint16_t* const __restrict codesFp16 =
|
|
227
300
|
reinterpret_cast<const uint16_t*>(codes);
|
|
301
|
+
#ifdef FAISS_BIG_ENDIAN
|
|
302
|
+
uint16_t rt = codesFp16[CPOS];
|
|
303
|
+
rt = Swap2Bytes(rt);
|
|
304
|
+
return rt;
|
|
305
|
+
#endif
|
|
228
306
|
return codesFp16[CPOS];
|
|
229
307
|
}
|
|
230
308
|
}
|
|
@@ -0,0 +1,152 @@
|
|
|
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
|
+
// -*- c++ -*-
|
|
9
|
+
|
|
10
|
+
#include <faiss/cppcontrib/factory_tools.h>
|
|
11
|
+
#include <map>
|
|
12
|
+
|
|
13
|
+
namespace faiss {
|
|
14
|
+
|
|
15
|
+
namespace {
|
|
16
|
+
|
|
17
|
+
const std::map<faiss::ScalarQuantizer::QuantizerType, std::string> sq_types = {
|
|
18
|
+
{faiss::ScalarQuantizer::QT_8bit, "SQ8"},
|
|
19
|
+
{faiss::ScalarQuantizer::QT_4bit, "SQ4"},
|
|
20
|
+
{faiss::ScalarQuantizer::QT_6bit, "SQ6"},
|
|
21
|
+
{faiss::ScalarQuantizer::QT_fp16, "SQfp16"},
|
|
22
|
+
{faiss::ScalarQuantizer::QT_bf16, "SQbf16"},
|
|
23
|
+
{faiss::ScalarQuantizer::QT_8bit_direct_signed, "SQ8_direct_signed"},
|
|
24
|
+
{faiss::ScalarQuantizer::QT_8bit_direct, "SQ8_direct"},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
int get_hnsw_M(const faiss::IndexHNSW* index) {
|
|
28
|
+
if (index->hnsw.cum_nneighbor_per_level.size() >= 1) {
|
|
29
|
+
return index->hnsw.cum_nneighbor_per_level[1] / 2;
|
|
30
|
+
}
|
|
31
|
+
// Avoid runtime error, just return 0.
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
} // namespace
|
|
36
|
+
|
|
37
|
+
// Reference for reverse_index_factory:
|
|
38
|
+
// https://github.com/facebookresearch/faiss/blob/838612c9d7f2f619811434ec9209c020f44107cb/contrib/factory_tools.py#L81
|
|
39
|
+
std::string reverse_index_factory(const faiss::Index* index) {
|
|
40
|
+
std::string prefix;
|
|
41
|
+
if (dynamic_cast<const faiss::IndexFlat*>(index)) {
|
|
42
|
+
return "Flat";
|
|
43
|
+
} else if (
|
|
44
|
+
const faiss::IndexIVF* ivf_index =
|
|
45
|
+
dynamic_cast<const faiss::IndexIVF*>(index)) {
|
|
46
|
+
const faiss::Index* quantizer = ivf_index->quantizer;
|
|
47
|
+
|
|
48
|
+
if (dynamic_cast<const faiss::IndexFlat*>(quantizer)) {
|
|
49
|
+
prefix = "IVF" + std::to_string(ivf_index->nlist);
|
|
50
|
+
} else if (
|
|
51
|
+
const faiss::MultiIndexQuantizer* miq =
|
|
52
|
+
dynamic_cast<const faiss::MultiIndexQuantizer*>(
|
|
53
|
+
quantizer)) {
|
|
54
|
+
prefix = "IMI" + std::to_string(miq->pq.M) + "x" +
|
|
55
|
+
std::to_string(miq->pq.nbits);
|
|
56
|
+
} else if (
|
|
57
|
+
const faiss::IndexHNSW* hnsw_index =
|
|
58
|
+
dynamic_cast<const faiss::IndexHNSW*>(quantizer)) {
|
|
59
|
+
prefix = "IVF" + std::to_string(ivf_index->nlist) + "_HNSW" +
|
|
60
|
+
std::to_string(get_hnsw_M(hnsw_index));
|
|
61
|
+
} else {
|
|
62
|
+
prefix = "IVF" + std::to_string(ivf_index->nlist) + "(" +
|
|
63
|
+
reverse_index_factory(quantizer) + ")";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (dynamic_cast<const faiss::IndexIVFFlat*>(ivf_index)) {
|
|
67
|
+
return prefix + ",Flat";
|
|
68
|
+
} else if (
|
|
69
|
+
auto sq_index =
|
|
70
|
+
dynamic_cast<const faiss::IndexIVFScalarQuantizer*>(
|
|
71
|
+
ivf_index)) {
|
|
72
|
+
return prefix + "," + sq_types.at(sq_index->sq.qtype);
|
|
73
|
+
} else if (
|
|
74
|
+
const faiss::IndexIVFPQ* ivfpq_index =
|
|
75
|
+
dynamic_cast<const faiss::IndexIVFPQ*>(ivf_index)) {
|
|
76
|
+
return prefix + ",PQ" + std::to_string(ivfpq_index->pq.M) + "x" +
|
|
77
|
+
std::to_string(ivfpq_index->pq.nbits);
|
|
78
|
+
} else if (
|
|
79
|
+
const faiss::IndexIVFPQFastScan* ivfpqfs_index =
|
|
80
|
+
dynamic_cast<const faiss::IndexIVFPQFastScan*>(
|
|
81
|
+
ivf_index)) {
|
|
82
|
+
return prefix + ",PQ" + std::to_string(ivfpqfs_index->pq.M) + "x" +
|
|
83
|
+
std::to_string(ivfpqfs_index->pq.nbits) + "fs";
|
|
84
|
+
}
|
|
85
|
+
} else if (
|
|
86
|
+
const faiss::IndexPreTransform* pretransform_index =
|
|
87
|
+
dynamic_cast<const faiss::IndexPreTransform*>(index)) {
|
|
88
|
+
if (pretransform_index->chain.size() != 1) {
|
|
89
|
+
// Avoid runtime error, just return empty string for logging.
|
|
90
|
+
return "";
|
|
91
|
+
}
|
|
92
|
+
const faiss::VectorTransform* vt = pretransform_index->chain.at(0);
|
|
93
|
+
if (const faiss::OPQMatrix* opq_matrix =
|
|
94
|
+
dynamic_cast<const faiss::OPQMatrix*>(vt)) {
|
|
95
|
+
prefix = "OPQ" + std::to_string(opq_matrix->M) + "_" +
|
|
96
|
+
std::to_string(opq_matrix->d_out);
|
|
97
|
+
} else if (
|
|
98
|
+
const faiss::ITQTransform* itq_transform =
|
|
99
|
+
dynamic_cast<const faiss::ITQTransform*>(vt)) {
|
|
100
|
+
prefix = "ITQ" + std::to_string(itq_transform->itq.d_out);
|
|
101
|
+
} else if (
|
|
102
|
+
const faiss::PCAMatrix* pca_matrix =
|
|
103
|
+
dynamic_cast<const faiss::PCAMatrix*>(vt)) {
|
|
104
|
+
assert(pca_matrix->eigen_power == 0);
|
|
105
|
+
prefix = "PCA" +
|
|
106
|
+
std::string(pca_matrix->random_rotation ? "R" : "") +
|
|
107
|
+
std::to_string(pca_matrix->d_out);
|
|
108
|
+
} else {
|
|
109
|
+
// Avoid runtime error, just return empty string for logging.
|
|
110
|
+
return "";
|
|
111
|
+
}
|
|
112
|
+
return prefix + "," + reverse_index_factory(pretransform_index->index);
|
|
113
|
+
} else if (
|
|
114
|
+
const faiss::IndexHNSW* hnsw_index =
|
|
115
|
+
dynamic_cast<const faiss::IndexHNSW*>(index)) {
|
|
116
|
+
return "HNSW" + std::to_string(get_hnsw_M(hnsw_index));
|
|
117
|
+
} else if (
|
|
118
|
+
const faiss::IndexRefine* refine_index =
|
|
119
|
+
dynamic_cast<const faiss::IndexRefine*>(index)) {
|
|
120
|
+
return reverse_index_factory(refine_index->base_index) + ",Refine(" +
|
|
121
|
+
reverse_index_factory(refine_index->refine_index) + ")";
|
|
122
|
+
} else if (
|
|
123
|
+
const faiss::IndexPQFastScan* pqfs_index =
|
|
124
|
+
dynamic_cast<const faiss::IndexPQFastScan*>(index)) {
|
|
125
|
+
return std::string("PQ") + std::to_string(pqfs_index->pq.M) + "x" +
|
|
126
|
+
std::to_string(pqfs_index->pq.nbits) + "fs";
|
|
127
|
+
} else if (
|
|
128
|
+
const faiss::IndexPQ* pq_index =
|
|
129
|
+
dynamic_cast<const faiss::IndexPQ*>(index)) {
|
|
130
|
+
return std::string("PQ") + std::to_string(pq_index->pq.M) + "x" +
|
|
131
|
+
std::to_string(pq_index->pq.nbits);
|
|
132
|
+
} else if (
|
|
133
|
+
const faiss::IndexLSH* lsh_index =
|
|
134
|
+
dynamic_cast<const faiss::IndexLSH*>(index)) {
|
|
135
|
+
std::string result = "LSH";
|
|
136
|
+
if (lsh_index->rotate_data) {
|
|
137
|
+
result += "r";
|
|
138
|
+
}
|
|
139
|
+
if (lsh_index->train_thresholds) {
|
|
140
|
+
result += "t";
|
|
141
|
+
}
|
|
142
|
+
return result;
|
|
143
|
+
} else if (
|
|
144
|
+
const faiss::IndexScalarQuantizer* sq_index =
|
|
145
|
+
dynamic_cast<const faiss::IndexScalarQuantizer*>(index)) {
|
|
146
|
+
return std::string("SQ") + sq_types.at(sq_index->sq.qtype);
|
|
147
|
+
}
|
|
148
|
+
// Avoid runtime error, just return empty string for logging.
|
|
149
|
+
return "";
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
} // namespace faiss
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
// -*- c++ -*-
|
|
9
|
+
|
|
10
|
+
#pragma once
|
|
11
|
+
|
|
12
|
+
#include <faiss/IndexHNSW.h>
|
|
13
|
+
#include <faiss/IndexIVFFlat.h>
|
|
14
|
+
#include <faiss/IndexIVFPQFastScan.h>
|
|
15
|
+
#include <faiss/IndexLSH.h>
|
|
16
|
+
#include <faiss/IndexPQFastScan.h>
|
|
17
|
+
#include <faiss/IndexPreTransform.h>
|
|
18
|
+
#include <faiss/IndexRefine.h>
|
|
19
|
+
|
|
20
|
+
namespace faiss {
|
|
21
|
+
|
|
22
|
+
std::string reverse_index_factory(const faiss::Index* index);
|
|
23
|
+
|
|
24
|
+
} // namespace faiss
|