faiss 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/ext/faiss/extconf.rb +9 -2
  6. data/ext/faiss/index.cpp +1 -1
  7. data/ext/faiss/index_binary.cpp +2 -2
  8. data/ext/faiss/product_quantizer.cpp +1 -1
  9. data/lib/faiss/version.rb +1 -1
  10. data/vendor/faiss/faiss/AutoTune.cpp +7 -7
  11. data/vendor/faiss/faiss/AutoTune.h +0 -1
  12. data/vendor/faiss/faiss/Clustering.cpp +4 -18
  13. data/vendor/faiss/faiss/Clustering.h +31 -21
  14. data/vendor/faiss/faiss/IVFlib.cpp +22 -11
  15. data/vendor/faiss/faiss/Index.cpp +1 -1
  16. data/vendor/faiss/faiss/Index.h +20 -5
  17. data/vendor/faiss/faiss/Index2Layer.cpp +7 -7
  18. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +176 -166
  19. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +15 -15
  20. data/vendor/faiss/faiss/IndexBinary.cpp +9 -4
  21. data/vendor/faiss/faiss/IndexBinary.h +8 -19
  22. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +2 -1
  23. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +24 -31
  24. data/vendor/faiss/faiss/IndexBinaryHash.cpp +25 -50
  25. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +106 -187
  26. data/vendor/faiss/faiss/IndexFastScan.cpp +90 -159
  27. data/vendor/faiss/faiss/IndexFastScan.h +9 -8
  28. data/vendor/faiss/faiss/IndexFlat.cpp +195 -3
  29. data/vendor/faiss/faiss/IndexFlat.h +20 -1
  30. data/vendor/faiss/faiss/IndexFlatCodes.cpp +11 -0
  31. data/vendor/faiss/faiss/IndexFlatCodes.h +3 -1
  32. data/vendor/faiss/faiss/IndexHNSW.cpp +112 -316
  33. data/vendor/faiss/faiss/IndexHNSW.h +12 -48
  34. data/vendor/faiss/faiss/IndexIDMap.cpp +69 -28
  35. data/vendor/faiss/faiss/IndexIDMap.h +24 -2
  36. data/vendor/faiss/faiss/IndexIVF.cpp +159 -53
  37. data/vendor/faiss/faiss/IndexIVF.h +37 -5
  38. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +18 -26
  39. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +3 -2
  40. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +19 -46
  41. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +4 -3
  42. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +433 -405
  43. data/vendor/faiss/faiss/IndexIVFFastScan.h +56 -26
  44. data/vendor/faiss/faiss/IndexIVFFlat.cpp +15 -5
  45. data/vendor/faiss/faiss/IndexIVFFlat.h +3 -2
  46. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +172 -0
  47. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.h +56 -0
  48. data/vendor/faiss/faiss/IndexIVFPQ.cpp +78 -122
  49. data/vendor/faiss/faiss/IndexIVFPQ.h +6 -7
  50. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +18 -50
  51. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +4 -3
  52. data/vendor/faiss/faiss/IndexIVFPQR.cpp +45 -29
  53. data/vendor/faiss/faiss/IndexIVFPQR.h +5 -2
  54. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +25 -27
  55. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +6 -6
  56. data/vendor/faiss/faiss/IndexLSH.cpp +14 -16
  57. data/vendor/faiss/faiss/IndexNNDescent.cpp +3 -4
  58. data/vendor/faiss/faiss/IndexNSG.cpp +11 -27
  59. data/vendor/faiss/faiss/IndexNSG.h +10 -10
  60. data/vendor/faiss/faiss/IndexPQ.cpp +72 -88
  61. data/vendor/faiss/faiss/IndexPQ.h +1 -4
  62. data/vendor/faiss/faiss/IndexPQFastScan.cpp +1 -1
  63. data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -31
  64. data/vendor/faiss/faiss/IndexRefine.cpp +49 -19
  65. data/vendor/faiss/faiss/IndexRefine.h +7 -0
  66. data/vendor/faiss/faiss/IndexReplicas.cpp +23 -26
  67. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +22 -16
  68. data/vendor/faiss/faiss/IndexScalarQuantizer.h +6 -4
  69. data/vendor/faiss/faiss/IndexShards.cpp +21 -29
  70. data/vendor/faiss/faiss/IndexShardsIVF.cpp +1 -2
  71. data/vendor/faiss/faiss/MatrixStats.cpp +17 -32
  72. data/vendor/faiss/faiss/MatrixStats.h +21 -9
  73. data/vendor/faiss/faiss/MetaIndexes.cpp +35 -35
  74. data/vendor/faiss/faiss/VectorTransform.cpp +13 -26
  75. data/vendor/faiss/faiss/VectorTransform.h +7 -7
  76. data/vendor/faiss/faiss/clone_index.cpp +15 -10
  77. data/vendor/faiss/faiss/clone_index.h +3 -0
  78. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +87 -4
  79. data/vendor/faiss/faiss/gpu/GpuCloner.h +22 -0
  80. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +7 -0
  81. data/vendor/faiss/faiss/gpu/GpuDistance.h +46 -38
  82. data/vendor/faiss/faiss/gpu/GpuIndex.h +28 -4
  83. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +4 -4
  84. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +8 -9
  85. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +18 -3
  86. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +22 -11
  87. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +1 -3
  88. data/vendor/faiss/faiss/gpu/GpuResources.cpp +24 -3
  89. data/vendor/faiss/faiss/gpu/GpuResources.h +39 -11
  90. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +117 -17
  91. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +57 -3
  92. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
  93. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +25 -0
  94. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +129 -9
  95. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +267 -40
  96. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +299 -208
  97. data/vendor/faiss/faiss/gpu/test/TestGpuMemoryException.cpp +1 -0
  98. data/vendor/faiss/faiss/gpu/utils/RaftUtils.h +75 -0
  99. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +3 -1
  100. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +5 -5
  101. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +1 -1
  102. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +1 -2
  103. data/vendor/faiss/faiss/impl/DistanceComputer.h +24 -1
  104. data/vendor/faiss/faiss/impl/FaissException.h +13 -34
  105. data/vendor/faiss/faiss/impl/HNSW.cpp +321 -70
  106. data/vendor/faiss/faiss/impl/HNSW.h +9 -8
  107. data/vendor/faiss/faiss/impl/IDSelector.h +4 -4
  108. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +3 -1
  109. data/vendor/faiss/faiss/impl/NNDescent.cpp +29 -19
  110. data/vendor/faiss/faiss/impl/NSG.h +1 -1
  111. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +14 -12
  112. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +1 -1
  113. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +24 -22
  114. data/vendor/faiss/faiss/impl/ProductQuantizer.h +1 -1
  115. data/vendor/faiss/faiss/impl/Quantizer.h +1 -1
  116. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +27 -1015
  117. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +5 -63
  118. data/vendor/faiss/faiss/impl/ResultHandler.h +232 -176
  119. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +444 -104
  120. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +0 -8
  121. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +280 -42
  122. data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +21 -14
  123. data/vendor/faiss/faiss/impl/code_distance/code_distance.h +22 -12
  124. data/vendor/faiss/faiss/impl/index_read.cpp +45 -19
  125. data/vendor/faiss/faiss/impl/index_write.cpp +60 -41
  126. data/vendor/faiss/faiss/impl/io.cpp +10 -10
  127. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +1 -1
  128. data/vendor/faiss/faiss/impl/platform_macros.h +18 -1
  129. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +3 -0
  130. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +7 -6
  131. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +52 -38
  132. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +40 -49
  133. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +960 -0
  134. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +176 -0
  135. data/vendor/faiss/faiss/impl/simd_result_handlers.h +374 -202
  136. data/vendor/faiss/faiss/index_factory.cpp +10 -7
  137. data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
  138. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +27 -9
  139. data/vendor/faiss/faiss/invlists/InvertedLists.h +12 -3
  140. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +3 -3
  141. data/vendor/faiss/faiss/python/python_callbacks.cpp +1 -1
  142. data/vendor/faiss/faiss/utils/Heap.cpp +3 -1
  143. data/vendor/faiss/faiss/utils/WorkerThread.h +1 -0
  144. data/vendor/faiss/faiss/utils/distances.cpp +128 -74
  145. data/vendor/faiss/faiss/utils/distances.h +81 -4
  146. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +5 -5
  147. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +2 -2
  148. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +2 -2
  149. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +1 -1
  150. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +5 -5
  151. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.h +1 -1
  152. data/vendor/faiss/faiss/utils/distances_simd.cpp +428 -70
  153. data/vendor/faiss/faiss/utils/fp16-arm.h +29 -0
  154. data/vendor/faiss/faiss/utils/fp16.h +2 -0
  155. data/vendor/faiss/faiss/utils/hamming.cpp +162 -110
  156. data/vendor/faiss/faiss/utils/hamming.h +58 -0
  157. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +16 -89
  158. data/vendor/faiss/faiss/utils/hamming_distance/common.h +1 -0
  159. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +15 -87
  160. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +57 -0
  161. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +14 -104
  162. data/vendor/faiss/faiss/utils/partitioning.cpp +3 -4
  163. data/vendor/faiss/faiss/utils/prefetch.h +77 -0
  164. data/vendor/faiss/faiss/utils/quantize_lut.cpp +0 -14
  165. data/vendor/faiss/faiss/utils/simdlib_avx2.h +0 -6
  166. data/vendor/faiss/faiss/utils/simdlib_neon.h +72 -77
  167. data/vendor/faiss/faiss/utils/sorting.cpp +140 -5
  168. data/vendor/faiss/faiss/utils/sorting.h +27 -0
  169. data/vendor/faiss/faiss/utils/utils.cpp +112 -6
  170. data/vendor/faiss/faiss/utils/utils.h +57 -20
  171. metadata +10 -3
