faiss 0.2.6 → 0.3.0
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/ext/faiss/extconf.rb +1 -1
- data/lib/faiss/version.rb +1 -1
- data/lib/faiss.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +15 -4
- data/vendor/faiss/faiss/AutoTune.h +0 -1
- data/vendor/faiss/faiss/Clustering.cpp +1 -5
- data/vendor/faiss/faiss/Clustering.h +0 -2
- data/vendor/faiss/faiss/IVFlib.h +0 -2
- data/vendor/faiss/faiss/Index.h +1 -2
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +17 -3
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +10 -1
- data/vendor/faiss/faiss/IndexBinary.h +0 -1
- data/vendor/faiss/faiss/IndexBinaryFlat.cpp +2 -1
- data/vendor/faiss/faiss/IndexBinaryFlat.h +4 -0
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +1 -3
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +273 -48
- data/vendor/faiss/faiss/IndexBinaryIVF.h +18 -11
- data/vendor/faiss/faiss/IndexFastScan.cpp +13 -10
- data/vendor/faiss/faiss/IndexFastScan.h +5 -1
- data/vendor/faiss/faiss/IndexFlat.cpp +16 -3
- data/vendor/faiss/faiss/IndexFlat.h +1 -1
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +5 -0
- data/vendor/faiss/faiss/IndexFlatCodes.h +7 -2
- data/vendor/faiss/faiss/IndexHNSW.cpp +3 -6
- data/vendor/faiss/faiss/IndexHNSW.h +0 -1
- data/vendor/faiss/faiss/IndexIDMap.cpp +4 -4
- data/vendor/faiss/faiss/IndexIDMap.h +0 -2
- data/vendor/faiss/faiss/IndexIVF.cpp +155 -129
- data/vendor/faiss/faiss/IndexIVF.h +121 -61
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +12 -11
- data/vendor/faiss/faiss/IndexIVFFastScan.h +6 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +221 -165
- data/vendor/faiss/faiss/IndexIVFPQ.h +1 -0
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +6 -1
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +0 -2
- data/vendor/faiss/faiss/IndexNNDescent.cpp +1 -2
- data/vendor/faiss/faiss/IndexNNDescent.h +0 -1
- data/vendor/faiss/faiss/IndexNSG.cpp +1 -2
- data/vendor/faiss/faiss/IndexPQ.cpp +7 -9
- data/vendor/faiss/faiss/IndexRefine.cpp +1 -1
- data/vendor/faiss/faiss/IndexReplicas.cpp +3 -4
- data/vendor/faiss/faiss/IndexReplicas.h +0 -1
- data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +8 -1
- data/vendor/faiss/faiss/IndexRowwiseMinMax.h +7 -0
- data/vendor/faiss/faiss/IndexShards.cpp +26 -109
- data/vendor/faiss/faiss/IndexShards.h +2 -3
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +246 -0
- data/vendor/faiss/faiss/IndexShardsIVF.h +42 -0
- data/vendor/faiss/faiss/MetaIndexes.cpp +86 -0
- data/vendor/faiss/faiss/MetaIndexes.h +29 -0
- data/vendor/faiss/faiss/MetricType.h +14 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +8 -10
- data/vendor/faiss/faiss/VectorTransform.h +1 -3
- data/vendor/faiss/faiss/clone_index.cpp +232 -18
- data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +25 -3
- data/vendor/faiss/faiss/cppcontrib/detail/CoarseBitType.h +7 -0
- data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +78 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +20 -6
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +7 -1
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +21 -7
- data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMax-inl.h +7 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMaxFP16-inl.h +7 -0
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +10 -3
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +7 -1
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +11 -3
- data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +25 -2
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +76 -29
- data/vendor/faiss/faiss/gpu/GpuCloner.h +2 -2
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +14 -13
- data/vendor/faiss/faiss/gpu/GpuDistance.h +18 -6
- data/vendor/faiss/faiss/gpu/GpuIndex.h +23 -21
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +10 -10
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -12
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +29 -50
- data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +3 -3
- data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +8 -8
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +4 -4
- data/vendor/faiss/faiss/gpu/impl/IndexUtils.h +2 -5
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +9 -7
- data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +4 -4
- data/vendor/faiss/faiss/gpu/perf/IndexWrapper-inl.h +2 -2
- data/vendor/faiss/faiss/gpu/perf/IndexWrapper.h +1 -1
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +55 -6
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +20 -6
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +95 -25
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +67 -16
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +4 -4
- data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +7 -7
- data/vendor/faiss/faiss/gpu/test/TestUtils.h +4 -4
- data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +1 -1
- data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +6 -0
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +0 -7
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +9 -9
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +1 -1
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +2 -7
- data/vendor/faiss/faiss/impl/CodePacker.cpp +67 -0
- data/vendor/faiss/faiss/impl/CodePacker.h +71 -0
- data/vendor/faiss/faiss/impl/DistanceComputer.h +0 -2
- data/vendor/faiss/faiss/impl/HNSW.cpp +3 -7
- data/vendor/faiss/faiss/impl/HNSW.h +6 -9
- data/vendor/faiss/faiss/impl/IDSelector.cpp +1 -1
- data/vendor/faiss/faiss/impl/IDSelector.h +39 -1
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +62 -51
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +11 -12
- data/vendor/faiss/faiss/impl/NNDescent.cpp +3 -9
- data/vendor/faiss/faiss/impl/NNDescent.h +10 -10
- data/vendor/faiss/faiss/impl/NSG.cpp +1 -6
- data/vendor/faiss/faiss/impl/NSG.h +4 -7
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +1 -15
- data/vendor/faiss/faiss/impl/PolysemousTraining.h +11 -10
- data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +0 -7
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +25 -12
- data/vendor/faiss/faiss/impl/ProductQuantizer.h +2 -4
- data/vendor/faiss/faiss/impl/Quantizer.h +6 -3
- data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +796 -174
- data/vendor/faiss/faiss/impl/ResidualQuantizer.h +16 -8
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +3 -5
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +4 -4
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +3 -3
- data/vendor/faiss/faiss/impl/ThreadedIndex.h +4 -4
- data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +291 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +74 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance.h +123 -0
- data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +102 -0
- data/vendor/faiss/faiss/impl/index_read.cpp +13 -10
- data/vendor/faiss/faiss/impl/index_write.cpp +3 -4
- data/vendor/faiss/faiss/impl/kmeans1d.cpp +0 -1
- data/vendor/faiss/faiss/impl/kmeans1d.h +3 -3
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -1
- data/vendor/faiss/faiss/impl/platform_macros.h +61 -0
- data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +48 -4
- data/vendor/faiss/faiss/impl/pq4_fast_scan.h +18 -4
- data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +2 -2
- data/vendor/faiss/faiss/index_factory.cpp +8 -10
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +29 -12
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +8 -2
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
- data/vendor/faiss/faiss/invlists/DirectMap.h +2 -4
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +118 -18
- data/vendor/faiss/faiss/invlists/InvertedLists.h +44 -4
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +3 -3
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
- data/vendor/faiss/faiss/python/python_callbacks.cpp +1 -1
- data/vendor/faiss/faiss/python/python_callbacks.h +1 -1
- data/vendor/faiss/faiss/utils/AlignedTable.h +3 -1
- data/vendor/faiss/faiss/utils/Heap.cpp +139 -3
- data/vendor/faiss/faiss/utils/Heap.h +35 -1
- data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +84 -0
- data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +196 -0
- data/vendor/faiss/faiss/utils/approx_topk/generic.h +138 -0
- data/vendor/faiss/faiss/utils/approx_topk/mode.h +34 -0
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +367 -0
- data/vendor/faiss/faiss/utils/distances.cpp +61 -7
- data/vendor/faiss/faiss/utils/distances.h +11 -0
- data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +346 -0
- data/vendor/faiss/faiss/utils/distances_fused/avx512.h +36 -0
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +42 -0
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +40 -0
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +352 -0
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.h +32 -0
- data/vendor/faiss/faiss/utils/distances_simd.cpp +515 -327
- data/vendor/faiss/faiss/utils/extra_distances-inl.h +17 -1
- data/vendor/faiss/faiss/utils/extra_distances.cpp +37 -8
- data/vendor/faiss/faiss/utils/extra_distances.h +2 -1
- data/vendor/faiss/faiss/utils/fp16-fp16c.h +7 -0
- data/vendor/faiss/faiss/utils/fp16-inl.h +7 -0
- data/vendor/faiss/faiss/utils/fp16.h +7 -0
- data/vendor/faiss/faiss/utils/hamming-inl.h +0 -456
- data/vendor/faiss/faiss/utils/hamming.cpp +104 -120
- data/vendor/faiss/faiss/utils/hamming.h +21 -10
- data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +535 -0
- data/vendor/faiss/faiss/utils/hamming_distance/common.h +48 -0
- data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +519 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +26 -0
- data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +614 -0
- data/vendor/faiss/faiss/utils/partitioning.cpp +21 -25
- data/vendor/faiss/faiss/utils/simdlib_avx2.h +344 -3
- data/vendor/faiss/faiss/utils/simdlib_emulated.h +390 -0
- data/vendor/faiss/faiss/utils/simdlib_neon.h +655 -130
- data/vendor/faiss/faiss/utils/sorting.cpp +692 -0
- data/vendor/faiss/faiss/utils/sorting.h +71 -0
- data/vendor/faiss/faiss/utils/transpose/transpose-avx2-inl.h +165 -0
- data/vendor/faiss/faiss/utils/utils.cpp +4 -176
- data/vendor/faiss/faiss/utils/utils.h +2 -9
- metadata +30 -4
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.cpp +0 -26
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
/** In this file are the implementations of extra metrics beyond L2
|
|
9
9
|
* and inner product */
|
|
10
10
|
|
|
11
|
+
#include <faiss/MetricType.h>
|
|
11
12
|
#include <faiss/utils/distances.h>
|
|
12
13
|
#include <type_traits>
|
|
13
14
|
|
|
@@ -17,12 +18,13 @@ template <MetricType mt>
|
|
|
17
18
|
struct VectorDistance {
|
|
18
19
|
size_t d;
|
|
19
20
|
float metric_arg;
|
|
21
|
+
static constexpr bool is_similarity = is_similarity_metric(mt);
|
|
20
22
|
|
|
21
23
|
inline float operator()(const float* x, const float* y) const;
|
|
22
24
|
|
|
23
25
|
// heap template to use for this type of metric
|
|
24
26
|
using C = typename std::conditional<
|
|
25
|
-
mt
|
|
27
|
+
is_similarity_metric(mt),
|
|
26
28
|
CMin<float, int64_t>,
|
|
27
29
|
CMax<float, int64_t>>::type;
|
|
28
30
|
};
|
|
@@ -114,4 +116,18 @@ inline float VectorDistance<METRIC_JensenShannon>::operator()(
|
|
|
114
116
|
return 0.5 * accu;
|
|
115
117
|
}
|
|
116
118
|
|
|
119
|
+
template <>
|
|
120
|
+
inline float VectorDistance<METRIC_Jaccard>::operator()(
|
|
121
|
+
const float* x,
|
|
122
|
+
const float* y) const {
|
|
123
|
+
// WARNING: this distance is defined only for positive input vectors.
|
|
124
|
+
// Providing vectors with negative values would lead to incorrect results.
|
|
125
|
+
float accu_num = 0, accu_den = 0;
|
|
126
|
+
for (size_t i = 0; i < d; i++) {
|
|
127
|
+
accu_num += fmin(x[i], y[i]);
|
|
128
|
+
accu_den += fmax(x[i], y[i]);
|
|
129
|
+
}
|
|
130
|
+
return accu_num / accu_den;
|
|
131
|
+
}
|
|
132
|
+
|
|
117
133
|
} // namespace faiss
|
|
@@ -50,14 +50,14 @@ void pairwise_extra_distances_template(
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
template <class VD>
|
|
53
|
+
template <class VD, class C>
|
|
54
54
|
void knn_extra_metrics_template(
|
|
55
55
|
VD vd,
|
|
56
56
|
const float* x,
|
|
57
57
|
const float* y,
|
|
58
58
|
size_t nx,
|
|
59
59
|
size_t ny,
|
|
60
|
-
|
|
60
|
+
HeapArray<C>* res) {
|
|
61
61
|
size_t k = res->k;
|
|
62
62
|
size_t d = vd.d;
|
|
63
63
|
size_t check_period = InterruptCallback::get_period_hint(ny * d);
|
|
@@ -74,16 +74,21 @@ void knn_extra_metrics_template(
|
|
|
74
74
|
float* simi = res->get_val(i);
|
|
75
75
|
int64_t* idxi = res->get_ids(i);
|
|
76
76
|
|
|
77
|
-
maxheap_heapify(k, simi, idxi);
|
|
77
|
+
// maxheap_heapify(k, simi, idxi);
|
|
78
|
+
heap_heapify<C>(k, simi, idxi);
|
|
78
79
|
for (j = 0; j < ny; j++) {
|
|
79
80
|
float disij = vd(x_i, y_j);
|
|
80
81
|
|
|
81
|
-
if (disij < simi[0]) {
|
|
82
|
-
|
|
82
|
+
// if (disij < simi[0]) {
|
|
83
|
+
if ((!vd.is_similarity && (disij < simi[0])) ||
|
|
84
|
+
(vd.is_similarity && (disij > simi[0]))) {
|
|
85
|
+
// maxheap_replace_top(k, simi, idxi, disij, j);
|
|
86
|
+
heap_replace_top<C>(k, simi, idxi, disij, j);
|
|
83
87
|
}
|
|
84
88
|
y_j += d;
|
|
85
89
|
}
|
|
86
|
-
maxheap_reorder(k, simi, idxi);
|
|
90
|
+
// maxheap_reorder(k, simi, idxi);
|
|
91
|
+
heap_reorder<C>(k, simi, idxi);
|
|
87
92
|
}
|
|
88
93
|
InterruptCallback::check();
|
|
89
94
|
}
|
|
@@ -92,7 +97,7 @@ void knn_extra_metrics_template(
|
|
|
92
97
|
template <class VD>
|
|
93
98
|
struct ExtraDistanceComputer : FlatCodesDistanceComputer {
|
|
94
99
|
VD vd;
|
|
95
|
-
|
|
100
|
+
idx_t nb;
|
|
96
101
|
const float* q;
|
|
97
102
|
const float* b;
|
|
98
103
|
|
|
@@ -158,12 +163,14 @@ void pairwise_extra_distances(
|
|
|
158
163
|
HANDLE_VAR(BrayCurtis);
|
|
159
164
|
HANDLE_VAR(JensenShannon);
|
|
160
165
|
HANDLE_VAR(Lp);
|
|
166
|
+
HANDLE_VAR(Jaccard);
|
|
161
167
|
#undef HANDLE_VAR
|
|
162
168
|
default:
|
|
163
169
|
FAISS_THROW_MSG("metric type not implemented");
|
|
164
170
|
}
|
|
165
171
|
}
|
|
166
172
|
|
|
173
|
+
template <class C>
|
|
167
174
|
void knn_extra_metrics(
|
|
168
175
|
const float* x,
|
|
169
176
|
const float* y,
|
|
@@ -172,7 +179,7 @@ void knn_extra_metrics(
|
|
|
172
179
|
size_t ny,
|
|
173
180
|
MetricType mt,
|
|
174
181
|
float metric_arg,
|
|
175
|
-
|
|
182
|
+
HeapArray<C>* res) {
|
|
176
183
|
switch (mt) {
|
|
177
184
|
#define HANDLE_VAR(kw) \
|
|
178
185
|
case METRIC_##kw: { \
|
|
@@ -187,12 +194,33 @@ void knn_extra_metrics(
|
|
|
187
194
|
HANDLE_VAR(BrayCurtis);
|
|
188
195
|
HANDLE_VAR(JensenShannon);
|
|
189
196
|
HANDLE_VAR(Lp);
|
|
197
|
+
HANDLE_VAR(Jaccard);
|
|
190
198
|
#undef HANDLE_VAR
|
|
191
199
|
default:
|
|
192
200
|
FAISS_THROW_MSG("metric type not implemented");
|
|
193
201
|
}
|
|
194
202
|
}
|
|
195
203
|
|
|
204
|
+
template void knn_extra_metrics<CMax<float, int64_t>>(
|
|
205
|
+
const float* x,
|
|
206
|
+
const float* y,
|
|
207
|
+
size_t d,
|
|
208
|
+
size_t nx,
|
|
209
|
+
size_t ny,
|
|
210
|
+
MetricType mt,
|
|
211
|
+
float metric_arg,
|
|
212
|
+
HeapArray<CMax<float, int64_t>>* res);
|
|
213
|
+
|
|
214
|
+
template void knn_extra_metrics<CMin<float, int64_t>>(
|
|
215
|
+
const float* x,
|
|
216
|
+
const float* y,
|
|
217
|
+
size_t d,
|
|
218
|
+
size_t nx,
|
|
219
|
+
size_t ny,
|
|
220
|
+
MetricType mt,
|
|
221
|
+
float metric_arg,
|
|
222
|
+
HeapArray<CMin<float, int64_t>>* res);
|
|
223
|
+
|
|
196
224
|
FlatCodesDistanceComputer* get_extra_distance_computer(
|
|
197
225
|
size_t d,
|
|
198
226
|
MetricType mt,
|
|
@@ -213,6 +241,7 @@ FlatCodesDistanceComputer* get_extra_distance_computer(
|
|
|
213
241
|
HANDLE_VAR(BrayCurtis);
|
|
214
242
|
HANDLE_VAR(JensenShannon);
|
|
215
243
|
HANDLE_VAR(Lp);
|
|
244
|
+
HANDLE_VAR(Jaccard);
|
|
216
245
|
#undef HANDLE_VAR
|
|
217
246
|
default:
|
|
218
247
|
FAISS_THROW_MSG("metric type not implemented");
|
|
@@ -33,6 +33,7 @@ void pairwise_extra_distances(
|
|
|
33
33
|
int64_t ldb = -1,
|
|
34
34
|
int64_t ldd = -1);
|
|
35
35
|
|
|
36
|
+
template <class C>
|
|
36
37
|
void knn_extra_metrics(
|
|
37
38
|
const float* x,
|
|
38
39
|
const float* y,
|
|
@@ -41,7 +42,7 @@ void knn_extra_metrics(
|
|
|
41
42
|
size_t ny,
|
|
42
43
|
MetricType mt,
|
|
43
44
|
float metric_arg,
|
|
44
|
-
|
|
45
|
+
HeapArray<C>* res);
|
|
45
46
|
|
|
46
47
|
/** get a DistanceComputer that refers to this type of distance and
|
|
47
48
|
* indexes a flat array of size nb */
|
|
@@ -7,61 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
namespace faiss {
|
|
9
9
|
|
|
10
|
-
extern const uint8_t hamdis_tab_ham_bytes[256];
|
|
11
|
-
|
|
12
|
-
/* Elementary Hamming distance computation: unoptimized */
|
|
13
|
-
template <size_t nbits, typename T>
|
|
14
|
-
inline T hamming(const uint8_t* bs1, const uint8_t* bs2) {
|
|
15
|
-
const size_t nbytes = nbits / 8;
|
|
16
|
-
size_t i;
|
|
17
|
-
T h = 0;
|
|
18
|
-
for (i = 0; i < nbytes; i++) {
|
|
19
|
-
h += (T)hamdis_tab_ham_bytes[bs1[i] ^ bs2[i]];
|
|
20
|
-
}
|
|
21
|
-
return h;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* Hamming distances for multiples of 64 bits */
|
|
25
|
-
template <size_t nbits>
|
|
26
|
-
inline hamdis_t hamming(const uint64_t* bs1, const uint64_t* bs2) {
|
|
27
|
-
const size_t nwords = nbits / 64;
|
|
28
|
-
size_t i;
|
|
29
|
-
hamdis_t h = 0;
|
|
30
|
-
for (i = 0; i < nwords; i++) {
|
|
31
|
-
h += popcount64(bs1[i] ^ bs2[i]);
|
|
32
|
-
}
|
|
33
|
-
return h;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/* specialized (optimized) functions */
|
|
37
|
-
template <>
|
|
38
|
-
inline hamdis_t hamming<64>(const uint64_t* pa, const uint64_t* pb) {
|
|
39
|
-
return popcount64(pa[0] ^ pb[0]);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
template <>
|
|
43
|
-
inline hamdis_t hamming<128>(const uint64_t* pa, const uint64_t* pb) {
|
|
44
|
-
return popcount64(pa[0] ^ pb[0]) + popcount64(pa[1] ^ pb[1]);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
template <>
|
|
48
|
-
inline hamdis_t hamming<256>(const uint64_t* pa, const uint64_t* pb) {
|
|
49
|
-
return popcount64(pa[0] ^ pb[0]) + popcount64(pa[1] ^ pb[1]) +
|
|
50
|
-
popcount64(pa[2] ^ pb[2]) + popcount64(pa[3] ^ pb[3]);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/* Hamming distances for multiple of 64 bits */
|
|
54
|
-
inline hamdis_t hamming(
|
|
55
|
-
const uint64_t* bs1,
|
|
56
|
-
const uint64_t* bs2,
|
|
57
|
-
size_t nwords) {
|
|
58
|
-
hamdis_t h = 0;
|
|
59
|
-
for (size_t i = 0; i < nwords; i++) {
|
|
60
|
-
h += popcount64(bs1[i] ^ bs2[i]);
|
|
61
|
-
}
|
|
62
|
-
return h;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
10
|
// BitstringWriter and BitstringReader functions
|
|
66
11
|
inline BitstringWriter::BitstringWriter(uint8_t* code, size_t code_size)
|
|
67
12
|
: code(code), code_size(code_size), i(0) {
|
|
@@ -119,407 +64,6 @@ inline uint64_t BitstringReader::read(int nbit) {
|
|
|
119
64
|
}
|
|
120
65
|
}
|
|
121
66
|
|
|
122
|
-
/******************************************************************
|
|
123
|
-
* The HammingComputer series of classes compares a single code of
|
|
124
|
-
* size 4 to 32 to incoming codes. They are intended for use as a
|
|
125
|
-
* template class where it would be inefficient to switch on the code
|
|
126
|
-
* size in the inner loop. Hopefully the compiler will inline the
|
|
127
|
-
* hamming() functions and put the a0, a1, ... in registers.
|
|
128
|
-
******************************************************************/
|
|
129
|
-
|
|
130
|
-
struct HammingComputer4 {
|
|
131
|
-
uint32_t a0;
|
|
132
|
-
|
|
133
|
-
HammingComputer4() {}
|
|
134
|
-
|
|
135
|
-
HammingComputer4(const uint8_t* a, int code_size) {
|
|
136
|
-
set(a, code_size);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
void set(const uint8_t* a, int code_size) {
|
|
140
|
-
assert(code_size == 4);
|
|
141
|
-
a0 = *(uint32_t*)a;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
inline int hamming(const uint8_t* b) const {
|
|
145
|
-
return popcount64(*(uint32_t*)b ^ a0);
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
struct HammingComputer8 {
|
|
150
|
-
uint64_t a0;
|
|
151
|
-
|
|
152
|
-
HammingComputer8() {}
|
|
153
|
-
|
|
154
|
-
HammingComputer8(const uint8_t* a, int code_size) {
|
|
155
|
-
set(a, code_size);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
void set(const uint8_t* a, int code_size) {
|
|
159
|
-
assert(code_size == 8);
|
|
160
|
-
a0 = *(uint64_t*)a;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
inline int hamming(const uint8_t* b) const {
|
|
164
|
-
return popcount64(*(uint64_t*)b ^ a0);
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
struct HammingComputer16 {
|
|
169
|
-
uint64_t a0, a1;
|
|
170
|
-
|
|
171
|
-
HammingComputer16() {}
|
|
172
|
-
|
|
173
|
-
HammingComputer16(const uint8_t* a8, int code_size) {
|
|
174
|
-
set(a8, code_size);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
void set(const uint8_t* a8, int code_size) {
|
|
178
|
-
assert(code_size == 16);
|
|
179
|
-
const uint64_t* a = (uint64_t*)a8;
|
|
180
|
-
a0 = a[0];
|
|
181
|
-
a1 = a[1];
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
inline int hamming(const uint8_t* b8) const {
|
|
185
|
-
const uint64_t* b = (uint64_t*)b8;
|
|
186
|
-
return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1);
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
// when applied to an array, 1/2 of the 64-bit accesses are unaligned.
|
|
191
|
-
// This incurs a penalty of ~10% wrt. fully aligned accesses.
|
|
192
|
-
struct HammingComputer20 {
|
|
193
|
-
uint64_t a0, a1;
|
|
194
|
-
uint32_t a2;
|
|
195
|
-
|
|
196
|
-
HammingComputer20() {}
|
|
197
|
-
|
|
198
|
-
HammingComputer20(const uint8_t* a8, int code_size) {
|
|
199
|
-
set(a8, code_size);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
void set(const uint8_t* a8, int code_size) {
|
|
203
|
-
assert(code_size == 20);
|
|
204
|
-
const uint64_t* a = (uint64_t*)a8;
|
|
205
|
-
a0 = a[0];
|
|
206
|
-
a1 = a[1];
|
|
207
|
-
a2 = a[2];
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
inline int hamming(const uint8_t* b8) const {
|
|
211
|
-
const uint64_t* b = (uint64_t*)b8;
|
|
212
|
-
return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
|
|
213
|
-
popcount64(*(uint32_t*)(b + 2) ^ a2);
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
struct HammingComputer32 {
|
|
218
|
-
uint64_t a0, a1, a2, a3;
|
|
219
|
-
|
|
220
|
-
HammingComputer32() {}
|
|
221
|
-
|
|
222
|
-
HammingComputer32(const uint8_t* a8, int code_size) {
|
|
223
|
-
set(a8, code_size);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
void set(const uint8_t* a8, int code_size) {
|
|
227
|
-
assert(code_size == 32);
|
|
228
|
-
const uint64_t* a = (uint64_t*)a8;
|
|
229
|
-
a0 = a[0];
|
|
230
|
-
a1 = a[1];
|
|
231
|
-
a2 = a[2];
|
|
232
|
-
a3 = a[3];
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
inline int hamming(const uint8_t* b8) const {
|
|
236
|
-
const uint64_t* b = (uint64_t*)b8;
|
|
237
|
-
return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
|
|
238
|
-
popcount64(b[2] ^ a2) + popcount64(b[3] ^ a3);
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
struct HammingComputer64 {
|
|
243
|
-
uint64_t a0, a1, a2, a3, a4, a5, a6, a7;
|
|
244
|
-
|
|
245
|
-
HammingComputer64() {}
|
|
246
|
-
|
|
247
|
-
HammingComputer64(const uint8_t* a8, int code_size) {
|
|
248
|
-
set(a8, code_size);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
void set(const uint8_t* a8, int code_size) {
|
|
252
|
-
assert(code_size == 64);
|
|
253
|
-
const uint64_t* a = (uint64_t*)a8;
|
|
254
|
-
a0 = a[0];
|
|
255
|
-
a1 = a[1];
|
|
256
|
-
a2 = a[2];
|
|
257
|
-
a3 = a[3];
|
|
258
|
-
a4 = a[4];
|
|
259
|
-
a5 = a[5];
|
|
260
|
-
a6 = a[6];
|
|
261
|
-
a7 = a[7];
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
inline int hamming(const uint8_t* b8) const {
|
|
265
|
-
const uint64_t* b = (uint64_t*)b8;
|
|
266
|
-
return popcount64(b[0] ^ a0) + popcount64(b[1] ^ a1) +
|
|
267
|
-
popcount64(b[2] ^ a2) + popcount64(b[3] ^ a3) +
|
|
268
|
-
popcount64(b[4] ^ a4) + popcount64(b[5] ^ a5) +
|
|
269
|
-
popcount64(b[6] ^ a6) + popcount64(b[7] ^ a7);
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
struct HammingComputerDefault {
|
|
274
|
-
const uint8_t* a8;
|
|
275
|
-
int quotient8;
|
|
276
|
-
int remainder8;
|
|
277
|
-
|
|
278
|
-
HammingComputerDefault() {}
|
|
279
|
-
|
|
280
|
-
HammingComputerDefault(const uint8_t* a8, int code_size) {
|
|
281
|
-
set(a8, code_size);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
void set(const uint8_t* a8, int code_size) {
|
|
285
|
-
this->a8 = a8;
|
|
286
|
-
quotient8 = code_size / 8;
|
|
287
|
-
remainder8 = code_size % 8;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
int hamming(const uint8_t* b8) const {
|
|
291
|
-
int accu = 0;
|
|
292
|
-
|
|
293
|
-
const uint64_t* a64 = reinterpret_cast<const uint64_t*>(a8);
|
|
294
|
-
const uint64_t* b64 = reinterpret_cast<const uint64_t*>(b8);
|
|
295
|
-
int i = 0, len = quotient8;
|
|
296
|
-
switch (len & 7) {
|
|
297
|
-
default:
|
|
298
|
-
while (len > 7) {
|
|
299
|
-
len -= 8;
|
|
300
|
-
accu += popcount64(a64[i] ^ b64[i]);
|
|
301
|
-
i++;
|
|
302
|
-
case 7:
|
|
303
|
-
accu += popcount64(a64[i] ^ b64[i]);
|
|
304
|
-
i++;
|
|
305
|
-
case 6:
|
|
306
|
-
accu += popcount64(a64[i] ^ b64[i]);
|
|
307
|
-
i++;
|
|
308
|
-
case 5:
|
|
309
|
-
accu += popcount64(a64[i] ^ b64[i]);
|
|
310
|
-
i++;
|
|
311
|
-
case 4:
|
|
312
|
-
accu += popcount64(a64[i] ^ b64[i]);
|
|
313
|
-
i++;
|
|
314
|
-
case 3:
|
|
315
|
-
accu += popcount64(a64[i] ^ b64[i]);
|
|
316
|
-
i++;
|
|
317
|
-
case 2:
|
|
318
|
-
accu += popcount64(a64[i] ^ b64[i]);
|
|
319
|
-
i++;
|
|
320
|
-
case 1:
|
|
321
|
-
accu += popcount64(a64[i] ^ b64[i]);
|
|
322
|
-
i++;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
if (remainder8) {
|
|
326
|
-
const uint8_t* a = a8 + 8 * quotient8;
|
|
327
|
-
const uint8_t* b = b8 + 8 * quotient8;
|
|
328
|
-
switch (remainder8) {
|
|
329
|
-
case 7:
|
|
330
|
-
accu += hamdis_tab_ham_bytes[a[6] ^ b[6]];
|
|
331
|
-
case 6:
|
|
332
|
-
accu += hamdis_tab_ham_bytes[a[5] ^ b[5]];
|
|
333
|
-
case 5:
|
|
334
|
-
accu += hamdis_tab_ham_bytes[a[4] ^ b[4]];
|
|
335
|
-
case 4:
|
|
336
|
-
accu += hamdis_tab_ham_bytes[a[3] ^ b[3]];
|
|
337
|
-
case 3:
|
|
338
|
-
accu += hamdis_tab_ham_bytes[a[2] ^ b[2]];
|
|
339
|
-
case 2:
|
|
340
|
-
accu += hamdis_tab_ham_bytes[a[1] ^ b[1]];
|
|
341
|
-
case 1:
|
|
342
|
-
accu += hamdis_tab_ham_bytes[a[0] ^ b[0]];
|
|
343
|
-
default:
|
|
344
|
-
break;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
return accu;
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
// more inefficient than HammingComputerDefault (obsolete)
|
|
353
|
-
struct HammingComputerM8 {
|
|
354
|
-
const uint64_t* a;
|
|
355
|
-
int n;
|
|
356
|
-
|
|
357
|
-
HammingComputerM8() {}
|
|
358
|
-
|
|
359
|
-
HammingComputerM8(const uint8_t* a8, int code_size) {
|
|
360
|
-
set(a8, code_size);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
void set(const uint8_t* a8, int code_size) {
|
|
364
|
-
assert(code_size % 8 == 0);
|
|
365
|
-
a = (uint64_t*)a8;
|
|
366
|
-
n = code_size / 8;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
int hamming(const uint8_t* b8) const {
|
|
370
|
-
const uint64_t* b = (uint64_t*)b8;
|
|
371
|
-
int accu = 0;
|
|
372
|
-
for (int i = 0; i < n; i++)
|
|
373
|
-
accu += popcount64(a[i] ^ b[i]);
|
|
374
|
-
return accu;
|
|
375
|
-
}
|
|
376
|
-
};
|
|
377
|
-
|
|
378
|
-
// more inefficient than HammingComputerDefault (obsolete)
|
|
379
|
-
struct HammingComputerM4 {
|
|
380
|
-
const uint32_t* a;
|
|
381
|
-
int n;
|
|
382
|
-
|
|
383
|
-
HammingComputerM4() {}
|
|
384
|
-
|
|
385
|
-
HammingComputerM4(const uint8_t* a4, int code_size) {
|
|
386
|
-
set(a4, code_size);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
void set(const uint8_t* a4, int code_size) {
|
|
390
|
-
assert(code_size % 4 == 0);
|
|
391
|
-
a = (uint32_t*)a4;
|
|
392
|
-
n = code_size / 4;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
int hamming(const uint8_t* b8) const {
|
|
396
|
-
const uint32_t* b = (uint32_t*)b8;
|
|
397
|
-
int accu = 0;
|
|
398
|
-
for (int i = 0; i < n; i++)
|
|
399
|
-
accu += popcount64(a[i] ^ b[i]);
|
|
400
|
-
return accu;
|
|
401
|
-
}
|
|
402
|
-
};
|
|
403
|
-
|
|
404
|
-
/***************************************************************************
|
|
405
|
-
* Equivalence with a template class when code size is known at compile time
|
|
406
|
-
**************************************************************************/
|
|
407
|
-
|
|
408
|
-
// default template
|
|
409
|
-
template <int CODE_SIZE>
|
|
410
|
-
struct HammingComputer : HammingComputerDefault {
|
|
411
|
-
HammingComputer(const uint8_t* a, int code_size)
|
|
412
|
-
: HammingComputerDefault(a, code_size) {}
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
#define SPECIALIZED_HC(CODE_SIZE) \
|
|
416
|
-
template <> \
|
|
417
|
-
struct HammingComputer<CODE_SIZE> : HammingComputer##CODE_SIZE { \
|
|
418
|
-
HammingComputer(const uint8_t* a) \
|
|
419
|
-
: HammingComputer##CODE_SIZE(a, CODE_SIZE) {} \
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
SPECIALIZED_HC(4);
|
|
423
|
-
SPECIALIZED_HC(8);
|
|
424
|
-
SPECIALIZED_HC(16);
|
|
425
|
-
SPECIALIZED_HC(20);
|
|
426
|
-
SPECIALIZED_HC(32);
|
|
427
|
-
SPECIALIZED_HC(64);
|
|
428
|
-
|
|
429
|
-
#undef SPECIALIZED_HC
|
|
430
|
-
|
|
431
|
-
/***************************************************************************
|
|
432
|
-
* generalized Hamming = number of bytes that are different between
|
|
433
|
-
* two codes.
|
|
434
|
-
***************************************************************************/
|
|
435
|
-
|
|
436
|
-
inline int generalized_hamming_64(uint64_t a) {
|
|
437
|
-
a |= a >> 1;
|
|
438
|
-
a |= a >> 2;
|
|
439
|
-
a |= a >> 4;
|
|
440
|
-
a &= 0x0101010101010101UL;
|
|
441
|
-
return popcount64(a);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
struct GenHammingComputer8 {
|
|
445
|
-
uint64_t a0;
|
|
446
|
-
|
|
447
|
-
GenHammingComputer8(const uint8_t* a, int code_size) {
|
|
448
|
-
assert(code_size == 8);
|
|
449
|
-
a0 = *(uint64_t*)a;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
inline int hamming(const uint8_t* b) const {
|
|
453
|
-
return generalized_hamming_64(*(uint64_t*)b ^ a0);
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
|
|
457
|
-
struct GenHammingComputer16 {
|
|
458
|
-
uint64_t a0, a1;
|
|
459
|
-
GenHammingComputer16(const uint8_t* a8, int code_size) {
|
|
460
|
-
assert(code_size == 16);
|
|
461
|
-
const uint64_t* a = (uint64_t*)a8;
|
|
462
|
-
a0 = a[0];
|
|
463
|
-
a1 = a[1];
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
inline int hamming(const uint8_t* b8) const {
|
|
467
|
-
const uint64_t* b = (uint64_t*)b8;
|
|
468
|
-
return generalized_hamming_64(b[0] ^ a0) +
|
|
469
|
-
generalized_hamming_64(b[1] ^ a1);
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
struct GenHammingComputer32 {
|
|
474
|
-
uint64_t a0, a1, a2, a3;
|
|
475
|
-
|
|
476
|
-
GenHammingComputer32(const uint8_t* a8, int code_size) {
|
|
477
|
-
assert(code_size == 32);
|
|
478
|
-
const uint64_t* a = (uint64_t*)a8;
|
|
479
|
-
a0 = a[0];
|
|
480
|
-
a1 = a[1];
|
|
481
|
-
a2 = a[2];
|
|
482
|
-
a3 = a[3];
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
inline int hamming(const uint8_t* b8) const {
|
|
486
|
-
const uint64_t* b = (uint64_t*)b8;
|
|
487
|
-
return generalized_hamming_64(b[0] ^ a0) +
|
|
488
|
-
generalized_hamming_64(b[1] ^ a1) +
|
|
489
|
-
generalized_hamming_64(b[2] ^ a2) +
|
|
490
|
-
generalized_hamming_64(b[3] ^ a3);
|
|
491
|
-
}
|
|
492
|
-
};
|
|
493
|
-
|
|
494
|
-
struct GenHammingComputerM8 {
|
|
495
|
-
const uint64_t* a;
|
|
496
|
-
int n;
|
|
497
|
-
|
|
498
|
-
GenHammingComputerM8(const uint8_t* a8, int code_size) {
|
|
499
|
-
assert(code_size % 8 == 0);
|
|
500
|
-
a = (uint64_t*)a8;
|
|
501
|
-
n = code_size / 8;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
int hamming(const uint8_t* b8) const {
|
|
505
|
-
const uint64_t* b = (uint64_t*)b8;
|
|
506
|
-
int accu = 0;
|
|
507
|
-
for (int i = 0; i < n; i++)
|
|
508
|
-
accu += generalized_hamming_64(a[i] ^ b[i]);
|
|
509
|
-
return accu;
|
|
510
|
-
}
|
|
511
|
-
};
|
|
512
|
-
|
|
513
|
-
/** generalized Hamming distances (= count number of code bytes that
|
|
514
|
-
are the same) */
|
|
515
|
-
void generalized_hammings_knn_hc(
|
|
516
|
-
int_maxheap_array_t* ha,
|
|
517
|
-
const uint8_t* a,
|
|
518
|
-
const uint8_t* b,
|
|
519
|
-
size_t nb,
|
|
520
|
-
size_t code_size,
|
|
521
|
-
int ordered = true);
|
|
522
|
-
|
|
523
67
|
/** This class maintains a list of best distances seen so far.
|
|
524
68
|
*
|
|
525
69
|
* Since the distances are in a limited range (0 to nbit), the
|