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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/faiss/version.rb +1 -1
  4. data/vendor/faiss/faiss/AutoTune.h +1 -1
  5. data/vendor/faiss/faiss/Clustering.cpp +35 -4
  6. data/vendor/faiss/faiss/Clustering.h +10 -1
  7. data/vendor/faiss/faiss/IVFlib.cpp +4 -1
  8. data/vendor/faiss/faiss/Index.h +21 -6
  9. data/vendor/faiss/faiss/IndexBinaryHNSW.h +1 -1
  10. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +1 -1
  11. data/vendor/faiss/faiss/IndexFastScan.cpp +22 -4
  12. data/vendor/faiss/faiss/IndexFlat.cpp +11 -7
  13. data/vendor/faiss/faiss/IndexFlatCodes.cpp +159 -5
  14. data/vendor/faiss/faiss/IndexFlatCodes.h +20 -3
  15. data/vendor/faiss/faiss/IndexHNSW.cpp +143 -90
  16. data/vendor/faiss/faiss/IndexHNSW.h +52 -3
  17. data/vendor/faiss/faiss/IndexIVF.cpp +3 -3
  18. data/vendor/faiss/faiss/IndexIVF.h +9 -1
  19. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +15 -0
  20. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +3 -0
  21. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +130 -57
  22. data/vendor/faiss/faiss/IndexIVFFastScan.h +14 -7
  23. data/vendor/faiss/faiss/IndexIVFPQ.cpp +1 -3
  24. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +21 -2
  25. data/vendor/faiss/faiss/IndexLattice.cpp +1 -19
  26. data/vendor/faiss/faiss/IndexLattice.h +3 -22
  27. data/vendor/faiss/faiss/IndexNNDescent.cpp +0 -29
  28. data/vendor/faiss/faiss/IndexNNDescent.h +1 -1
  29. data/vendor/faiss/faiss/IndexNSG.h +1 -1
  30. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +56 -0
  31. data/vendor/faiss/faiss/IndexNeuralNetCodec.h +49 -0
  32. data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
  33. data/vendor/faiss/faiss/IndexRefine.cpp +5 -5
  34. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +3 -1
  35. data/vendor/faiss/faiss/MetricType.h +7 -2
  36. data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +95 -17
  37. data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +152 -0
  38. data/vendor/faiss/faiss/cppcontrib/factory_tools.h +24 -0
  39. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +83 -30
  40. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +36 -4
  41. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +6 -0
  42. data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -1
  43. data/vendor/faiss/faiss/gpu/GpuIndex.h +2 -8
  44. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +282 -0
  45. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +6 -0
  46. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +2 -0
  47. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +25 -0
  48. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +26 -21
  49. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +6 -0
  50. data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +8 -5
  51. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +65 -0
  52. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +1 -1
  53. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +6 -0
  54. data/vendor/faiss/faiss/gpu/utils/Timer.cpp +4 -1
  55. data/vendor/faiss/faiss/gpu/utils/Timer.h +1 -1
  56. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +25 -0
  57. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +9 -1
  58. data/vendor/faiss/faiss/impl/DistanceComputer.h +46 -0
  59. data/vendor/faiss/faiss/impl/FaissAssert.h +4 -2
  60. data/vendor/faiss/faiss/impl/HNSW.cpp +358 -190
  61. data/vendor/faiss/faiss/impl/HNSW.h +43 -22
  62. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +8 -8
  63. data/vendor/faiss/faiss/impl/LookupTableScaler.h +34 -0
  64. data/vendor/faiss/faiss/impl/NNDescent.cpp +13 -8
  65. data/vendor/faiss/faiss/impl/NSG.cpp +0 -29
  66. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +1 -0
  67. data/vendor/faiss/faiss/impl/ProductQuantizer.h +5 -1
  68. data/vendor/faiss/faiss/impl/ResultHandler.h +151 -32
  69. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +719 -102
  70. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +3 -0
  71. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +5 -0
  72. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx512.h +248 -0
  73. data/vendor/faiss/faiss/impl/index_read.cpp +29 -15
  74. data/vendor/faiss/faiss/impl/index_read_utils.h +37 -0
  75. data/vendor/faiss/faiss/impl/index_write.cpp +28 -10
  76. data/vendor/faiss/faiss/impl/io.cpp +13 -5
  77. data/vendor/faiss/faiss/impl/io.h +4 -4
  78. data/vendor/faiss/faiss/impl/io_macros.h +6 -0
  79. data/vendor/faiss/faiss/impl/platform_macros.h +22 -0
  80. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +11 -0
  81. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +1 -1
  82. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +448 -1
  83. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +5 -5
  84. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
  85. data/vendor/faiss/faiss/impl/simd_result_handlers.h +143 -59
  86. data/vendor/faiss/faiss/index_factory.cpp +31 -13
  87. data/vendor/faiss/faiss/index_io.h +12 -5
  88. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +28 -8
  89. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +3 -0
  90. data/vendor/faiss/faiss/invlists/DirectMap.cpp +9 -1
  91. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +55 -17
  92. data/vendor/faiss/faiss/invlists/InvertedLists.h +18 -9
  93. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +21 -6
  94. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +2 -1
  95. data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -3
  96. data/vendor/faiss/faiss/utils/Heap.h +105 -0
  97. data/vendor/faiss/faiss/utils/NeuralNet.cpp +342 -0
  98. data/vendor/faiss/faiss/utils/NeuralNet.h +147 -0
  99. data/vendor/faiss/faiss/utils/bf16.h +36 -0
  100. data/vendor/faiss/faiss/utils/distances.cpp +58 -88
  101. data/vendor/faiss/faiss/utils/distances.h +5 -5
  102. data/vendor/faiss/faiss/utils/distances_simd.cpp +997 -9
  103. data/vendor/faiss/faiss/utils/extra_distances-inl.h +70 -0
  104. data/vendor/faiss/faiss/utils/extra_distances.cpp +85 -137
  105. data/vendor/faiss/faiss/utils/extra_distances.h +3 -2
  106. data/vendor/faiss/faiss/utils/hamming.cpp +1 -1
  107. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +4 -1
  108. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +2 -1
  109. data/vendor/faiss/faiss/utils/random.cpp +43 -0
  110. data/vendor/faiss/faiss/utils/random.h +25 -0
  111. data/vendor/faiss/faiss/utils/simdlib.h +10 -1
  112. data/vendor/faiss/faiss/utils/simdlib_avx512.h +296 -0
  113. data/vendor/faiss/faiss/utils/simdlib_neon.h +5 -2
  114. data/vendor/faiss/faiss/utils/simdlib_ppc64.h +1084 -0
  115. data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +176 -0
  116. data/vendor/faiss/faiss/utils/utils.cpp +10 -3
  117. data/vendor/faiss/faiss/utils/utils.h +3 -0
  118. metadata +16 -4
  119. 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