@@ -195,8 +195,9 @@ void NNDescent::update() {
195
195
  int l = 0;
196
196
 
197
197
  while ((l < maxl) && (c < S)) {
198
- if (nn.pool[l].flag)
198
+ if (nn.pool[l].flag) {
199
199
  ++c;
200
+ }
200
201
  ++l;
201
202
  }
202
203
  nn.M = l;
@@ -305,8 +306,9 @@ void NNDescent::generate_eval_set(
305
306
  for (int i = 0; i < c.size(); i++) {
306
307
  std::vector<Neighbor> tmp;
307
308
  for (int j = 0; j < N; j++) {
308
- if (c[i] == j)
309
+ if (c[i] == j) {
309
310
  continue; // skip itself
311
+ }
310
312
  float dist = qdis.symmetric_dis(c[i], j);
311
313
  tmp.push_back(Neighbor(j, dist, true));
312
314
  }
@@ -360,8 +362,9 @@ void NNDescent::init_graph(DistanceComputer& qdis) {
360
362
 
361
363
  for (int j = 0; j < S; j++) {
362
364
  int id = tmp[j];
363
- if (id == i)
365
+ if (id == i) {
364
366
  continue;
367
+ }
365
368
  float dist = qdis.symmetric_dis(i, id);
366
369
 
367
370
  graph[i].pool.push_back(Neighbor(id, dist, true));
@@ -374,6 +377,10 @@ void NNDescent::init_graph(DistanceComputer& qdis) {
374
377
 
375
378
  void NNDescent::build(DistanceComputer& qdis, const int n, bool verbose) {
376
379
  FAISS_THROW_IF_NOT_MSG(L >= K, "L should be >= K in NNDescent.build");
380
+ FAISS_THROW_IF_NOT_FMT(
381
+ n > NUM_EVAL_POINTS,
382
+ "NNDescent.build cannot build a graph smaller than %d",
383
+ int(NUM_EVAL_POINTS));
377
384
 
378
385
  if (verbose) {
379
386
  printf("Parameters: K=%d, S=%d, R=%d, L=%d, iter=%d\n",
@@ -403,7 +410,7 @@ void NNDescent::build(DistanceComputer& qdis, const int n, bool verbose) {
403
410
  has_built = true;
404
411
 
405
412
  if (verbose) {
406
- printf("Addes %d points into the index\n", ntotal);
413
+ printf("Added %d points into the index\n", ntotal);
407
414
  }
408
415
  }
409
416
 
@@ -414,30 +421,30 @@ void NNDescent::search(
414
421
  float* dists,
415
422
  VisitedTable& vt) const {
416
423
  FAISS_THROW_IF_NOT_MSG(has_built, "The index is not build yet.");
417
- int L = std::max(search_L, topk);
424
+ int L_2 = std::max(search_L, topk);
418
425
 
419
426
  // candidate pool, the K best items is the result.
420
- std::vector<Neighbor> retset(L + 1);
427
+ std::vector<Neighbor> retset(L_2 + 1);
421
428
 
422
- // Randomly choose L points to initialize the candidate pool
423
- std::vector<int> init_ids(L);
429
+ // Randomly choose L_2 points to initialize the candidate pool
430
+ std::vector<int> init_ids(L_2);
424
431
  std::mt19937 rng(random_seed);
425
432
 
426
- gen_random(rng, init_ids.data(), L, ntotal);
427
- for (int i = 0; i < L; i++) {
433
+ gen_random(rng, init_ids.data(), L_2, ntotal);
434
+ for (int i = 0; i < L_2; i++) {
428
435
  int id = init_ids[i];
429
436
  float dist = qdis(id);
430
437
  retset[i] = Neighbor(id, dist, true);
431
438
  }
432
439
 
433
440
  // Maintain the candidate pool in ascending order
434
- std::sort(retset.begin(), retset.begin() + L);
441
+ std::sort(retset.begin(), retset.begin() + L_2);
435
442
 
436
443
  int k = 0;
437
444
 
438
- // Stop until the smallest position updated is >= L
439
- while (k < L) {
440
- int nk = L;
445
+ // Stop until the smallest position updated is >= L_2
446
+ while (k < L_2) {
447
+ int nk = L_2;
441
448
 
442
449
  if (retset[k].flag) {
443
450
  retset[k].flag = false;
@@ -445,25 +452,28 @@ void NNDescent::search(
445
452
 
446
453
  for (int m = 0; m < K; ++m) {
447
454
  int id = final_graph[n * K + m];
448
- if (vt.get(id))
455
+ if (vt.get(id)) {
449
456
  continue;
457
+ }
450
458
 
451
459
  vt.set(id);
452
460
  float dist = qdis(id);
453
- if (dist >= retset[L - 1].distance)
461
+ if (dist >= retset[L_2 - 1].distance) {
454
462
  continue;
463
+ }
455
464
 
456
465
  Neighbor nn(id, dist, true);
457
- int r = insert_into_pool(retset.data(), L, nn);
466
+ int r = insert_into_pool(retset.data(), L_2, nn);
458
467
 
459
468
  if (r < nk)
460
469
  nk = r;
461
470
  }
462
471
  }
463
- if (nk <= k)
472
+ if (nk <= k) {
464
473
  k = nk;
465
- else
474
+ } else {
466
475
  ++k;
476
+ }
467
477
  }
468
478
  for (size_t i = 0; i < topk; i++) {
469
479
  indices[i] = retset[i].id;
@@ -54,7 +54,7 @@ namespace nsg {
54
54
 
55
55
  template <class node_t>
56
56
  struct Graph {
57
- node_t* data; ///< the flattened adjacency matrix
57
+ node_t* data; ///< the flattened adjacency matrix, size N-by-K
58
58
  int K; ///< nb of neighbors per node
59
59
  int N; ///< total nb of nodes
60
60
  bool own_fields; ///< the underlying data owned by itself or not
@@ -12,11 +12,11 @@
12
12
  #include <omp.h>
13
13
  #include <stdint.h>
14
14
 
15
+ #include <algorithm>
15
16
  #include <cmath>
16
17
  #include <cstdlib>
17
18
  #include <cstring>
18
-
19
- #include <algorithm>
19
+ #include <memory>
20
20
 
21
21
  #include <faiss/utils/distances.h>
22
22
  #include <faiss/utils/hamming.h>
@@ -683,18 +683,21 @@ struct RankingScore2 : Score3Computer<float, double> {
683
683
  double accum_gt_weight_diff(
684
684
  const std::vector<int>& a,
685
685
  const std::vector<int>& b) {
686
- int nb = b.size(), na = a.size();
686
+ const auto nb_2 = b.size();
687
+ const auto na = a.size();
687
688
 
688
689
  double accu = 0;
689
- int j = 0;
690
- for (int i = 0; i < na; i++) {
691
- int ai = a[i];
692
- while (j < nb && ai >= b[j])
690
+ size_t j = 0;
691
+ for (size_t i = 0; i < na; i++) {
692
+ const auto ai = a[i];
693
+ while (j < nb_2 && ai >= b[j]) {
693
694
  j++;
695
+ }
694
696
 
695
697
  double accu_i = 0;
696
- for (int k = j; k < b.size(); k++)
698
+ for (auto k = j; k < b.size(); k++) {
697
699
  accu_i += rank_weight(b[k] - ai);
700
+ }
698
701
 
699
702
  accu += rank_weight(ai) * accu_i;
700
703
  }
@@ -882,14 +885,13 @@ void PolysemousTraining::optimize_ranking(
882
885
 
883
886
  double t0 = getmillisecs();
884
887
 
885
- PermutationObjective* obj = new RankingScore2(
888
+ std::unique_ptr<PermutationObjective> obj(new RankingScore2(
886
889
  nbits,
887
890
  nq,
888
891
  nb,
889
892
  codes.data(),
890
893
  codes.data() + nq,
891
- gt_distances.data());
892
- ScopeDeleter1<PermutationObjective> del(obj);
894
+ gt_distances.data()));
893
895
 
894
896
  if (verbose > 0) {
895
897
  printf(" m=%d, nq=%zd, nb=%zd, initialize RankingScore "
@@ -900,7 +902,7 @@ void PolysemousTraining::optimize_ranking(
900
902
  getmillisecs() - t0);
901
903
  }
902
904
 
903
- SimulatedAnnealingOptimizer optim(obj, *this);
905
+ SimulatedAnnealingOptimizer optim(obj.get(), *this);
904
906
 
905
907
  if (log_pattern.size()) {
906
908
  char fname[256];
@@ -151,4 +151,4 @@ struct ProductResidualQuantizer : ProductAdditiveQuantizer {
151
151
  ProductResidualQuantizer();
152
152
  };
153
153
 
154
- }; // namespace faiss
154
+ } // namespace faiss
@@ -135,11 +135,10 @@ void ProductQuantizer::train(size_t n, const float* x) {
135
135
  }
136
136
  }
137
137
 
138
- float* xslice = new float[n * dsub];
139
- ScopeDeleter<float> del(xslice);
138
+ std::unique_ptr<float[]> xslice(new float[n * dsub]);
140
139
  for (int m = 0; m < M; m++) {
141
140
  for (int j = 0; j < n; j++)
142
- memcpy(xslice + j * dsub,
141
+ memcpy(xslice.get() + j * dsub,
143
142
  x + j * d + m * dsub,
144
143
  dsub * sizeof(float));
145
144
 
@@ -153,11 +152,19 @@ void ProductQuantizer::train(size_t n, const float* x) {
153
152
  switch (final_train_type) {
154
153
  case Train_hypercube:
155
154
  init_hypercube(
156
- dsub, nbits, n, xslice, clus.centroids.data());
155
+ dsub,
156
+ nbits,
157
+ n,
158
+ xslice.get(),
159
+ clus.centroids.data());
157
160
  break;
158
161
  case Train_hypercube_pca:
159
162
  init_hypercube_pca(
160
- dsub, nbits, n, xslice, clus.centroids.data());
163
+ dsub,
164
+ nbits,
165
+ n,
166
+ xslice.get(),
167
+ clus.centroids.data());
161
168
  break;
162
169
  case Train_hot_start:
163
170
  memcpy(clus.centroids.data(),
@@ -172,7 +179,7 @@ void ProductQuantizer::train(size_t n, const float* x) {
172
179
  printf("Training PQ slice %d/%zd\n", m, M);
173
180
  }
174
181
  IndexFlatL2 index(dsub);
175
- clus.train(n, xslice, assign_index ? *assign_index : index);
182
+ clus.train(n, xslice.get(), assign_index ? *assign_index : index);
176
183
  set_params(clus.centroids.data(), m);
177
184
  }
178
185
 
@@ -306,7 +313,8 @@ void ProductQuantizer::decode(const uint8_t* code, float* x) const {
306
313
  }
307
314
 
308
315
  void ProductQuantizer::decode(const uint8_t* code, float* x, size_t n) const {
309
- for (size_t i = 0; i < n; i++) {
316
+ #pragma omp parallel for if (n > 100)
317
+ for (int64_t i = 0; i < n; i++) {
310
318
  this->decode(code + code_size * i, x + d * i);
311
319
  }
312
320
  }
@@ -342,21 +350,20 @@ void ProductQuantizer::compute_codes_with_assign_index(
342
350
  assign_index->reset();
343
351
  assign_index->add(ksub, get_centroids(m, 0));
344
352
  size_t bs = 65536;
345
- float* xslice = new float[bs * dsub];
346
- ScopeDeleter<float> del(xslice);
347
- idx_t* assign = new idx_t[bs];
348
- ScopeDeleter<idx_t> del2(assign);
353
+
354
+ std::unique_ptr<float[]> xslice(new float[bs * dsub]);
355
+ std::unique_ptr<idx_t[]> assign(new idx_t[bs]);
349
356
 
350
357
  for (size_t i0 = 0; i0 < n; i0 += bs) {
351
358
  size_t i1 = std::min(i0 + bs, n);
352
359
 
353
360
  for (size_t i = i0; i < i1; i++) {
354
- memcpy(xslice + (i - i0) * dsub,
361
+ memcpy(xslice.get() + (i - i0) * dsub,
355
362
  x + i * d + m * dsub,
356
363
  dsub * sizeof(float));
357
364
  }
358
365
 
359
- assign_index->assign(i1 - i0, xslice, assign);
366
+ assign_index->assign(i1 - i0, xslice.get(), assign.get());
360
367
 
361
368
  if (nbits == 8) {
362
369
  uint8_t* c = codes + code_size * i0 + m;
@@ -405,15 +412,14 @@ void ProductQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
405
412
  for (int64_t i = 0; i < n; i++)
406
413
  compute_code(x + i * d, codes + i * code_size);
407
414
 
408
- } else { // worthwile to use BLAS
409
- float* dis_tables = new float[n * ksub * M];
410
- ScopeDeleter<float> del(dis_tables);
411
- compute_distance_tables(n, x, dis_tables);
415
+ } else { // worthwhile to use BLAS
416
+ std::unique_ptr<float[]> dis_tables(new float[n * ksub * M]);
417
+ compute_distance_tables(n, x, dis_tables.get());
412
418
 
413
419
  #pragma omp parallel for
414
420
  for (int64_t i = 0; i < n; i++) {
415
421
  uint8_t* code = codes + i * code_size;
416
- const float* tab = dis_tables + i * ksub * M;
422
+ const float* tab = dis_tables.get() + i * ksub * M;
417
423
  compute_code_from_distance_table(tab, code);
418
424
  }
419
425
  }
@@ -774,10 +780,6 @@ void ProductQuantizer::search_ip(
774
780
  init_finalize_heap);
775
781
  }
776
782
 
777
- static float sqr(float x) {
778
- return x * x;
779
- }
780
-
781
783
  void ProductQuantizer::compute_sdc_table() {
782
784
  sdc_table.resize(M * ksub * ksub);
783
785
 
@@ -35,7 +35,7 @@ struct ProductQuantizer : Quantizer {
35
35
  enum train_type_t {
36
36
  Train_default,
37
37
  Train_hot_start, ///< the centroids are already initialized
38
- Train_shared, ///< share dictionary accross PQ segments
38
+ Train_shared, ///< share dictionary across PQ segments
39
39
  Train_hypercube, ///< initialize centroids with nbits-D hypercube
40
40
  Train_hypercube_pca, ///< initialize centroids with nbits-D hypercube
41
41
  };
@@ -11,7 +11,7 @@
11
11
 
12
12
  namespace faiss {
13
13
 
14
- /** Product Quantizer. Implemented only for METRIC_L2 */
14
+ /** General interface for quantizer objects */
15
15
  struct Quantizer {
16
16
  size_t d; ///< size of the input vectors
17
17
  size_t code_size; ///< bytes per indexed vector