faiss 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/ext/faiss/extconf.rb +1 -1
  4. data/lib/faiss/version.rb +1 -1
  5. data/vendor/faiss/benchs/bench_6bit_codec.cpp +80 -0
  6. data/vendor/faiss/c_api/AutoTune_c.h +2 -0
  7. data/vendor/faiss/c_api/IndexShards_c.cpp +0 -6
  8. data/vendor/faiss/c_api/IndexShards_c.h +1 -4
  9. data/vendor/faiss/c_api/gpu/GpuAutoTune_c.cpp +4 -2
  10. data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.cpp +1 -1
  11. data/vendor/faiss/c_api/gpu/GpuIndex_c.cpp +1 -1
  12. data/vendor/faiss/c_api/gpu/GpuResources_c.cpp +1 -1
  13. data/vendor/faiss/c_api/gpu/StandardGpuResources_c.cpp +1 -1
  14. data/vendor/faiss/demos/demo_imi_flat.cpp +5 -2
  15. data/vendor/faiss/demos/demo_imi_pq.cpp +6 -2
  16. data/vendor/faiss/demos/demo_ivfpq_indexing.cpp +7 -2
  17. data/vendor/faiss/{AutoTune.cpp → faiss/AutoTune.cpp} +9 -9
  18. data/vendor/faiss/{AutoTune.h → faiss/AutoTune.h} +0 -0
  19. data/vendor/faiss/{Clustering.cpp → faiss/Clustering.cpp} +13 -12
  20. data/vendor/faiss/{Clustering.h → faiss/Clustering.h} +0 -0
  21. data/vendor/faiss/{DirectMap.cpp → faiss/DirectMap.cpp} +0 -0
  22. data/vendor/faiss/{DirectMap.h → faiss/DirectMap.h} +0 -0
  23. data/vendor/faiss/{IVFlib.cpp → faiss/IVFlib.cpp} +86 -11
  24. data/vendor/faiss/{IVFlib.h → faiss/IVFlib.h} +26 -8
  25. data/vendor/faiss/{Index.cpp → faiss/Index.cpp} +0 -0
  26. data/vendor/faiss/{Index.h → faiss/Index.h} +1 -1
  27. data/vendor/faiss/{Index2Layer.cpp → faiss/Index2Layer.cpp} +12 -11
  28. data/vendor/faiss/{Index2Layer.h → faiss/Index2Layer.h} +0 -0
  29. data/vendor/faiss/{IndexBinary.cpp → faiss/IndexBinary.cpp} +2 -1
  30. data/vendor/faiss/{IndexBinary.h → faiss/IndexBinary.h} +0 -0
  31. data/vendor/faiss/{IndexBinaryFlat.cpp → faiss/IndexBinaryFlat.cpp} +0 -0
  32. data/vendor/faiss/{IndexBinaryFlat.h → faiss/IndexBinaryFlat.h} +0 -0
  33. data/vendor/faiss/{IndexBinaryFromFloat.cpp → faiss/IndexBinaryFromFloat.cpp} +1 -0
  34. data/vendor/faiss/{IndexBinaryFromFloat.h → faiss/IndexBinaryFromFloat.h} +0 -0
  35. data/vendor/faiss/{IndexBinaryHNSW.cpp → faiss/IndexBinaryHNSW.cpp} +1 -2
  36. data/vendor/faiss/{IndexBinaryHNSW.h → faiss/IndexBinaryHNSW.h} +0 -0
  37. data/vendor/faiss/{IndexBinaryHash.cpp → faiss/IndexBinaryHash.cpp} +16 -7
  38. data/vendor/faiss/{IndexBinaryHash.h → faiss/IndexBinaryHash.h} +2 -1
  39. data/vendor/faiss/{IndexBinaryIVF.cpp → faiss/IndexBinaryIVF.cpp} +10 -16
  40. data/vendor/faiss/{IndexBinaryIVF.h → faiss/IndexBinaryIVF.h} +1 -1
  41. data/vendor/faiss/{IndexFlat.cpp → faiss/IndexFlat.cpp} +0 -0
  42. data/vendor/faiss/{IndexFlat.h → faiss/IndexFlat.h} +0 -0
  43. data/vendor/faiss/{IndexHNSW.cpp → faiss/IndexHNSW.cpp} +63 -32
  44. data/vendor/faiss/{IndexHNSW.h → faiss/IndexHNSW.h} +0 -0
  45. data/vendor/faiss/{IndexIVF.cpp → faiss/IndexIVF.cpp} +129 -46
  46. data/vendor/faiss/{IndexIVF.h → faiss/IndexIVF.h} +7 -3
  47. data/vendor/faiss/{IndexIVFFlat.cpp → faiss/IndexIVFFlat.cpp} +6 -5
  48. data/vendor/faiss/{IndexIVFFlat.h → faiss/IndexIVFFlat.h} +0 -0
  49. data/vendor/faiss/{IndexIVFPQ.cpp → faiss/IndexIVFPQ.cpp} +9 -8
  50. data/vendor/faiss/{IndexIVFPQ.h → faiss/IndexIVFPQ.h} +4 -2
  51. data/vendor/faiss/{IndexIVFPQR.cpp → faiss/IndexIVFPQR.cpp} +3 -1
  52. data/vendor/faiss/{IndexIVFPQR.h → faiss/IndexIVFPQR.h} +0 -0
  53. data/vendor/faiss/{IndexIVFSpectralHash.cpp → faiss/IndexIVFSpectralHash.cpp} +1 -1
  54. data/vendor/faiss/{IndexIVFSpectralHash.h → faiss/IndexIVFSpectralHash.h} +0 -0
  55. data/vendor/faiss/{IndexLSH.cpp → faiss/IndexLSH.cpp} +0 -0
  56. data/vendor/faiss/{IndexLSH.h → faiss/IndexLSH.h} +0 -0
  57. data/vendor/faiss/{IndexLattice.cpp → faiss/IndexLattice.cpp} +0 -0
  58. data/vendor/faiss/{IndexLattice.h → faiss/IndexLattice.h} +0 -0
  59. data/vendor/faiss/{IndexPQ.cpp → faiss/IndexPQ.cpp} +6 -6
  60. data/vendor/faiss/{IndexPQ.h → faiss/IndexPQ.h} +3 -1
  61. data/vendor/faiss/{IndexPreTransform.cpp → faiss/IndexPreTransform.cpp} +0 -0
  62. data/vendor/faiss/{IndexPreTransform.h → faiss/IndexPreTransform.h} +0 -0
  63. data/vendor/faiss/{IndexReplicas.cpp → faiss/IndexReplicas.cpp} +102 -10
  64. data/vendor/faiss/{IndexReplicas.h → faiss/IndexReplicas.h} +6 -0
  65. data/vendor/faiss/{IndexScalarQuantizer.cpp → faiss/IndexScalarQuantizer.cpp} +3 -3
  66. data/vendor/faiss/{IndexScalarQuantizer.h → faiss/IndexScalarQuantizer.h} +0 -0
  67. data/vendor/faiss/{IndexShards.cpp → faiss/IndexShards.cpp} +37 -12
  68. data/vendor/faiss/{IndexShards.h → faiss/IndexShards.h} +3 -4
  69. data/vendor/faiss/{InvertedLists.cpp → faiss/InvertedLists.cpp} +2 -2
  70. data/vendor/faiss/{InvertedLists.h → faiss/InvertedLists.h} +1 -0
  71. data/vendor/faiss/{MatrixStats.cpp → faiss/MatrixStats.cpp} +0 -0
  72. data/vendor/faiss/{MatrixStats.h → faiss/MatrixStats.h} +0 -0
  73. data/vendor/faiss/{MetaIndexes.cpp → faiss/MetaIndexes.cpp} +5 -3
  74. data/vendor/faiss/{MetaIndexes.h → faiss/MetaIndexes.h} +0 -0
  75. data/vendor/faiss/{MetricType.h → faiss/MetricType.h} +0 -0
  76. data/vendor/faiss/{OnDiskInvertedLists.cpp → faiss/OnDiskInvertedLists.cpp} +141 -3
  77. data/vendor/faiss/{OnDiskInvertedLists.h → faiss/OnDiskInvertedLists.h} +27 -7
  78. data/vendor/faiss/{VectorTransform.cpp → faiss/VectorTransform.cpp} +4 -3
  79. data/vendor/faiss/{VectorTransform.h → faiss/VectorTransform.h} +0 -0
  80. data/vendor/faiss/{clone_index.cpp → faiss/clone_index.cpp} +0 -0
  81. data/vendor/faiss/{clone_index.h → faiss/clone_index.h} +0 -0
  82. data/vendor/faiss/{gpu → faiss/gpu}/GpuAutoTune.cpp +0 -0
  83. data/vendor/faiss/{gpu → faiss/gpu}/GpuAutoTune.h +0 -0
  84. data/vendor/faiss/{gpu → faiss/gpu}/GpuCloner.cpp +14 -14
  85. data/vendor/faiss/{gpu → faiss/gpu}/GpuCloner.h +6 -7
  86. data/vendor/faiss/{gpu → faiss/gpu}/GpuClonerOptions.cpp +0 -0
  87. data/vendor/faiss/{gpu → faiss/gpu}/GpuClonerOptions.h +0 -0
  88. data/vendor/faiss/{gpu → faiss/gpu}/GpuDistance.h +12 -4
  89. data/vendor/faiss/{gpu → faiss/gpu}/GpuFaissAssert.h +0 -0
  90. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndex.h +3 -9
  91. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexBinaryFlat.h +7 -7
  92. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexFlat.h +35 -10
  93. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexIVF.h +1 -2
  94. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexIVFFlat.h +4 -3
  95. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexIVFPQ.h +21 -4
  96. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexIVFScalarQuantizer.h +4 -3
  97. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndicesOptions.h +0 -0
  98. data/vendor/faiss/faiss/gpu/GpuResources.cpp +200 -0
  99. data/vendor/faiss/faiss/gpu/GpuResources.h +264 -0
  100. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +572 -0
  101. data/vendor/faiss/{gpu → faiss/gpu}/StandardGpuResources.h +83 -15
  102. data/vendor/faiss/{gpu → faiss/gpu}/impl/RemapIndices.cpp +0 -0
  103. data/vendor/faiss/{gpu → faiss/gpu}/impl/RemapIndices.h +0 -0
  104. data/vendor/faiss/{gpu → faiss/gpu}/perf/IndexWrapper-inl.h +1 -1
  105. data/vendor/faiss/{gpu → faiss/gpu}/perf/IndexWrapper.h +1 -1
  106. data/vendor/faiss/{gpu → faiss/gpu}/perf/PerfClustering.cpp +1 -1
  107. data/vendor/faiss/{gpu → faiss/gpu}/perf/PerfIVFPQAdd.cpp +0 -0
  108. data/vendor/faiss/{gpu → faiss/gpu}/perf/WriteIndex.cpp +0 -0
  109. data/vendor/faiss/{gpu → faiss/gpu}/test/TestGpuIndexBinaryFlat.cpp +0 -0
  110. data/vendor/faiss/{gpu → faiss/gpu}/test/TestGpuIndexFlat.cpp +1 -1
  111. data/vendor/faiss/{gpu → faiss/gpu}/test/TestGpuIndexIVFFlat.cpp +0 -0
  112. data/vendor/faiss/{gpu → faiss/gpu}/test/TestGpuIndexIVFPQ.cpp +141 -52
  113. data/vendor/faiss/{gpu → faiss/gpu}/test/TestGpuMemoryException.cpp +0 -0
  114. data/vendor/faiss/{gpu → faiss/gpu}/test/TestUtils.cpp +4 -2
  115. data/vendor/faiss/{gpu → faiss/gpu}/test/TestUtils.h +0 -0
  116. data/vendor/faiss/{gpu → faiss/gpu}/test/demo_ivfpq_indexing_gpu.cpp +7 -5
  117. data/vendor/faiss/{gpu → faiss/gpu}/utils/DeviceUtils.h +1 -1
  118. data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +213 -0
  119. data/vendor/faiss/{gpu → faiss/gpu}/utils/StackDeviceMemory.h +25 -40
  120. data/vendor/faiss/{gpu → faiss/gpu}/utils/StaticUtils.h +0 -0
  121. data/vendor/faiss/{gpu → faiss/gpu}/utils/Timer.cpp +0 -0
  122. data/vendor/faiss/{gpu → faiss/gpu}/utils/Timer.h +0 -0
  123. data/vendor/faiss/{impl → faiss/impl}/AuxIndexStructures.cpp +1 -0
  124. data/vendor/faiss/{impl → faiss/impl}/AuxIndexStructures.h +3 -1
  125. data/vendor/faiss/{impl → faiss/impl}/FaissAssert.h +1 -0
  126. data/vendor/faiss/{impl → faiss/impl}/FaissException.cpp +26 -0
  127. data/vendor/faiss/{impl → faiss/impl}/FaissException.h +4 -0
  128. data/vendor/faiss/{impl → faiss/impl}/HNSW.cpp +26 -26
  129. data/vendor/faiss/{impl → faiss/impl}/HNSW.h +19 -11
  130. data/vendor/faiss/{impl → faiss/impl}/PolysemousTraining.cpp +1 -1
  131. data/vendor/faiss/{impl → faiss/impl}/PolysemousTraining.h +1 -1
  132. data/vendor/faiss/{impl → faiss/impl}/ProductQuantizer-inl.h +0 -1
  133. data/vendor/faiss/{impl → faiss/impl}/ProductQuantizer.cpp +9 -9
  134. data/vendor/faiss/{impl → faiss/impl}/ProductQuantizer.h +0 -0
  135. data/vendor/faiss/{impl → faiss/impl}/ScalarQuantizer.cpp +63 -39
  136. data/vendor/faiss/{impl → faiss/impl}/ScalarQuantizer.h +1 -1
  137. data/vendor/faiss/{impl → faiss/impl}/ThreadedIndex-inl.h +0 -0
  138. data/vendor/faiss/{impl → faiss/impl}/ThreadedIndex.h +0 -0
  139. data/vendor/faiss/{impl → faiss/impl}/index_read.cpp +99 -116
  140. data/vendor/faiss/{impl → faiss/impl}/index_write.cpp +15 -50
  141. data/vendor/faiss/{impl → faiss/impl}/io.cpp +15 -10
  142. data/vendor/faiss/{impl → faiss/impl}/io.h +22 -8
  143. data/vendor/faiss/faiss/impl/io_macros.h +57 -0
  144. data/vendor/faiss/{impl → faiss/impl}/lattice_Zn.cpp +52 -36
  145. data/vendor/faiss/{impl → faiss/impl}/lattice_Zn.h +3 -3
  146. data/vendor/faiss/faiss/impl/platform_macros.h +24 -0
  147. data/vendor/faiss/{index_factory.cpp → faiss/index_factory.cpp} +33 -12
  148. data/vendor/faiss/{index_factory.h → faiss/index_factory.h} +0 -0
  149. data/vendor/faiss/{index_io.h → faiss/index_io.h} +55 -1
  150. data/vendor/faiss/faiss/python/python_callbacks.cpp +112 -0
  151. data/vendor/faiss/faiss/python/python_callbacks.h +45 -0
  152. data/vendor/faiss/{utils → faiss/utils}/Heap.cpp +5 -5
  153. data/vendor/faiss/{utils → faiss/utils}/Heap.h +1 -3
  154. data/vendor/faiss/{utils → faiss/utils}/WorkerThread.cpp +0 -0
  155. data/vendor/faiss/{utils → faiss/utils}/WorkerThread.h +0 -0
  156. data/vendor/faiss/{utils → faiss/utils}/distances.cpp +28 -13
  157. data/vendor/faiss/{utils → faiss/utils}/distances.h +2 -1
  158. data/vendor/faiss/{utils → faiss/utils}/distances_simd.cpp +5 -5
  159. data/vendor/faiss/{utils → faiss/utils}/extra_distances.cpp +8 -7
  160. data/vendor/faiss/{utils → faiss/utils}/extra_distances.h +0 -0
  161. data/vendor/faiss/{utils → faiss/utils}/hamming-inl.h +1 -3
  162. data/vendor/faiss/{utils → faiss/utils}/hamming.cpp +8 -7
  163. data/vendor/faiss/{utils → faiss/utils}/hamming.h +7 -1
  164. data/vendor/faiss/{utils → faiss/utils}/random.cpp +5 -5
  165. data/vendor/faiss/{utils → faiss/utils}/random.h +0 -0
  166. data/vendor/faiss/{utils → faiss/utils}/utils.cpp +27 -28
  167. data/vendor/faiss/{utils → faiss/utils}/utils.h +4 -0
  168. data/vendor/faiss/misc/test_blas.cpp +4 -1
  169. data/vendor/faiss/tests/test_binary_flat.cpp +0 -2
  170. data/vendor/faiss/tests/test_dealloc_invlists.cpp +6 -1
  171. data/vendor/faiss/tests/test_ivfpq_codec.cpp +4 -1
  172. data/vendor/faiss/tests/test_ivfpq_indexing.cpp +6 -4
  173. data/vendor/faiss/tests/test_lowlevel_ivf.cpp +12 -5
  174. data/vendor/faiss/tests/test_merge.cpp +6 -3
  175. data/vendor/faiss/tests/test_ondisk_ivf.cpp +7 -2
  176. data/vendor/faiss/tests/test_pairs_decoding.cpp +5 -1
  177. data/vendor/faiss/tests/test_params_override.cpp +7 -2
  178. data/vendor/faiss/tests/test_sliding_ivf.cpp +10 -4
  179. data/vendor/faiss/tutorial/cpp/1-Flat.cpp +14 -8
  180. data/vendor/faiss/tutorial/cpp/2-IVFFlat.cpp +11 -7
  181. data/vendor/faiss/tutorial/cpp/3-IVFPQ.cpp +12 -7
  182. data/vendor/faiss/tutorial/cpp/4-GPU.cpp +6 -3
  183. data/vendor/faiss/tutorial/cpp/5-Multiple-GPUs.cpp +7 -3
  184. metadata +154 -153
  185. data/vendor/faiss/gpu/GpuResources.cpp +0 -52
  186. data/vendor/faiss/gpu/GpuResources.h +0 -73
  187. data/vendor/faiss/gpu/StandardGpuResources.cpp +0 -303
  188. data/vendor/faiss/gpu/utils/DeviceMemory.cpp +0 -77
  189. data/vendor/faiss/gpu/utils/DeviceMemory.h +0 -71
  190. data/vendor/faiss/gpu/utils/MemorySpace.cpp +0 -89
  191. data/vendor/faiss/gpu/utils/MemorySpace.h +0 -44
  192. data/vendor/faiss/gpu/utils/StackDeviceMemory.cpp +0 -239
