faiss 0.6.1 → 0.6.3
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 +8 -0
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +3 -1
- data/vendor/faiss/faiss/Clustering.cpp +9 -1
- data/vendor/faiss/faiss/IVFlib.cpp +14 -3
- data/vendor/faiss/faiss/Index.h +2 -2
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +9 -10
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +2 -3
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +1 -2
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +10 -12
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +5 -7
- data/vendor/faiss/faiss/IndexEDEN.cpp +273 -0
- data/vendor/faiss/faiss/IndexEDEN.h +57 -0
- data/vendor/faiss/faiss/IndexFastScan.cpp +15 -4
- data/vendor/faiss/faiss/IndexFlat.cpp +13 -50
- data/vendor/faiss/faiss/IndexHNSW.cpp +177 -148
- data/vendor/faiss/faiss/IndexIDMap.cpp +16 -3
- data/vendor/faiss/faiss/IndexIDMap.h +2 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +19 -8
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +3 -3
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +3 -4
- data/vendor/faiss/faiss/IndexIVFEDEN.cpp +302 -0
- data/vendor/faiss/faiss/IndexIVFEDEN.h +70 -0
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +5 -6
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +6 -5
- data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +3 -3
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +42 -25
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +2 -3
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +23 -62
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +180 -76
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -4
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +8 -6
- data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
- data/vendor/faiss/faiss/IndexLattice.cpp +5 -0
- data/vendor/faiss/faiss/IndexNNDescent.cpp +10 -3
- data/vendor/faiss/faiss/IndexNSG.cpp +8 -4
- data/vendor/faiss/faiss/IndexPQ.cpp +6 -8
- data/vendor/faiss/faiss/IndexPreTransform.cpp +15 -0
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +2 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +1 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +5 -1
- data/vendor/faiss/faiss/IndexRefine.cpp +30 -1
- data/vendor/faiss/faiss/IndexReplicas.cpp +1 -2
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +68 -6
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +10 -0
- data/vendor/faiss/faiss/IndexShards.cpp +2 -2
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +2 -2
- data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
- data/vendor/faiss/faiss/SuperKMeans.cpp +256 -240
- data/vendor/faiss/faiss/SuperKMeans.h +30 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +33 -2
- data/vendor/faiss/faiss/clone_index.cpp +5 -0
- data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +1 -1
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +902 -12
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +702 -10
- data/vendor/faiss/faiss/factory_tools.cpp +51 -4
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
- data/vendor/faiss/faiss/gpu/GpuIndex.h +34 -11
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +47 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +17 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +16 -0
- data/vendor/faiss/faiss/gpu/GpuResources.h +3 -2
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +11 -12
- data/vendor/faiss/faiss/gpu/StandardGpuResources.h +3 -3
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
- data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -2
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +180 -0
- data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +87 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +7 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +177 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -0
- data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +48 -3
- data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +45 -0
- data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFFlat.h +193 -0
- data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h +134 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +2 -2
- data/vendor/faiss/faiss/impl/DistanceComputer.h +34 -0
- data/vendor/faiss/faiss/impl/EDENQuantizer.h +119 -0
- data/vendor/faiss/faiss/impl/HNSW.cpp +658 -344
- data/vendor/faiss/faiss/impl/HNSW.h +51 -13
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/impl/NSG.cpp +18 -12
- data/vendor/faiss/faiss/impl/Panorama.h +20 -7
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +59 -24
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +45 -37
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +175 -68
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +19 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +2 -11
- data/vendor/faiss/faiss/impl/ResultHandler.h +26 -31
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +522 -58
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +70 -0
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
- data/vendor/faiss/faiss/impl/VisitedTable.cpp +33 -13
- data/vendor/faiss/faiss/impl/VisitedTable.h +88 -33
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +1 -1
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +38 -3
- data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
- data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +35 -43
- data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +64 -15
- data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +86 -40
- data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +81 -50
- data/vendor/faiss/faiss/impl/index_read.cpp +476 -75
- data/vendor/faiss/faiss/impl/index_write.cpp +56 -4
- data/vendor/faiss/faiss/impl/io_macros.h +25 -0
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
- data/vendor/faiss/faiss/impl/platform_macros.h +15 -9
- data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +284 -0
- data/vendor/faiss/faiss/impl/polysemous_training/dispatch.h +115 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +0 -1
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +26 -15
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +6 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +2 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +2 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +20 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +36 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +5 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +105 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +2 -0
- data/vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp +195 -0
- data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +133 -0
- data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +281 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +72 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +228 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +882 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +6 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +336 -26
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +331 -32
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +553 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +558 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +284 -45
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +502 -3
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +157 -32
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +26 -0
- data/vendor/faiss/faiss/impl/simd_dispatch.h +86 -8
- data/vendor/faiss/faiss/index_factory.cpp +37 -7
- data/vendor/faiss/faiss/index_io.h +16 -0
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +5 -2
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +15 -15
- data/vendor/faiss/faiss/invlists/InvertedLists.h +2 -2
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +19 -4
- data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +60 -0
- data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +26 -1
- data/vendor/faiss/faiss/svs/IndexSVSFlat.h +13 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +150 -23
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +30 -7
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +3 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +65 -25
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +3 -2
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
- data/vendor/faiss/faiss/utils/bf16.h +34 -0
- data/vendor/faiss/faiss/utils/distances.cpp +14 -2
- data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -4
- data/vendor/faiss/faiss/utils/extra_distances.cpp +4 -14
- data/vendor/faiss/faiss/utils/extra_distances.h +1 -2
- data/vendor/faiss/faiss/utils/hamming.cpp +9 -9
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +2 -1
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +15 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +6 -30
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_spr.h +171 -0
- data/vendor/faiss/faiss/utils/partitioning.cpp +0 -2
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +29 -8
- data/vendor/faiss/faiss/utils/rabitq_simd.h +202 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +0 -1
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +263 -15
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +160 -18
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_simdlib256.h +14 -68
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +273 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_spr.cpp +435 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +11 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +143 -6
- data/vendor/faiss/faiss/utils/simd_levels.cpp +56 -2
- data/vendor/faiss/faiss/utils/simd_levels.h +14 -0
- data/vendor/faiss/faiss/utils/utils.cpp +9 -27
- metadata +27 -2
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and 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/IndexIVFEDEN.h>
|
|
9
|
+
|
|
10
|
+
#include <omp.h>
|
|
11
|
+
|
|
12
|
+
#include <cstddef>
|
|
13
|
+
#include <cstdint>
|
|
14
|
+
#include <cstring>
|
|
15
|
+
#include <memory>
|
|
16
|
+
#include <vector>
|
|
17
|
+
|
|
18
|
+
#include <faiss/impl/EDENQuantizer.h>
|
|
19
|
+
#include <faiss/impl/FaissAssert.h>
|
|
20
|
+
#include <faiss/impl/expanded_scanners.h>
|
|
21
|
+
|
|
22
|
+
namespace faiss {
|
|
23
|
+
|
|
24
|
+
IndexIVFEDEN::IndexIVFEDEN(
|
|
25
|
+
Index* quantizer_in,
|
|
26
|
+
const size_t d_in,
|
|
27
|
+
const size_t nlist_in,
|
|
28
|
+
MetricType metric,
|
|
29
|
+
bool own_invlists_in,
|
|
30
|
+
uint8_t nb_bits_in,
|
|
31
|
+
EDENScaleType scale_type_in)
|
|
32
|
+
: IndexIVF(quantizer_in, d_in, nlist_in, 0, metric, own_invlists_in),
|
|
33
|
+
sq(d_in, eden_utils::quantizer_type_for_bits(nb_bits_in)),
|
|
34
|
+
scale_type(scale_type_in) {
|
|
35
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
36
|
+
scale_type == EDENScaleType_UNBIASED ||
|
|
37
|
+
scale_type == EDENScaleType_BIASED,
|
|
38
|
+
"invalid EDEN scale type");
|
|
39
|
+
sq.train(0, nullptr);
|
|
40
|
+
code_size = eden_utils::code_size(d, sq.bits);
|
|
41
|
+
if (own_invlists_in) {
|
|
42
|
+
invlists->code_size = code_size;
|
|
43
|
+
}
|
|
44
|
+
is_trained = false;
|
|
45
|
+
by_residual = true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
IndexIVFEDEN::IndexIVFEDEN() {
|
|
49
|
+
by_residual = true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
void IndexIVFEDEN::train_encoder(
|
|
53
|
+
idx_t n,
|
|
54
|
+
const float* x,
|
|
55
|
+
const idx_t* /*assign*/) {
|
|
56
|
+
sq.train(n, x);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
void IndexIVFEDEN::encode_vectors(
|
|
60
|
+
idx_t n,
|
|
61
|
+
const float* x,
|
|
62
|
+
const idx_t* list_nos,
|
|
63
|
+
uint8_t* codes,
|
|
64
|
+
bool include_listnos) const {
|
|
65
|
+
const size_t coarse_size = include_listnos ? coarse_code_size() : 0;
|
|
66
|
+
memset(codes, 0, (code_size + coarse_size) * n);
|
|
67
|
+
|
|
68
|
+
#pragma omp parallel if (n > 1000)
|
|
69
|
+
{
|
|
70
|
+
std::vector<float> centroid(d);
|
|
71
|
+
|
|
72
|
+
#pragma omp for
|
|
73
|
+
for (idx_t i = 0; i < n; i++) {
|
|
74
|
+
const int64_t list_no = list_nos[i];
|
|
75
|
+
if (list_no >= 0) {
|
|
76
|
+
const float* xi = x + i * d;
|
|
77
|
+
uint8_t* code = codes + i * (code_size + coarse_size);
|
|
78
|
+
|
|
79
|
+
quantizer->reconstruct(list_no, centroid.data());
|
|
80
|
+
eden_utils::compute_codes(
|
|
81
|
+
sq,
|
|
82
|
+
metric_type,
|
|
83
|
+
scale_type,
|
|
84
|
+
xi,
|
|
85
|
+
code + coarse_size,
|
|
86
|
+
1,
|
|
87
|
+
centroid.data());
|
|
88
|
+
|
|
89
|
+
if (coarse_size) {
|
|
90
|
+
encode_listno(list_no, code);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
void IndexIVFEDEN::decode_vectors(
|
|
98
|
+
idx_t n,
|
|
99
|
+
const uint8_t* codes,
|
|
100
|
+
const idx_t* listnos,
|
|
101
|
+
float* x) const {
|
|
102
|
+
#pragma omp parallel
|
|
103
|
+
{
|
|
104
|
+
std::vector<float> centroid(d);
|
|
105
|
+
|
|
106
|
+
#pragma omp for
|
|
107
|
+
for (idx_t i = 0; i < n; i++) {
|
|
108
|
+
const uint8_t* code = codes + i * code_size;
|
|
109
|
+
const int64_t list_no = listnos[i];
|
|
110
|
+
float* xi = x + i * d;
|
|
111
|
+
|
|
112
|
+
quantizer->reconstruct(list_no, centroid.data());
|
|
113
|
+
eden_utils::decode(sq, code, xi, 1, centroid.data());
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
void IndexIVFEDEN::add_core(
|
|
119
|
+
idx_t n,
|
|
120
|
+
const float* x,
|
|
121
|
+
const idx_t* xids,
|
|
122
|
+
const idx_t* precomputed_idx,
|
|
123
|
+
void* inverted_list_context) {
|
|
124
|
+
FAISS_THROW_IF_NOT(is_trained);
|
|
125
|
+
|
|
126
|
+
DirectMapAdd dm_add(direct_map, n, xids);
|
|
127
|
+
|
|
128
|
+
#pragma omp parallel
|
|
129
|
+
{
|
|
130
|
+
std::vector<uint8_t> one_code(code_size);
|
|
131
|
+
std::vector<float> centroid(d);
|
|
132
|
+
|
|
133
|
+
const int nt = omp_get_num_threads();
|
|
134
|
+
const int rank = omp_get_thread_num();
|
|
135
|
+
|
|
136
|
+
for (idx_t i = 0; i < n; i++) {
|
|
137
|
+
const int64_t list_no = precomputed_idx[i];
|
|
138
|
+
if (list_no >= 0 && list_no % nt == rank) {
|
|
139
|
+
const int64_t id = xids ? xids[i] : ntotal + i;
|
|
140
|
+
const float* xi = x + i * d;
|
|
141
|
+
|
|
142
|
+
quantizer->reconstruct(list_no, centroid.data());
|
|
143
|
+
eden_utils::compute_codes(
|
|
144
|
+
sq,
|
|
145
|
+
metric_type,
|
|
146
|
+
scale_type,
|
|
147
|
+
xi,
|
|
148
|
+
one_code.data(),
|
|
149
|
+
1,
|
|
150
|
+
centroid.data());
|
|
151
|
+
|
|
152
|
+
const size_t ofs = invlists->add_entry(
|
|
153
|
+
list_no, id, one_code.data(), inverted_list_context);
|
|
154
|
+
dm_add.add(i, list_no, ofs);
|
|
155
|
+
} else if (rank == 0 && list_no == -1) {
|
|
156
|
+
dm_add.add(i, -1, 0);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
ntotal += n;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
namespace {
|
|
165
|
+
|
|
166
|
+
struct EDENInvertedListScanner : InvertedListScanner {
|
|
167
|
+
using InvertedListScanner::scan_codes;
|
|
168
|
+
|
|
169
|
+
const IndexIVFEDEN& ivf_eden;
|
|
170
|
+
std::vector<float> reconstructed_centroid;
|
|
171
|
+
std::vector<float> query_vector;
|
|
172
|
+
std::unique_ptr<FlatCodesDistanceComputer> dc;
|
|
173
|
+
|
|
174
|
+
explicit EDENInvertedListScanner(
|
|
175
|
+
const IndexIVFEDEN& ivf_eden_in,
|
|
176
|
+
bool store_pairs_in = false,
|
|
177
|
+
const IDSelector* sel_in = nullptr)
|
|
178
|
+
: InvertedListScanner(store_pairs_in, sel_in),
|
|
179
|
+
ivf_eden(ivf_eden_in) {
|
|
180
|
+
keep_max = is_similarity_metric(ivf_eden.metric_type);
|
|
181
|
+
code_size = ivf_eden.code_size;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
void set_query(const float* query_vector_in) override {
|
|
185
|
+
query_vector.assign(query_vector_in, query_vector_in + ivf_eden.d);
|
|
186
|
+
internal_try_setup_dc();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
void set_list(idx_t list_no_in, float /*coarse_dis*/) override {
|
|
190
|
+
list_no = list_no_in;
|
|
191
|
+
|
|
192
|
+
reconstructed_centroid.resize(ivf_eden.d);
|
|
193
|
+
ivf_eden.quantizer->reconstruct(
|
|
194
|
+
list_no_in, reconstructed_centroid.data());
|
|
195
|
+
internal_try_setup_dc();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
float distance_to_code(const uint8_t* code) const final {
|
|
199
|
+
return dc->distance_to_code(code);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
size_t scan_codes(
|
|
203
|
+
size_t list_size,
|
|
204
|
+
const uint8_t* codes,
|
|
205
|
+
const idx_t* ids,
|
|
206
|
+
ResultHandler& handler) const override {
|
|
207
|
+
return run_scan_codes(*this, list_size, codes, ids, handler);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
void internal_try_setup_dc() {
|
|
211
|
+
if (!query_vector.empty() && !reconstructed_centroid.empty()) {
|
|
212
|
+
dc.reset(
|
|
213
|
+
eden_utils::get_distance_computer(
|
|
214
|
+
ivf_eden.sq,
|
|
215
|
+
ivf_eden.metric_type,
|
|
216
|
+
reconstructed_centroid.data()));
|
|
217
|
+
dc->set_query(query_vector.data());
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
} // namespace
|
|
223
|
+
|
|
224
|
+
InvertedListScanner* IndexIVFEDEN::get_InvertedListScanner(
|
|
225
|
+
bool store_pairs,
|
|
226
|
+
const IDSelector* sel,
|
|
227
|
+
const IVFSearchParameters* /*params*/) const {
|
|
228
|
+
return new EDENInvertedListScanner(*this, store_pairs, sel);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
void IndexIVFEDEN::reconstruct_from_offset(
|
|
232
|
+
int64_t list_no,
|
|
233
|
+
int64_t offset,
|
|
234
|
+
float* recons) const {
|
|
235
|
+
const uint8_t* code = invlists->get_single_code(list_no, offset);
|
|
236
|
+
|
|
237
|
+
std::vector<float> centroid(d);
|
|
238
|
+
quantizer->reconstruct(list_no, centroid.data());
|
|
239
|
+
eden_utils::decode(sq, code, recons, 1, centroid.data());
|
|
240
|
+
|
|
241
|
+
invlists->release_codes(list_no, code);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
void IndexIVFEDEN::sa_decode(idx_t n, const uint8_t* bytes, float* x) const {
|
|
245
|
+
const size_t coarse_size = coarse_code_size();
|
|
246
|
+
|
|
247
|
+
#pragma omp parallel
|
|
248
|
+
{
|
|
249
|
+
std::vector<float> centroid(d);
|
|
250
|
+
|
|
251
|
+
#pragma omp for
|
|
252
|
+
for (idx_t i = 0; i < n; i++) {
|
|
253
|
+
const uint8_t* code = bytes + i * (code_size + coarse_size);
|
|
254
|
+
const int64_t list_no = decode_listno(code);
|
|
255
|
+
float* xi = x + i * d;
|
|
256
|
+
|
|
257
|
+
quantizer->reconstruct(list_no, centroid.data());
|
|
258
|
+
eden_utils::decode(sq, code + coarse_size, xi, 1, centroid.data());
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
struct IVFEDENDistanceComputer : DistanceComputer {
|
|
264
|
+
const float* q = nullptr;
|
|
265
|
+
const IndexIVFEDEN* parent = nullptr;
|
|
266
|
+
|
|
267
|
+
void set_query(const float* x) override {
|
|
268
|
+
q = x;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
float operator()(idx_t i) override {
|
|
272
|
+
const idx_t lo = parent->direct_map.get(i);
|
|
273
|
+
const uint64_t list_no = lo_listno(lo);
|
|
274
|
+
const uint64_t offset = lo_offset(lo);
|
|
275
|
+
const uint8_t* code =
|
|
276
|
+
parent->invlists->get_single_code(list_no, offset);
|
|
277
|
+
|
|
278
|
+
std::vector<float> centroid(parent->d);
|
|
279
|
+
parent->quantizer->reconstruct(list_no, centroid.data());
|
|
280
|
+
|
|
281
|
+
std::unique_ptr<FlatCodesDistanceComputer> dc(
|
|
282
|
+
eden_utils::get_distance_computer(
|
|
283
|
+
parent->sq, parent->metric_type, centroid.data()));
|
|
284
|
+
dc->set_query(q);
|
|
285
|
+
const float distance = dc->distance_to_code(code);
|
|
286
|
+
|
|
287
|
+
parent->invlists->release_codes(list_no, code);
|
|
288
|
+
return distance;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
float symmetric_dis(idx_t /*i*/, idx_t /*j*/) override {
|
|
292
|
+
FAISS_THROW_MSG("Not implemented");
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
DistanceComputer* IndexIVFEDEN::get_distance_computer() const {
|
|
297
|
+
IVFEDENDistanceComputer* dc = new IVFEDENDistanceComputer;
|
|
298
|
+
dc->parent = this;
|
|
299
|
+
return dc;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
} // namespace faiss
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and 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 <cstddef>
|
|
11
|
+
#include <cstdint>
|
|
12
|
+
|
|
13
|
+
#include <faiss/IndexIVF.h>
|
|
14
|
+
#include <faiss/impl/EDENQuantizer.h>
|
|
15
|
+
|
|
16
|
+
namespace faiss {
|
|
17
|
+
|
|
18
|
+
struct IndexIVFEDEN : IndexIVF {
|
|
19
|
+
ScalarQuantizer sq;
|
|
20
|
+
EDENScaleType scale_type = EDENScaleType_UNBIASED;
|
|
21
|
+
|
|
22
|
+
// Factory strings: IVF<nlist>,EDEN, IVF<nlist>,EDEN<n>, and the same
|
|
23
|
+
// forms with the BIASED suffix for EDEN's MSE-minimizing scale.
|
|
24
|
+
IndexIVFEDEN(
|
|
25
|
+
Index* quantizer,
|
|
26
|
+
const size_t d,
|
|
27
|
+
const size_t nlist,
|
|
28
|
+
MetricType metric = METRIC_L2,
|
|
29
|
+
bool own_invlists = true,
|
|
30
|
+
uint8_t nb_bits = 1,
|
|
31
|
+
EDENScaleType scale_type = EDENScaleType_UNBIASED);
|
|
32
|
+
|
|
33
|
+
IndexIVFEDEN();
|
|
34
|
+
|
|
35
|
+
void train_encoder(idx_t n, const float* x, const idx_t* assign) override;
|
|
36
|
+
|
|
37
|
+
void encode_vectors(
|
|
38
|
+
idx_t n,
|
|
39
|
+
const float* x,
|
|
40
|
+
const idx_t* list_nos,
|
|
41
|
+
uint8_t* codes,
|
|
42
|
+
bool include_listnos = false) const override;
|
|
43
|
+
|
|
44
|
+
void decode_vectors(
|
|
45
|
+
idx_t n,
|
|
46
|
+
const uint8_t* codes,
|
|
47
|
+
const idx_t* list_nos,
|
|
48
|
+
float* x) const override;
|
|
49
|
+
|
|
50
|
+
void add_core(
|
|
51
|
+
idx_t n,
|
|
52
|
+
const float* x,
|
|
53
|
+
const idx_t* xids,
|
|
54
|
+
const idx_t* precomputed_idx,
|
|
55
|
+
void* inverted_list_context = nullptr) override;
|
|
56
|
+
|
|
57
|
+
InvertedListScanner* get_InvertedListScanner(
|
|
58
|
+
bool store_pairs,
|
|
59
|
+
const IDSelector* sel,
|
|
60
|
+
const IVFSearchParameters* params) const override;
|
|
61
|
+
|
|
62
|
+
void reconstruct_from_offset(int64_t list_no, int64_t offset, float* recons)
|
|
63
|
+
const override;
|
|
64
|
+
|
|
65
|
+
void sa_decode(idx_t n, const uint8_t* bytes, float* x) const override;
|
|
66
|
+
|
|
67
|
+
DistanceComputer* get_distance_computer() const override;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
} // namespace faiss
|
|
@@ -376,9 +376,8 @@ void IndexIVFFastScan::search_preassigned(
|
|
|
376
376
|
cur_nprobe = params->nprobe;
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
FAISS_THROW_IF_NOT_MSG(!stats, "stats not supported for this index");
|
|
379
|
+
FAISS_THROW_IF_MSG(store_pairs, "store_pairs not supported for this index");
|
|
380
|
+
FAISS_THROW_IF_MSG(stats, "stats not supported for this index");
|
|
382
381
|
FAISS_THROW_IF_NOT(k > 0);
|
|
383
382
|
FastScanDistancePostProcessing empty_context{};
|
|
384
383
|
|
|
@@ -404,8 +403,8 @@ void IndexIVFFastScan::range_search(
|
|
|
404
403
|
params->max_lists_num == 0,
|
|
405
404
|
"max_lists_num is a knn knob and is not honored by "
|
|
406
405
|
"fastscan range search");
|
|
407
|
-
|
|
408
|
-
|
|
406
|
+
FAISS_THROW_IF_MSG(
|
|
407
|
+
params->ensure_topk_full,
|
|
409
408
|
"ensure_topk_full is a knn knob and is not honored by "
|
|
410
409
|
"fastscan range search");
|
|
411
410
|
FAISS_THROW_IF_NOT_MSG(
|
|
@@ -1592,7 +1591,7 @@ void IndexIVFFastScan::reconstruct_from_offset(
|
|
|
1592
1591
|
}
|
|
1593
1592
|
|
|
1594
1593
|
void IndexIVFFastScan::reconstruct_orig_invlists() {
|
|
1595
|
-
FAISS_THROW_IF_NOT(orig_invlists
|
|
1594
|
+
FAISS_THROW_IF_NOT(orig_invlists);
|
|
1596
1595
|
FAISS_THROW_IF_NOT(orig_invlists->list_size(0) == 0);
|
|
1597
1596
|
|
|
1598
1597
|
#pragma omp parallel for if (nlist > 100)
|
|
@@ -65,7 +65,7 @@ void IndexIVFFlat::add_core(
|
|
|
65
65
|
void* inverted_list_context) {
|
|
66
66
|
FAISS_THROW_IF_NOT(is_trained);
|
|
67
67
|
FAISS_THROW_IF_NOT(coarse_idx);
|
|
68
|
-
|
|
68
|
+
FAISS_THROW_IF_MSG(by_residual, "by_residual not supported for this index");
|
|
69
69
|
FAISS_THROW_IF_NOT_MSG(invlists, "invlists not initialized");
|
|
70
70
|
direct_map.check_can_add(xids);
|
|
71
71
|
|
|
@@ -110,7 +110,7 @@ void IndexIVFFlat::encode_vectors(
|
|
|
110
110
|
const idx_t* list_nos,
|
|
111
111
|
uint8_t* codes,
|
|
112
112
|
bool include_listnos) const {
|
|
113
|
-
|
|
113
|
+
FAISS_THROW_IF_MSG(by_residual, "by_residual not supported for this index");
|
|
114
114
|
if (!include_listnos) {
|
|
115
115
|
memcpy(codes, x, code_size * n);
|
|
116
116
|
} else {
|
|
@@ -164,7 +164,9 @@ void IndexIVFFlat::reconstruct_from_offset(
|
|
|
164
164
|
int64_t list_no,
|
|
165
165
|
int64_t offset,
|
|
166
166
|
float* recons) const {
|
|
167
|
-
memcpy(recons,
|
|
167
|
+
memcpy(recons,
|
|
168
|
+
InvertedLists::ScopedCodes(invlists, list_no, offset).get(),
|
|
169
|
+
code_size);
|
|
168
170
|
}
|
|
169
171
|
|
|
170
172
|
/*****************************************
|
|
@@ -289,8 +291,7 @@ void IndexIVFFlatDedup::search_preassigned(
|
|
|
289
291
|
bool store_pairs,
|
|
290
292
|
const IVFSearchParameters* params,
|
|
291
293
|
IndexIVFStats* /*stats*/) const {
|
|
292
|
-
|
|
293
|
-
!store_pairs, "store_pairs not supported in IVFDedup");
|
|
294
|
+
FAISS_THROW_IF_MSG(store_pairs, "store_pairs not supported in IVFDedup");
|
|
294
295
|
|
|
295
296
|
IndexIVFFlat::search_preassigned(
|
|
296
297
|
n, x, k, assign, centroid_dis, distances, labels, false, params);
|
|
@@ -194,9 +194,9 @@ void IndexIVFFlatPanorama::reconstruct_from_offset(
|
|
|
194
194
|
int64_t list_no,
|
|
195
195
|
int64_t offset,
|
|
196
196
|
float* recons) const {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
memcpy(recons,
|
|
198
|
+
InvertedLists::ScopedCodes(invlists, list_no, offset).get(),
|
|
199
|
+
code_size);
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
} // namespace faiss
|
|
@@ -90,7 +90,7 @@ void IndexIVFIndependentQuantizer::search(
|
|
|
90
90
|
float* distances,
|
|
91
91
|
idx_t* labels,
|
|
92
92
|
const SearchParameters* params) const {
|
|
93
|
-
|
|
93
|
+
FAISS_THROW_IF_MSG(params, "search parameters not supported");
|
|
94
94
|
size_t nprobe = index_ivf->nprobe;
|
|
95
95
|
std::vector<float> D(n * nprobe);
|
|
96
96
|
std::vector<idx_t> I(n * nprobe);
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
#include <cstdint>
|
|
15
15
|
#include <cstdio>
|
|
16
16
|
|
|
17
|
+
#include <omp.h>
|
|
18
|
+
|
|
17
19
|
#include <algorithm>
|
|
18
20
|
|
|
19
21
|
#include <faiss/utils/distances_dispatch.h>
|
|
@@ -28,6 +30,7 @@
|
|
|
28
30
|
#include <faiss/impl/IDSelector.h>
|
|
29
31
|
#include <faiss/impl/ProductQuantizer.h>
|
|
30
32
|
#include <faiss/impl/ResultHandler.h>
|
|
33
|
+
// NOLINTNEXTLINE(facebook-hte-InlineHeader,facebook-unused-include-check)
|
|
31
34
|
#include <faiss/impl/pq_code_distance/pq_code_distance-generic.h>
|
|
32
35
|
#include <faiss/impl/simd_dispatch.h>
|
|
33
36
|
|
|
@@ -292,34 +295,49 @@ void IndexIVFPQ::add_core_o(
|
|
|
292
295
|
pq.compute_codes(to_encode, xcodes.get(), n);
|
|
293
296
|
|
|
294
297
|
double t2 = getmillisecs();
|
|
295
|
-
// TODO: parallelize?
|
|
296
298
|
size_t n_ignore = 0;
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
299
|
+
DirectMapAdd dm_adder(direct_map, n, xids);
|
|
300
|
+
|
|
301
|
+
#pragma omp parallel reduction(+ : n_ignore)
|
|
302
|
+
{
|
|
303
|
+
int nt = omp_get_num_threads();
|
|
304
|
+
int rank = omp_get_thread_num();
|
|
305
|
+
|
|
306
|
+
// each thread takes care of a subset of lists
|
|
307
|
+
for (idx_t i = 0; i < n; i++) {
|
|
308
|
+
idx_t key = idx[i];
|
|
309
|
+
if (key < 0) {
|
|
310
|
+
if (rank == 0) {
|
|
311
|
+
dm_adder.add(i, -1, 0);
|
|
312
|
+
n_ignore++;
|
|
313
|
+
if (residuals_2) {
|
|
314
|
+
memset(residuals_2 + i * d,
|
|
315
|
+
0,
|
|
316
|
+
sizeof(*residuals_2) * d);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
if (key % nt != rank) {
|
|
322
|
+
continue;
|
|
305
323
|
}
|
|
306
|
-
continue;
|
|
307
|
-
}
|
|
308
324
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
325
|
+
idx_t id = xids ? xids[i] : ntotal + i;
|
|
326
|
+
uint8_t* code = xcodes.get() + i * code_size;
|
|
327
|
+
size_t offset =
|
|
328
|
+
invlists->add_entry(key, id, code, inverted_list_context);
|
|
312
329
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
330
|
+
if (residuals_2) {
|
|
331
|
+
float* res2 = residuals_2 + i * d;
|
|
332
|
+
const float* xi = to_encode + i * d;
|
|
333
|
+
pq.decode(code, res2);
|
|
334
|
+
for (int j = 0; j < d; j++) {
|
|
335
|
+
res2[j] = xi[j] - res2[j];
|
|
336
|
+
}
|
|
319
337
|
}
|
|
320
|
-
}
|
|
321
338
|
|
|
322
|
-
|
|
339
|
+
dm_adder.add(i, key, offset);
|
|
340
|
+
}
|
|
323
341
|
}
|
|
324
342
|
|
|
325
343
|
double t3 = getmillisecs();
|
|
@@ -341,9 +359,8 @@ void IndexIVFPQ::reconstruct_from_offset(
|
|
|
341
359
|
int64_t list_no,
|
|
342
360
|
int64_t offset,
|
|
343
361
|
float* recons) const {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
pq.decode(code, recons);
|
|
362
|
+
InvertedLists::ScopedCodes sc(invlists, list_no, offset);
|
|
363
|
+
pq.decode(sc.get(), recons);
|
|
347
364
|
if (by_residual) {
|
|
348
365
|
std::vector<float> centroid(d);
|
|
349
366
|
quantizer->reconstruct(list_no, centroid.data());
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
#include <faiss/impl/FaissAssert.h>
|
|
17
17
|
#include <faiss/impl/ResultHandler.h>
|
|
18
18
|
#include <faiss/impl/simdlib/simdlib_dispatch.h>
|
|
19
|
-
#include <faiss/utils/distances.h>
|
|
20
19
|
#include <faiss/utils/distances_dispatch.h>
|
|
21
20
|
#include <faiss/utils/extra_distances.h>
|
|
22
21
|
|
|
@@ -187,9 +187,8 @@ void IndexIVFPQR::search_preassigned(
|
|
|
187
187
|
quantizer->compute_residual(xq, residual_1.get(), list_no);
|
|
188
188
|
|
|
189
189
|
// 2nd level residual
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
pq.decode(l2code, residual_2);
|
|
190
|
+
InvertedLists::ScopedCodes l2sc(invlists, list_no, ofs);
|
|
191
|
+
pq.decode(l2sc.get(), residual_2);
|
|
193
192
|
for (int l = 0; l < d; l++) {
|
|
194
193
|
residual_2[l] = residual_1[l] - residual_2[l];
|
|
195
194
|
}
|