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
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* and inner product */
|
|
10
10
|
|
|
11
11
|
#include <faiss/MetricType.h>
|
|
12
|
+
#include <faiss/impl/FaissAssert.h>
|
|
12
13
|
#include <faiss/utils/distances.h>
|
|
14
|
+
#include <cmath>
|
|
13
15
|
#include <type_traits>
|
|
14
16
|
|
|
15
17
|
namespace faiss {
|
|
@@ -130,4 +132,72 @@ inline float VectorDistance<METRIC_Jaccard>::operator()(
|
|
|
130
132
|
return accu_num / accu_den;
|
|
131
133
|
}
|
|
132
134
|
|
|
135
|
+
template <>
|
|
136
|
+
inline float VectorDistance<METRIC_NaNEuclidean>::operator()(
|
|
137
|
+
const float* x,
|
|
138
|
+
const float* y) const {
|
|
139
|
+
// https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.nan_euclidean_distances.html
|
|
140
|
+
float accu = 0;
|
|
141
|
+
size_t present = 0;
|
|
142
|
+
for (size_t i = 0; i < d; i++) {
|
|
143
|
+
if (!std::isnan(x[i]) && !std::isnan(y[i])) {
|
|
144
|
+
float diff = x[i] - y[i];
|
|
145
|
+
accu += diff * diff;
|
|
146
|
+
present++;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (present == 0) {
|
|
150
|
+
return NAN;
|
|
151
|
+
}
|
|
152
|
+
return float(d) / float(present) * accu;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
template <>
|
|
156
|
+
inline float VectorDistance<METRIC_ABS_INNER_PRODUCT>::operator()(
|
|
157
|
+
const float* x,
|
|
158
|
+
const float* y) const {
|
|
159
|
+
float accu = 0;
|
|
160
|
+
for (size_t i = 0; i < d; i++) {
|
|
161
|
+
accu += fabs(x[i] * y[i]);
|
|
162
|
+
}
|
|
163
|
+
return accu;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/***************************************************************************
|
|
167
|
+
* Dispatching function that takes a metric type and a consumer object
|
|
168
|
+
* the consumer object should contain a retun type T and a operation template
|
|
169
|
+
* function f() that is called to perform the operation. The first argument
|
|
170
|
+
* of the function is the VectorDistance object. The rest are passed in as is.
|
|
171
|
+
**************************************************************************/
|
|
172
|
+
|
|
173
|
+
template <class Consumer, class... Types>
|
|
174
|
+
typename Consumer::T dispatch_VectorDistance(
|
|
175
|
+
size_t d,
|
|
176
|
+
MetricType metric,
|
|
177
|
+
float metric_arg,
|
|
178
|
+
Consumer& consumer,
|
|
179
|
+
Types... args) {
|
|
180
|
+
switch (metric) {
|
|
181
|
+
#define DISPATCH_VD(mt) \
|
|
182
|
+
case mt: { \
|
|
183
|
+
VectorDistance<mt> vd = {d, metric_arg}; \
|
|
184
|
+
return consumer.template f<VectorDistance<mt>>(vd, args...); \
|
|
185
|
+
}
|
|
186
|
+
DISPATCH_VD(METRIC_INNER_PRODUCT);
|
|
187
|
+
DISPATCH_VD(METRIC_L2);
|
|
188
|
+
DISPATCH_VD(METRIC_L1);
|
|
189
|
+
DISPATCH_VD(METRIC_Linf);
|
|
190
|
+
DISPATCH_VD(METRIC_Lp);
|
|
191
|
+
DISPATCH_VD(METRIC_Canberra);
|
|
192
|
+
DISPATCH_VD(METRIC_BrayCurtis);
|
|
193
|
+
DISPATCH_VD(METRIC_JensenShannon);
|
|
194
|
+
DISPATCH_VD(METRIC_Jaccard);
|
|
195
|
+
DISPATCH_VD(METRIC_NaNEuclidean);
|
|
196
|
+
DISPATCH_VD(METRIC_ABS_INNER_PRODUCT);
|
|
197
|
+
default:
|
|
198
|
+
FAISS_THROW_FMT("Invalid metric %d", metric);
|
|
199
|
+
}
|
|
200
|
+
#undef DISPATCH_VD
|
|
201
|
+
}
|
|
202
|
+
|
|
133
203
|
} // namespace faiss
|
|
@@ -26,73 +26,77 @@ namespace faiss {
|
|
|
26
26
|
|
|
27
27
|
namespace {
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
void
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
29
|
+
struct Run_pairwise_extra_distances {
|
|
30
|
+
using T = void;
|
|
31
|
+
|
|
32
|
+
template <class VD>
|
|
33
|
+
void f(VD vd,
|
|
34
|
+
int64_t nq,
|
|
35
|
+
const float* xq,
|
|
36
|
+
int64_t nb,
|
|
37
|
+
const float* xb,
|
|
38
|
+
float* dis,
|
|
39
|
+
int64_t ldq,
|
|
40
|
+
int64_t ldb,
|
|
41
|
+
int64_t ldd) {
|
|
40
42
|
#pragma omp parallel for if (nq > 10)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
for (int64_t i = 0; i < nq; i++) {
|
|
44
|
+
const float* xqi = xq + i * ldq;
|
|
45
|
+
const float* xbj = xb;
|
|
46
|
+
float* disi = dis + ldd * i;
|
|
47
|
+
|
|
48
|
+
for (int64_t j = 0; j < nb; j++) {
|
|
49
|
+
disi[j] = vd(xqi, xbj);
|
|
50
|
+
xbj += ldb;
|
|
51
|
+
}
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
template <class VD, class C>
|
|
54
|
-
void knn_extra_metrics_template(
|
|
55
|
-
VD vd,
|
|
56
|
-
const float* x,
|
|
57
|
-
const float* y,
|
|
58
|
-
size_t nx,
|
|
59
|
-
size_t ny,
|
|
60
|
-
HeapArray<C>* res) {
|
|
61
|
-
size_t k = res->k;
|
|
62
|
-
size_t d = vd.d;
|
|
63
|
-
size_t check_period = InterruptCallback::get_period_hint(ny * d);
|
|
64
|
-
check_period *= omp_get_max_threads();
|
|
54
|
+
};
|
|
65
55
|
|
|
66
|
-
|
|
67
|
-
|
|
56
|
+
struct Run_knn_extra_metrics {
|
|
57
|
+
using T = void;
|
|
58
|
+
template <class VD>
|
|
59
|
+
void f(VD vd,
|
|
60
|
+
const float* x,
|
|
61
|
+
const float* y,
|
|
62
|
+
size_t nx,
|
|
63
|
+
size_t ny,
|
|
64
|
+
size_t k,
|
|
65
|
+
float* distances,
|
|
66
|
+
int64_t* labels) {
|
|
67
|
+
size_t d = vd.d;
|
|
68
|
+
using C = typename VD::C;
|
|
69
|
+
size_t check_period = InterruptCallback::get_period_hint(ny * d);
|
|
70
|
+
check_period *= omp_get_max_threads();
|
|
71
|
+
|
|
72
|
+
for (size_t i0 = 0; i0 < nx; i0 += check_period) {
|
|
73
|
+
size_t i1 = std::min(i0 + check_period, nx);
|
|
68
74
|
|
|
69
75
|
#pragma omp parallel for
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
heap_replace_top<C>(k, simi, idxi, disij, j);
|
|
76
|
+
for (int64_t i = i0; i < i1; i++) {
|
|
77
|
+
const float* x_i = x + i * d;
|
|
78
|
+
const float* y_j = y;
|
|
79
|
+
size_t j;
|
|
80
|
+
float* simi = distances + k * i;
|
|
81
|
+
int64_t* idxi = labels + k * i;
|
|
82
|
+
|
|
83
|
+
// maxheap_heapify(k, simi, idxi);
|
|
84
|
+
heap_heapify<C>(k, simi, idxi);
|
|
85
|
+
for (j = 0; j < ny; j++) {
|
|
86
|
+
float disij = vd(x_i, y_j);
|
|
87
|
+
|
|
88
|
+
if (C::cmp(simi[0], disij)) {
|
|
89
|
+
heap_replace_top<C>(k, simi, idxi, disij, j);
|
|
90
|
+
}
|
|
91
|
+
y_j += d;
|
|
87
92
|
}
|
|
88
|
-
|
|
93
|
+
// maxheap_reorder(k, simi, idxi);
|
|
94
|
+
heap_reorder<C>(k, simi, idxi);
|
|
89
95
|
}
|
|
90
|
-
|
|
91
|
-
heap_reorder<C>(k, simi, idxi);
|
|
96
|
+
InterruptCallback::check();
|
|
92
97
|
}
|
|
93
|
-
InterruptCallback::check();
|
|
94
98
|
}
|
|
95
|
-
}
|
|
99
|
+
};
|
|
96
100
|
|
|
97
101
|
template <class VD>
|
|
98
102
|
struct ExtraDistanceComputer : FlatCodesDistanceComputer {
|
|
@@ -125,6 +129,19 @@ struct ExtraDistanceComputer : FlatCodesDistanceComputer {
|
|
|
125
129
|
}
|
|
126
130
|
};
|
|
127
131
|
|
|
132
|
+
struct Run_get_distance_computer {
|
|
133
|
+
using T = FlatCodesDistanceComputer*;
|
|
134
|
+
|
|
135
|
+
template <class VD>
|
|
136
|
+
FlatCodesDistanceComputer* f(
|
|
137
|
+
VD vd,
|
|
138
|
+
const float* xb,
|
|
139
|
+
size_t nb,
|
|
140
|
+
const float* q = nullptr) {
|
|
141
|
+
return new ExtraDistanceComputer<VD>(vd, xb, nb, q);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
128
145
|
} // anonymous namespace
|
|
129
146
|
|
|
130
147
|
void pairwise_extra_distances(
|
|
@@ -148,29 +165,11 @@ void pairwise_extra_distances(
|
|
|
148
165
|
if (ldd == -1)
|
|
149
166
|
ldd = nb;
|
|
150
167
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
VectorDistance<METRIC_##kw> vd = {(size_t)d, metric_arg}; \
|
|
155
|
-
pairwise_extra_distances_template( \
|
|
156
|
-
vd, nq, xq, nb, xb, dis, ldq, ldb, ldd); \
|
|
157
|
-
break; \
|
|
158
|
-
}
|
|
159
|
-
HANDLE_VAR(L2);
|
|
160
|
-
HANDLE_VAR(L1);
|
|
161
|
-
HANDLE_VAR(Linf);
|
|
162
|
-
HANDLE_VAR(Canberra);
|
|
163
|
-
HANDLE_VAR(BrayCurtis);
|
|
164
|
-
HANDLE_VAR(JensenShannon);
|
|
165
|
-
HANDLE_VAR(Lp);
|
|
166
|
-
HANDLE_VAR(Jaccard);
|
|
167
|
-
#undef HANDLE_VAR
|
|
168
|
-
default:
|
|
169
|
-
FAISS_THROW_MSG("metric type not implemented");
|
|
170
|
-
}
|
|
168
|
+
Run_pairwise_extra_distances run;
|
|
169
|
+
dispatch_VectorDistance(
|
|
170
|
+
d, mt, metric_arg, run, nq, xq, nb, xb, dis, ldq, ldb, ldd);
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
template <class C>
|
|
174
173
|
void knn_extra_metrics(
|
|
175
174
|
const float* x,
|
|
176
175
|
const float* y,
|
|
@@ -179,73 +178,22 @@ void knn_extra_metrics(
|
|
|
179
178
|
size_t ny,
|
|
180
179
|
MetricType mt,
|
|
181
180
|
float metric_arg,
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
break; \
|
|
189
|
-
}
|
|
190
|
-
HANDLE_VAR(L2);
|
|
191
|
-
HANDLE_VAR(L1);
|
|
192
|
-
HANDLE_VAR(Linf);
|
|
193
|
-
HANDLE_VAR(Canberra);
|
|
194
|
-
HANDLE_VAR(BrayCurtis);
|
|
195
|
-
HANDLE_VAR(JensenShannon);
|
|
196
|
-
HANDLE_VAR(Lp);
|
|
197
|
-
HANDLE_VAR(Jaccard);
|
|
198
|
-
#undef HANDLE_VAR
|
|
199
|
-
default:
|
|
200
|
-
FAISS_THROW_MSG("metric type not implemented");
|
|
201
|
-
}
|
|
181
|
+
size_t k,
|
|
182
|
+
float* distances,
|
|
183
|
+
int64_t* indexes) {
|
|
184
|
+
Run_knn_extra_metrics run;
|
|
185
|
+
dispatch_VectorDistance(
|
|
186
|
+
d, mt, metric_arg, run, x, y, nx, ny, k, distances, indexes);
|
|
202
187
|
}
|
|
203
188
|
|
|
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
|
-
|
|
224
189
|
FlatCodesDistanceComputer* get_extra_distance_computer(
|
|
225
190
|
size_t d,
|
|
226
191
|
MetricType mt,
|
|
227
192
|
float metric_arg,
|
|
228
193
|
size_t nb,
|
|
229
194
|
const float* xb) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
case METRIC_##kw: { \
|
|
233
|
-
VectorDistance<METRIC_##kw> vd = {(size_t)d, metric_arg}; \
|
|
234
|
-
return new ExtraDistanceComputer<VectorDistance<METRIC_##kw>>( \
|
|
235
|
-
vd, xb, nb); \
|
|
236
|
-
}
|
|
237
|
-
HANDLE_VAR(L2);
|
|
238
|
-
HANDLE_VAR(L1);
|
|
239
|
-
HANDLE_VAR(Linf);
|
|
240
|
-
HANDLE_VAR(Canberra);
|
|
241
|
-
HANDLE_VAR(BrayCurtis);
|
|
242
|
-
HANDLE_VAR(JensenShannon);
|
|
243
|
-
HANDLE_VAR(Lp);
|
|
244
|
-
HANDLE_VAR(Jaccard);
|
|
245
|
-
#undef HANDLE_VAR
|
|
246
|
-
default:
|
|
247
|
-
FAISS_THROW_MSG("metric type not implemented");
|
|
248
|
-
}
|
|
195
|
+
Run_get_distance_computer run;
|
|
196
|
+
return dispatch_VectorDistance(d, mt, metric_arg, run, xb, nb);
|
|
249
197
|
}
|
|
250
198
|
|
|
251
199
|
} // namespace faiss
|
|
@@ -33,7 +33,6 @@ void pairwise_extra_distances(
|
|
|
33
33
|
int64_t ldb = -1,
|
|
34
34
|
int64_t ldd = -1);
|
|
35
35
|
|
|
36
|
-
template <class C>
|
|
37
36
|
void knn_extra_metrics(
|
|
38
37
|
const float* x,
|
|
39
38
|
const float* y,
|
|
@@ -42,7 +41,9 @@ void knn_extra_metrics(
|
|
|
42
41
|
size_t ny,
|
|
43
42
|
MetricType mt,
|
|
44
43
|
float metric_arg,
|
|
45
|
-
|
|
44
|
+
size_t k,
|
|
45
|
+
float* distances,
|
|
46
|
+
int64_t* indexes);
|
|
46
47
|
|
|
47
48
|
/** get a DistanceComputer that refers to this type of distance and
|
|
48
49
|
* indexes a flat array of size nb */
|
|
@@ -364,7 +364,7 @@ void fvec2bitvec(const float* __restrict x, uint8_t* __restrict b, size_t d) {
|
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
/* Same but for n vectors.
|
|
367
|
-
Ensure that the
|
|
367
|
+
Ensure that the output b is byte-aligned (pad with 0s). */
|
|
368
368
|
void fvecs2bitvecs(
|
|
369
369
|
const float* __restrict x,
|
|
370
370
|
uint8_t* __restrict b,
|
|
@@ -166,9 +166,12 @@ struct HammingComputer20 {
|
|
|
166
166
|
void set(const uint8_t* a8, int code_size) {
|
|
167
167
|
assert(code_size == 20);
|
|
168
168
|
const uint64_t* a = (uint64_t*)a8;
|
|
169
|
+
const uint32_t* b = (uint32_t*)a8;
|
|
169
170
|
a0 = a[0];
|
|
170
171
|
a1 = a[1];
|
|
171
|
-
|
|
172
|
+
// can't read a[2] since it is uint64_t, not uint32_t
|
|
173
|
+
// results in AddressSanitizer failure reading past end of array
|
|
174
|
+
a2 = b[4];
|
|
172
175
|
}
|
|
173
176
|
|
|
174
177
|
inline int hamming(const uint8_t* b8) const {
|
|
@@ -55,7 +55,7 @@ SPECIALIZED_HC(64);
|
|
|
55
55
|
/***************************************************************************
|
|
56
56
|
* Dispatching function that takes a code size and a consumer object
|
|
57
57
|
* the consumer object should contain a retun type t and a operation template
|
|
58
|
-
* function f() that
|
|
58
|
+
* function f() that must be called to perform the operation.
|
|
59
59
|
**************************************************************************/
|
|
60
60
|
|
|
61
61
|
template <class Consumer, class... Types>
|
|
@@ -76,6 +76,7 @@ typename Consumer::T dispatch_HammingComputer(
|
|
|
76
76
|
default:
|
|
77
77
|
return consumer.template f<HammingComputerDefault>(args...);
|
|
78
78
|
}
|
|
79
|
+
#undef DISPATCH_HC
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
} // namespace faiss
|
|
@@ -54,6 +54,37 @@ double RandomGenerator::rand_double() {
|
|
|
54
54
|
return mt() / double(mt.max());
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
SplitMix64RandomGenerator::SplitMix64RandomGenerator(int64_t seed)
|
|
58
|
+
: state{static_cast<uint64_t>(seed)} {}
|
|
59
|
+
|
|
60
|
+
int SplitMix64RandomGenerator::rand_int() {
|
|
61
|
+
return next() & 0x7fffffff;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
int64_t SplitMix64RandomGenerator::rand_int64() {
|
|
65
|
+
uint64_t value = next();
|
|
66
|
+
return static_cast<int64_t>(value & 0x7fffffffffffffffULL);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
int SplitMix64RandomGenerator::rand_int(int max) {
|
|
70
|
+
return next() % max;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
float SplitMix64RandomGenerator::rand_float() {
|
|
74
|
+
return next() / float(std::numeric_limits<uint64_t>::max());
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
double SplitMix64RandomGenerator::rand_double() {
|
|
78
|
+
return next() / double(std::numeric_limits<uint64_t>::max());
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
uint64_t SplitMix64RandomGenerator::next() {
|
|
82
|
+
uint64_t z = (state += 0x9e3779b97f4a7c15ULL);
|
|
83
|
+
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;
|
|
84
|
+
z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;
|
|
85
|
+
return z ^ (z >> 31);
|
|
86
|
+
}
|
|
87
|
+
|
|
57
88
|
/***********************************************************************
|
|
58
89
|
* Random functions in this C file only exist because Torch
|
|
59
90
|
* counterparts are slow and not multi-threaded. Typical use is for
|
|
@@ -162,6 +193,18 @@ void rand_perm(int* perm, size_t n, int64_t seed) {
|
|
|
162
193
|
}
|
|
163
194
|
}
|
|
164
195
|
|
|
196
|
+
void rand_perm_splitmix64(int* perm, size_t n, int64_t seed) {
|
|
197
|
+
for (size_t i = 0; i < n; i++)
|
|
198
|
+
perm[i] = i;
|
|
199
|
+
|
|
200
|
+
SplitMix64RandomGenerator rng(seed);
|
|
201
|
+
|
|
202
|
+
for (size_t i = 0; i + 1 < n; i++) {
|
|
203
|
+
int i2 = i + rng.rand_int(n - i);
|
|
204
|
+
std::swap(perm[i], perm[i2]);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
165
208
|
void byte_rand(uint8_t* x, size_t n, int64_t seed) {
|
|
166
209
|
// only try to parallelize on large enough arrays
|
|
167
210
|
const size_t nblock = n < 1024 ? 1 : 1024;
|
|
@@ -43,6 +43,30 @@ struct RandomGenerator {
|
|
|
43
43
|
explicit RandomGenerator(int64_t seed = 1234);
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
/// fast random generator that cannot be used in multithreaded contexts.
|
|
47
|
+
/// based on https://prng.di.unimi.it/
|
|
48
|
+
struct SplitMix64RandomGenerator {
|
|
49
|
+
uint64_t state;
|
|
50
|
+
|
|
51
|
+
/// random positive integer
|
|
52
|
+
int rand_int();
|
|
53
|
+
|
|
54
|
+
/// random int64_t
|
|
55
|
+
int64_t rand_int64();
|
|
56
|
+
|
|
57
|
+
/// generate random integer between 0 and max-1
|
|
58
|
+
int rand_int(int max);
|
|
59
|
+
|
|
60
|
+
/// between 0 and 1
|
|
61
|
+
float rand_float();
|
|
62
|
+
|
|
63
|
+
double rand_double();
|
|
64
|
+
|
|
65
|
+
explicit SplitMix64RandomGenerator(int64_t seed = 1234);
|
|
66
|
+
|
|
67
|
+
uint64_t next();
|
|
68
|
+
};
|
|
69
|
+
|
|
46
70
|
/* Generate an array of uniform random floats / multi-threaded implementation */
|
|
47
71
|
void float_rand(float* x, size_t n, int64_t seed);
|
|
48
72
|
void float_randn(float* x, size_t n, int64_t seed);
|
|
@@ -53,6 +77,7 @@ void int64_rand_max(int64_t* x, size_t n, uint64_t max, int64_t seed);
|
|
|
53
77
|
|
|
54
78
|
/* random permutation */
|
|
55
79
|
void rand_perm(int* perm, size_t n, int64_t seed);
|
|
80
|
+
void rand_perm_splitmix64(int* perm, size_t n, int64_t seed);
|
|
56
81
|
|
|
57
82
|
/* Random set of vectors with intrinsic dimensionality 10 that is harder to
|
|
58
83
|
* index than a subspace of dim 10 but easier than uniform data in dimension d
|
|
@@ -14,7 +14,12 @@
|
|
|
14
14
|
* functions.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
#
|
|
17
|
+
#if defined(__AVX512F__)
|
|
18
|
+
|
|
19
|
+
#include <faiss/utils/simdlib_avx2.h>
|
|
20
|
+
#include <faiss/utils/simdlib_avx512.h>
|
|
21
|
+
|
|
22
|
+
#elif defined(__AVX2__)
|
|
18
23
|
|
|
19
24
|
#include <faiss/utils/simdlib_avx2.h>
|
|
20
25
|
|
|
@@ -22,6 +27,10 @@
|
|
|
22
27
|
|
|
23
28
|
#include <faiss/utils/simdlib_neon.h>
|
|
24
29
|
|
|
30
|
+
#elif defined(__PPC64__)
|
|
31
|
+
|
|
32
|
+
#include <faiss/utils/simdlib_ppc64.h>
|
|
33
|
+
|
|
25
34
|
#else
|
|
26
35
|
|
|
27
36
|
// emulated = all operations are implemented as scalars
|