@@ -11,6 +11,7 @@
11
11
  #define FAISS_ASSERT_INCLUDED
12
12
 
13
13
  #include <faiss/impl/FaissException.h>
14
+ #include <faiss/impl/platform_macros.h>
14
15
  #include <cstdlib>
15
16
  #include <cstdio>
16
17
  #include <string>
@@ -10,6 +10,10 @@
10
10
  #include <faiss/impl/FaissException.h>
11
11
  #include <sstream>
12
12
 
13
+ #ifdef __GNUG__
14
+ #include <cxxabi.h>
15
+ #endif
16
+
13
17
  namespace faiss {
14
18
 
15
19
  FaissException::FaissException(const std::string& m)
@@ -63,4 +67,26 @@ void handleExceptions(
63
67
  }
64
68
  }
65
69
 
70
+
71
+ // From
72
+ // https://stackoverflow.com/questions/281818/unmangling-the-result-of-stdtype-infoname
73
+
74
+ std::string demangle_cpp_symbol(const char* name) {
75
+ #ifdef __GNUG__
76
+ int status = -1;
77
+ const char * res = abi::__cxa_demangle(name, nullptr, nullptr, &status);
78
+ std::string sres;
79
+ if (status == 0) {
80
+ sres = res;
81
+ }
82
+ free((void*)res);
83
+ return sres;
84
+ #else
85
+ // don't know how to do this on other platforms
86
+ return std::string(name);
87
+ #endif
66
88
  }