- template <class VD>
30
- void pairwise_extra_distances_template(
31
- VD vd,
32
- int64_t nq,
33
- const float* xq,
34
- int64_t nb,
35
- const float* xb,
36
- float* dis,
37
- int64_t ldq,
38
- int64_t ldb,
39
- int64_t ldd) {
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
- for (int64_t i = 0; i < nq; i++) {
42
- const float* xqi = xq + i * ldq;
43
- const float* xbj = xb;
44
- float* disi = dis + ldd * i;
45
-
46
- for (int64_t j = 0; j < nb; j++) {
47
- disi[j] = vd(xqi, xbj);
48
- xbj += ldb;
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
- for (size_t i0 = 0; i0 < nx; i0 += check_period) {
67
- size_t i1 = std::min(i0 + check_period, nx);
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
- for (int64_t i = i0; i < i1; i++) {
71
- const float* x_i = x + i * d;
72
- const float* y_j = y;
73
- size_t j;
74
- float* simi = res->get_val(i);
75
- int64_t* idxi = res->get_ids(i);
76
-
77
- // maxheap_heapify(k, simi, idxi);
78
- heap_heapify<C>(k, simi, idxi);
79
- for (j = 0; j < ny; j++) {
80
- float disij = vd(x_i, y_j);
81
-
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);
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
- y_j += d;
93
+ // maxheap_reorder(k, simi, idxi);
94
+ heap_reorder<C>(k, simi, idxi);
89
95
  }
90
- // maxheap_reorder(k, simi, idxi);
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
- switch (mt) {
152
- #define HANDLE_VAR(kw) \
153
- case METRIC_##kw: { \
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
- HeapArray<C>* res) {
183
- switch (mt) {
184
- #define HANDLE_VAR(kw) \
185
- case METRIC_##kw: { \
186
- VectorDistance<METRIC_##kw> vd = {(size_t)d, metric_arg}; \
187
- knn_extra_metrics_template(vd, x, y, nx, ny, res); \
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
- switch (mt) {
231
- #define HANDLE_VAR(kw) \
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
- HeapArray<C>* res);
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 ouptut b is byte-aligned (pad with 0s). */
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
- a2 = a[2];
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 to be called to perform the operation.
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
- #ifdef __AVX2__
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