faiss 0.1.2 → 0.1.3

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 (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