89
+
90
+
91
+
92
+ } // namespace
@@ -66,6 +66,10 @@ struct ScopeDeleter1 {
66
66
  }
67
67
  };
68
68
 
69
+ /// make typeids more readable
70
+ std::string demangle_cpp_symbol(const char* name);
71
+
72
+
69
73
  }
70
74
 
71
75
  #endif
@@ -157,11 +157,11 @@ void HNSW::print_neighbor_stats(int level) const
157
157
  }
158
158
  }
159
159
  float normalizer = n_node;
160
- printf(" nb of nodes at that level %ld\n", n_node);
161
- printf(" neighbors per node: %.2f (%ld)\n",
160
+ printf(" nb of nodes at that level %zd\n", n_node);
161
+ printf(" neighbors per node: %.2f (%zd)\n",
162
162
  tot_neigh / normalizer, tot_neigh);
163
163
  printf(" nb of reciprocal neighbors: %.2f\n", tot_reciprocal / normalizer);
164
- printf(" nb of neighbors that are also neighbor-of-neighbors: %.2f (%ld)\n",
164
+ printf(" nb of neighbors that are also neighbor-of-neighbors: %.2f (%zd)\n",
165
165
  tot_common / normalizer, tot_common);
166
166
 
167
167
 
@@ -181,7 +181,7 @@ void HNSW::fill_with_random_links(size_t n)
181
181
  elts.push_back(i);
182
182
  }
183
183
  }
184
- printf ("linking %ld elements in level %d\n",
184
+ printf ("linking %zd elements in level %d\n",
185
185
  elts.size(), level);
186
186
 
187
187
  if (elts.size() == 1) continue;
@@ -527,6 +527,7 @@ int HNSW::search_from_candidates(
527
527
  idx_t *I, float *D,
528
528
  MinimaxHeap& candidates,
529
529
  VisitedTable& vt,
530
+ HNSWStats& stats,
530
531
  int level, int nres_in) const
531
532
  {
532
533
  int nres = nres_in;
@@ -590,14 +591,11 @@ int HNSW::search_from_candidates(
590
591
  }
591
592
 
592
593
  if (level == 0) {
593
- #pragma omp critical
594
- {
595
- hnsw_stats.n1 ++;
596
- if (candidates.size() == 0) {
597
- hnsw_stats.n2 ++;
598
- }
599
- hnsw_stats.n3 += ndis;
594
+ stats.n1 ++;
595
+ if (candidates.size() == 0) {
596
+ stats.n2 ++;
600
597
  }
598
+ stats.n3 += ndis;
601
599
  }
602
600
 
603
601
  return nres;
@@ -612,7 +610,8 @@ std::priority_queue<HNSW::Node> HNSW::search_from_candidate_unbounded(
612
610
  const Node& node,
613
611
  DistanceComputer& qdis,
614
612
  int ef,
615
- VisitedTable *vt) const
613
+ VisitedTable *vt,
614
+ HNSWStats& stats) const
616
615
  {
617
616
  int ndis = 0;
618
617
  std::priority_queue<Node> top_candidates;
@@ -663,22 +662,21 @@ std::priority_queue<HNSW::Node> HNSW::search_from_candidate_unbounded(
663
662
  }
664
663
  }
665
664
 
666
- #pragma omp critical
667
- {
668
- ++hnsw_stats.n1;
669
- if (candidates.size() == 0) {
670
- ++hnsw_stats.n2;
671
- }
672
- hnsw_stats.n3 += ndis;
665
+ ++stats.n1;
666
+ if (candidates.size() == 0) {
667
+ ++stats.n2;
673
668
  }
669
+ stats.n3 += ndis;
674
670
 
675
671
  return top_candidates;
676
672
  }
677
673
 
678
- void HNSW::search(DistanceComputer& qdis, int k,
679
- idx_t *I, float *D,
680
- VisitedTable& vt) const
674
+ HNSWStats HNSW::search(DistanceComputer& qdis, int k,
675
+ idx_t *I, float *D,
676
+ VisitedTable& vt) const
681
677
  {
678
+ HNSWStats stats;
679
+
682
680
  if (upper_beam == 1) {
683
681
 
684
682
  // greedy search on upper levels
@@ -695,11 +693,11 @@ void HNSW::search(DistanceComputer& qdis, int k,
695
693
 
696
694
  candidates.push(nearest, d_nearest);
697
695
 
698
- search_from_candidates(qdis, k, I, D, candidates, vt, 0);
696
+ search_from_candidates(qdis, k, I, D, candidates, vt, stats, 0);
699
697
  } else {
700
698
  std::priority_queue<Node> top_candidates =
701
699
  search_from_candidate_unbounded(Node(d_nearest, nearest),
702
- qdis, ef, &vt);
700
+ qdis, ef, &vt, stats);
703
701
 
704
702
  while (top_candidates.size() > k) {
705
703
  top_candidates.pop();
@@ -739,17 +737,19 @@ void HNSW::search(DistanceComputer& qdis, int k,
739
737
  }
740
738
 
741
739
  if (level == 0) {
742
- nres = search_from_candidates(qdis, k, I, D, candidates, vt, 0);
740
+ nres = search_from_candidates(qdis, k, I, D, candidates, vt, stats, 0);
743
741
  } else {
744
742
  nres = search_from_candidates(
745
743
  qdis, candidates_size,
746
744
  I_to_next.data(), D_to_next.data(),
747
- candidates, vt, level
745
+ candidates, vt, stats, level
748
746
  );
749
747
  }
750
748
  vt.advance();
751
749
  }
752
750
  }
751
+
752
+ return stats;
753
753
  }
754
754
 
755
755
 
@@ -19,6 +19,7 @@
19
19
  #include <faiss/impl/FaissAssert.h>
20
20
  #include <faiss/utils/random.h>
21
21
  #include <faiss/utils/Heap.h>
22
+ #include <faiss/impl/platform_macros.h>
22
23
 
23
24
 
24
25
  namespace faiss {
@@ -43,6 +44,7 @@ namespace faiss {
43
44
 
44
45
  struct VisitedTable;
45
46
  struct DistanceComputer; // from AuxIndexStructures
47
+ struct HNSWStats;
46
48
 
47
49
  struct HNSW {
48
50
  /// internal storage of vectors (32 bits: this is expensive)
@@ -186,19 +188,20 @@ struct HNSW {
186
188
  idx_t *I, float *D,
187
189
  MinimaxHeap& candidates,
188
190
  VisitedTable &vt,
191
+ HNSWStats &stats,
189
192
  int level, int nres_in = 0) const;
190
193
 
191
194
  std::priority_queue<Node> search_from_candidate_unbounded(
192
195
  const Node& node,
193
196
  DistanceComputer& qdis,
194
197
  int ef,
195
- VisitedTable *vt
196
- ) const;
198
+ VisitedTable *vt,
199
+ HNSWStats &stats) const;
197
200
 
198
201
  /// search interface
199
- void search(DistanceComputer& qdis, int k,
200
- idx_t *I, float *D,
201
- VisitedTable& vt) const;
202
+ HNSWStats search(DistanceComputer& qdis, int k,
203
+ idx_t *I, float *D,
204
+ VisitedTable &vt) const;
202
205
 
203
206
  void reset();
204
207
 
@@ -254,22 +257,27 @@ struct HNSWStats {
254
257
  size_t n1, n2, n3;
255
258
  size_t ndis;
256
259
  size_t nreorder;
257
- bool view;
258
260
 
259
- HNSWStats() {
260
- reset();
261
- }
261
+ HNSWStats(size_t n1 = 0, size_t n2 = 0, size_t n3 = 0, size_t ndis = 0, size_t nreorder = 0)
262
+ : n1(n1), n2(n2), n3(n3), ndis(ndis), nreorder(nreorder) {}
262
263
 
263
264
  void reset() {
264
265
  n1 = n2 = n3 = 0;
265
266
  ndis = 0;
266
267
  nreorder = 0;
267
- view = false;
268
+ }
269
+
270
+ void combine(const HNSWStats& other) {
271
+ n1 += other.n1;
272
+ n2 += other.n2;
273
+ n3 += other.n3;
274
+ ndis += other.ndis;
275
+ nreorder += other.nreorder;
268
276
  }
269
277
  };
270
278
 
271
279
  // global var that collects them all
272
- extern HNSWStats hnsw_stats;
280
+ FAISS_API extern HNSWStats hnsw_stats;
273
281
 
274
282
 
275
283
  } // namespace faiss
@@ -893,7 +893,7 @@ void PolysemousTraining::optimize_ranking (
893
893
  ScopeDeleter1<PermutationObjective> del (obj);
894
894
 
895
895
  if (verbose > 0) {
896
- printf(" m=%d, nq=%ld, nb=%ld, intialize RankingScore "
896
+ printf(" m=%d, nq=%zd, nb=%zd, intialize RankingScore "
897
897
  "in %.3f ms\n",
898
898
  m, nq, nb, getmillisecs () - t0);
899
899
  }
@@ -101,7 +101,7 @@ struct RandomGenerator;
101
101
  const SimulatedAnnealingParameters &p);
102
102
  RandomGenerator *rnd;
103
103
 
104
- /// remember intial cost of optimization
104
+ /// remember initial cost of optimization
105
105
  double init_cost;
106
106
 
107
107
  // main entry point. Perform the optimization loop, starting from
@@ -134,5 +134,4 @@ uint64_t PQDecoder16::decode() {
134
134
  return (uint64_t)(*code++);
135
135
  }
136
136
 
137
-
138
137
  } // namespace faiss
@@ -261,7 +261,7 @@ void ProductQuantizer::train (int n, const float * x)
261
261
  train_type == Train_hypercube_pca) {
262
262
  if (dsub < nbits) {
263
263
  final_train_type = Train_default;
264
- printf ("cannot train hypercube: nbits=%ld > log2(d=%ld)\n",
264
+ printf ("cannot train hypercube: nbits=%zd > log2(d=%zd)\n",
265
265
  nbits, dsub);
266
266
  }
267
267
  }
@@ -329,14 +329,14 @@ void ProductQuantizer::train (int n, const float * x)
329
329
 
330
330
  template<class PQEncoder>
331
331
  void compute_code(const ProductQuantizer& pq, const float *x, uint8_t *code) {
332
- float distances [pq.ksub];
332
+ std::vector<float> distances(pq.ksub);
333
333
  PQEncoder encoder(code, pq.nbits);
334
334
  for (size_t m = 0; m < pq.M; m++) {
335
335
  float mindis = 1e20;
336
336
  uint64_t idxm = 0;
337
337
  const float * xsub = x + m * pq.dsub;
338
338
 
339
- fvec_L2sqr_ny(distances, xsub, pq.get_centroids(m, 0), pq.dsub, pq.ksub);
339
+ fvec_L2sqr_ny(distances.data(), xsub, pq.get_centroids(m, 0), pq.dsub, pq.ksub);
340
340
 
341
341
  /* Find best centroid */
342
342
  for (size_t i = 0; i < pq.ksub; i++) {
@@ -496,7 +496,7 @@ void ProductQuantizer::compute_codes (const float * x,
496
496
  if (dsub < 16) { // simple direct computation
497
497
 
498
498
  #pragma omp parallel for
499
- for (size_t i = 0; i < n; i++)
499
+ for (int64_t i = 0; i < n; i++)
500
500
  compute_code (x + i * d, codes + i * code_size);
501
501
 
502
502
  } else { // worthwile to use BLAS
@@ -505,7 +505,7 @@ void ProductQuantizer::compute_codes (const float * x,
505
505
  compute_distance_tables (n, x, dis_tables);
506
506
 
507
507
  #pragma omp parallel for
508
- for (size_t i = 0; i < n; i++) {
508
+ for (int64_t i = 0; i < n; i++) {
509
509
  uint8_t * code = codes + i * code_size;
510
510
  const float * tab = dis_tables + i * ksub * M;
511
511
  compute_code_from_distance_table (tab, code);
@@ -552,7 +552,7 @@ void ProductQuantizer::compute_distance_tables (
552
552
  if (dsub < 16) {
553
553
 
554
554
  #pragma omp parallel for
555
- for (size_t i = 0; i < nx; i++) {
555
+ for (int64_t i = 0; i < nx; i++) {
556
556
  compute_distance_table (x + i * d, dis_tables + i * ksub * M);
557
557
  }
558
558
 
@@ -577,7 +577,7 @@ void ProductQuantizer::compute_inner_prod_tables (
577
577
  if (dsub < 16) {
578
578
 
579
579
  #pragma omp parallel for
580
- for (size_t i = 0; i < nx; i++) {
580
+ for (int64_t i = 0; i < nx; i++) {
581
581
  compute_inner_prod_table (x + i * d, dis_tables + i * ksub * M);
582
582
  }
583
583
 
@@ -614,7 +614,7 @@ static void pq_knn_search_with_tables (
614
614
 
615
615
 
616
616
  #pragma omp parallel for
617
- for (size_t i = 0; i < nx; i++) {
617
+ for (int64_t i = 0; i < nx; i++) {
618
618
  /* query preparation for asymmetric search: compute look-up tables */
619
619
  const float* dis_table = dis_tables + i * ksub * M;
620
620
 
@@ -728,7 +728,7 @@ void ProductQuantizer::search_sdc (const uint8_t * qcodes,
728
728
 
729
729
 
730
730
  #pragma omp parallel for
731
- for (size_t i = 0; i < nq; i++) {
731
+ for (int64_t i = 0; i < nq; i++) {
732
732
 
733
733
  /* Compute distances and keep smallest values */
734
734
  idx_t * heap_ids = res->ids + i * k;
@@ -39,11 +39,7 @@ namespace faiss {
39
39
  * that hides the template mess.
40
40
  ********************************************************************/
41
41
 
42
- #ifdef __AVX__
43
- #define USE_AVX
44
- #endif
45
-
46
- #ifdef __F16C__
42
+ #if defined(__F16C__) && defined(__AVX2__)
47
43
  #define USE_F16C
48
44
  #endif
49
45
 
@@ -72,7 +68,7 @@ struct Codec8bit {
72
68
  return (code[i] + 0.5f) / 255.0f;
73
69
  }
74
70
 
75
- #ifdef USE_AVX
71
+ #ifdef __AVX2__
76
72
  static __m256 decode_8_components (const uint8_t *code, int i) {
77
73
  uint64_t c8 = *(uint64_t*)(code + i);
78
74
  __m128i c4lo = _mm_cvtepu8_epi32 (_mm_set1_epi32(c8));
@@ -101,7 +97,7 @@ struct Codec4bit {
101
97
  }
102
98
 
103
99
 
104
- #ifdef USE_AVX
100
+ #ifdef __AVX2__
105
101
  static __m256 decode_8_components (const uint8_t *code, int i) {
106
102
  uint32_t c4 = *(uint32_t*)(code + (i >> 1));
107
103
  uint32_t mask = 0x0f0f0f0f;
@@ -169,18 +165,38 @@ struct Codec6bit {
169
165
  return (bits + 0.5f) / 63.0f;
170
166
  }
171
167
 
172
- #ifdef USE_AVX
168
+ #ifdef __AVX2__
169
+
170
+ /* Load 6 bytes that represent 8 6-bit values, return them as a
171
+ * 8*32 bit vector register */
172
+ static __m256i load6 (const uint16_t *code16) {
173
+ const __m128i perm = _mm_set_epi8(-1, 5, 5, 4, 4, 3, -1, 3, -1, 2, 2, 1, 1, 0, -1, 0);
174
+ const __m256i shifts = _mm256_set_epi32(2, 4, 6, 0, 2, 4, 6, 0);
175
+
176
+ // load 6 bytes
177
+ __m128i c1 = _mm_set_epi16(0, 0, 0, 0, 0, code16[2], code16[1], code16[0]);
178
+
179
+ // put in 8 * 32 bits
180
+ __m128i c2 = _mm_shuffle_epi8(c1, perm);
181
+ __m256i c3 = _mm256_cvtepi16_epi32(c2);
182
+
183
+ // shift and mask out useless bits
184
+ __m256i c4 = _mm256_srlv_epi32(c3, shifts);
185
+ __m256i c5 = _mm256_and_si256(_mm256_set1_epi32(63), c4);
186
+ return c5;
187
+ }
188
+
173
189
  static __m256 decode_8_components (const uint8_t *code, int i) {
174
- return _mm256_set_ps
175
- (decode_component(code, i + 7),
176
- decode_component(code, i + 6),
177
- decode_component(code, i + 5),
178
- decode_component(code, i + 4),
179
- decode_component(code, i + 3),
180
- decode_component(code, i + 2),
181
- decode_component(code, i + 1),
182
- decode_component(code, i + 0));
190
+ __m256i i8 = load6 ((const uint16_t *)(code + (i >> 2) * 3));
191
+ __m256 f8 = _mm256_cvtepi32_ps (i8);
192
+ // this could also be done with bit manipulations but it is
193
+ // not obviously faster
194
+ __m256 half = _mm256_set1_ps (0.5f);
195
+ f8 += half;
196
+ __m256 one_63 = _mm256_set1_ps (1.f / 63.f);
197
+ return f8 * one_63;
183
198
  }
199
+
184
200
  #endif
185
201
  };
186
202
 
@@ -326,12 +342,15 @@ struct QuantizerTemplate<Codec, true, 1>: ScalarQuantizer::Quantizer {
326
342
 
327
343
  void encode_vector(const float* x, uint8_t* code) const final {
328
344
  for (size_t i = 0; i < d; i++) {
329
- float xi = (x[i] - vmin) / vdiff;
330
- if (xi < 0) {
331
- xi = 0;
332
- }
333
- if (xi > 1.0) {
334
- xi = 1.0;
345
+ float xi = 0;
346
+ if (vdiff != 0) {
347
+ xi = (x[i] - vmin) / vdiff;
348
+ if (xi < 0) {
349
+ xi = 0;
350
+ }
351
+ if (xi > 1.0) {
352
+ xi = 1.0;
353
+ }
335
354
  }
336
355
  Codec::encode_component(xi, code, i);
337
356
  }
@@ -354,7 +373,7 @@ struct QuantizerTemplate<Codec, true, 1>: ScalarQuantizer::Quantizer {
354
373
 
355
374
 
356
375
 
357
- #ifdef USE_AVX
376
+ #ifdef __AVX2__
358
377
 
359
378
  template<class Codec>
360
379
  struct QuantizerTemplate<Codec, true, 8>: QuantizerTemplate<Codec, true, 1> {
@@ -384,11 +403,16 @@ struct QuantizerTemplate<Codec, false, 1>: ScalarQuantizer::Quantizer {
384
403
 
385
404
  void encode_vector(const float* x, uint8_t* code) const final {
386
405
  for (size_t i = 0; i < d; i++) {
387
- float xi = (x[i] - vmin[i]) / vdiff[i];
388
- if (xi < 0)
389
- xi = 0;
390
- if (xi > 1.0)
391
- xi = 1.0;
406
+ float xi = 0;
407
+ if (vdiff[i] != 0) {
408
+ xi = (x[i] - vmin[i]) / vdiff[i];
409
+ if (xi < 0) {
410
+ xi = 0;
411
+ }
412
+ if (xi > 1.0) {
413
+ xi = 1.0;
414
+ }
415
+ }
392
416
  Codec::encode_component(xi, code, i);
393
417
  }
394
418
  }
@@ -409,7 +433,7 @@ struct QuantizerTemplate<Codec, false, 1>: ScalarQuantizer::Quantizer {
409
433
  };
410
434
 
411
435
 
412
- #ifdef USE_AVX
436
+ #ifdef __AVX2__
413
437
 
414
438
  template<class Codec>
415
439
  struct QuantizerTemplate<Codec, false, 8>: QuantizerTemplate<Codec, false, 1> {
@@ -513,7 +537,7 @@ struct Quantizer8bitDirect<1>: ScalarQuantizer::Quantizer {
513
537
 
514
538
  };
515
539
 
516
- #ifdef USE_AVX
540
+ #ifdef __AVX2__
517
541
 
518
542
  template<>
519
543
  struct Quantizer8bitDirect<8>: Quantizer8bitDirect<1> {
@@ -691,7 +715,7 @@ void train_NonUniform(RangeStat rs, float rs_arg,
691
715
  float vexp = (vmax[j] - vmin[j]) * rs_arg;
692
716
  vmin[j] -= vexp;
693
717
  vmax[j] += vexp;
694
- vdiff [j] = vmax[j] - vmin[j];
718
+ vdiff[j] = vmax[j] - vmin[j];
695
719
  }
696
720
  } else {
697
721
  // transpose
@@ -704,7 +728,7 @@ void train_NonUniform(RangeStat rs, float rs_arg,
704
728
  }
705
729
  std::vector<float> trained_d(2);
706
730
  #pragma omp parallel for
707
- for (size_t j = 0; j < d; j++) {
731
+ for (int j = 0; j < d; j++) {
708
732
  train_Uniform(rs, rs_arg,
709
733
  n, k, xt.data() + j * n,
710
734
  trained_d);
@@ -760,7 +784,7 @@ struct SimilarityL2<1> {
760
784
  };
761
785
 
762
786
 
763
- #ifdef USE_AVX
787
+ #ifdef __AVX2__
764
788
  template<>
765
789
  struct SimilarityL2<8> {
766
790
  static constexpr int simdwidth = 8;
@@ -835,7 +859,7 @@ struct SimilarityIP<1> {
835
859
  }
836
860
  };
837
861
 
838
- #ifdef USE_AVX
862
+ #ifdef __AVX2__
839
863
 
840
864
  template<>
841
865
  struct SimilarityIP<8> {
@@ -915,7 +939,7 @@ struct DCTemplate<Quantizer, Similarity, 1> : SQDistanceComputer
915
939
  for (size_t i = 0; i < quant.d; i++) {
916
940
  float x1 = quant.reconstruct_component(code1, i);
917
941
  float x2 = quant.reconstruct_component(code2, i);
918
- sim.add_component_2(x1, x2);
942
+ sim.add_component_2(x1, x2);
919
943
  }
920
944
  return sim.result();
921
945
  }
@@ -1058,7 +1082,7 @@ struct DistanceComputerByte<Similarity, 1> : SQDistanceComputer {
1058
1082
 
1059
1083
  };
1060
1084
 
1061
- #ifdef USE_AVX
1085
+ #ifdef __AVX2__
1062
1086
 
1063
1087
 
1064
1088
  template<class Similarity>
@@ -1298,7 +1322,7 @@ void ScalarQuantizer::compute_codes (const float * x,
1298
1322
 
1299
1323
  memset (codes, 0, code_size * n);
1300
1324
  #pragma omp parallel for
1301
- for (size_t i = 0; i < n; i++)
1325
+ for (int64_t i = 0; i < n; i++)
1302
1326
  squant->encode_vector (x + i * d, codes + i * code_size);
1303
1327
  }
1304
1328
 
@@ -1307,7 +1331,7 @@ void ScalarQuantizer::decode (const uint8_t *codes, float *x, size_t n) const
1307
1331
  std::unique_ptr<Quantizer> squant(select_quantizer ());
1308
1332
 
1309
1333
  #pragma omp parallel for
1310
- for (size_t i = 0; i < n; i++)
1334
+ for (int64_t i = 0; i < n; i++)
1311
1335
  squant->decode_vector (codes + i * code_size, x + i * d);
1312
1336
  }
1313
1337