faiss 0.2.0 → 0.2.4

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 (215) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +7 -7
  5. data/ext/faiss/extconf.rb +6 -3
  6. data/ext/faiss/numo.hpp +4 -4
  7. data/ext/faiss/utils.cpp +1 -1
  8. data/ext/faiss/utils.h +1 -1
  9. data/lib/faiss/version.rb +1 -1
  10. data/vendor/faiss/faiss/AutoTune.cpp +292 -291
  11. data/vendor/faiss/faiss/AutoTune.h +55 -56
  12. data/vendor/faiss/faiss/Clustering.cpp +365 -194
  13. data/vendor/faiss/faiss/Clustering.h +102 -35
  14. data/vendor/faiss/faiss/IVFlib.cpp +171 -195
  15. data/vendor/faiss/faiss/IVFlib.h +48 -51
  16. data/vendor/faiss/faiss/Index.cpp +85 -103
  17. data/vendor/faiss/faiss/Index.h +54 -48
  18. data/vendor/faiss/faiss/Index2Layer.cpp +126 -224
  19. data/vendor/faiss/faiss/Index2Layer.h +22 -36
  20. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +407 -0
  21. data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +195 -0
  22. data/vendor/faiss/faiss/IndexBinary.cpp +45 -37
  23. data/vendor/faiss/faiss/IndexBinary.h +140 -132
  24. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +73 -53
  25. data/vendor/faiss/faiss/IndexBinaryFlat.h +29 -24
  26. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +46 -43
  27. data/vendor/faiss/faiss/IndexBinaryFromFloat.h +16 -15
  28. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +215 -232
  29. data/vendor/faiss/faiss/IndexBinaryHNSW.h +25 -24
  30. data/vendor/faiss/faiss/IndexBinaryHash.cpp +182 -177
  31. data/vendor/faiss/faiss/IndexBinaryHash.h +41 -34
  32. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +489 -461
  33. data/vendor/faiss/faiss/IndexBinaryIVF.h +97 -68
  34. data/vendor/faiss/faiss/IndexFlat.cpp +115 -176
  35. data/vendor/faiss/faiss/IndexFlat.h +42 -59
  36. data/vendor/faiss/faiss/IndexFlatCodes.cpp +67 -0
  37. data/vendor/faiss/faiss/IndexFlatCodes.h +47 -0
  38. data/vendor/faiss/faiss/IndexHNSW.cpp +372 -348
  39. data/vendor/faiss/faiss/IndexHNSW.h +57 -41
  40. data/vendor/faiss/faiss/IndexIVF.cpp +545 -453
  41. data/vendor/faiss/faiss/IndexIVF.h +169 -118
  42. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +316 -0
  43. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +121 -0
  44. data/vendor/faiss/faiss/IndexIVFFlat.cpp +247 -252
  45. data/vendor/faiss/faiss/IndexIVFFlat.h +48 -51
  46. data/vendor/faiss/faiss/IndexIVFPQ.cpp +459 -517
  47. data/vendor/faiss/faiss/IndexIVFPQ.h +75 -67
  48. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +406 -372
  49. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +82 -57
  50. data/vendor/faiss/faiss/IndexIVFPQR.cpp +104 -102
  51. data/vendor/faiss/faiss/IndexIVFPQR.h +33 -28
  52. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +163 -150
  53. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +38 -25
  54. data/vendor/faiss/faiss/IndexLSH.cpp +66 -113
  55. data/vendor/faiss/faiss/IndexLSH.h +20 -38
  56. data/vendor/faiss/faiss/IndexLattice.cpp +42 -56
  57. data/vendor/faiss/faiss/IndexLattice.h +11 -16
  58. data/vendor/faiss/faiss/IndexNNDescent.cpp +229 -0
  59. data/vendor/faiss/faiss/IndexNNDescent.h +72 -0
  60. data/vendor/faiss/faiss/IndexNSG.cpp +301 -0
  61. data/vendor/faiss/faiss/IndexNSG.h +85 -0
  62. data/vendor/faiss/faiss/IndexPQ.cpp +387 -495
  63. data/vendor/faiss/faiss/IndexPQ.h +64 -82
  64. data/vendor/faiss/faiss/IndexPQFastScan.cpp +143 -170
  65. data/vendor/faiss/faiss/IndexPQFastScan.h +46 -32
  66. data/vendor/faiss/faiss/IndexPreTransform.cpp +120 -150
  67. data/vendor/faiss/faiss/IndexPreTransform.h +33 -36
  68. data/vendor/faiss/faiss/IndexRefine.cpp +139 -127
  69. data/vendor/faiss/faiss/IndexRefine.h +32 -23
  70. data/vendor/faiss/faiss/IndexReplicas.cpp +147 -153
  71. data/vendor/faiss/faiss/IndexReplicas.h +62 -56
  72. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +111 -172
  73. data/vendor/faiss/faiss/IndexScalarQuantizer.h +41 -59
  74. data/vendor/faiss/faiss/IndexShards.cpp +256 -240
  75. data/vendor/faiss/faiss/IndexShards.h +85 -73
  76. data/vendor/faiss/faiss/MatrixStats.cpp +112 -97
  77. data/vendor/faiss/faiss/MatrixStats.h +7 -10
  78. data/vendor/faiss/faiss/MetaIndexes.cpp +135 -157
  79. data/vendor/faiss/faiss/MetaIndexes.h +40 -34
  80. data/vendor/faiss/faiss/MetricType.h +7 -7
  81. data/vendor/faiss/faiss/VectorTransform.cpp +654 -475
  82. data/vendor/faiss/faiss/VectorTransform.h +64 -89
  83. data/vendor/faiss/faiss/clone_index.cpp +78 -73
  84. data/vendor/faiss/faiss/clone_index.h +4 -9
  85. data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +33 -38
  86. data/vendor/faiss/faiss/gpu/GpuAutoTune.h +11 -9
  87. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +198 -171
  88. data/vendor/faiss/faiss/gpu/GpuCloner.h +53 -35
  89. data/vendor/faiss/faiss/gpu/GpuClonerOptions.cpp +12 -14
  90. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +27 -25
  91. data/vendor/faiss/faiss/gpu/GpuDistance.h +116 -112
  92. data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -2
  93. data/vendor/faiss/faiss/gpu/GpuIcmEncoder.h +60 -0
  94. data/vendor/faiss/faiss/gpu/GpuIndex.h +134 -137
  95. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +76 -73
  96. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +173 -162
  97. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +67 -64
  98. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +89 -86
  99. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +150 -141
  100. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +101 -103
  101. data/vendor/faiss/faiss/gpu/GpuIndicesOptions.h +17 -16
  102. data/vendor/faiss/faiss/gpu/GpuResources.cpp +116 -128
  103. data/vendor/faiss/faiss/gpu/GpuResources.h +182 -186
  104. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +433 -422
  105. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +131 -130
  106. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +468 -456
  107. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.h +25 -19
  108. data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +22 -20
  109. data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +9 -8
  110. data/vendor/faiss/faiss/gpu/perf/IndexWrapper-inl.h +39 -44
  111. data/vendor/faiss/faiss/gpu/perf/IndexWrapper.h +16 -14
  112. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +77 -71
  113. data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +109 -88
  114. data/vendor/faiss/faiss/gpu/perf/WriteIndex.cpp +75 -64
  115. data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +230 -215
  116. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +80 -86
  117. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +284 -277
  118. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +416 -416
  119. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +611 -517
  120. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +166 -164
  121. data/vendor/faiss/faiss/gpu/test/TestGpuMemoryException.cpp +61 -53
  122. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +274 -238
  123. data/vendor/faiss/faiss/gpu/test/TestUtils.h +73 -57
  124. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +47 -50
  125. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +79 -72
  126. data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +140 -146
  127. data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.h +69 -71
  128. data/vendor/faiss/faiss/gpu/utils/StaticUtils.h +21 -16
  129. data/vendor/faiss/faiss/gpu/utils/Timer.cpp +25 -29
  130. data/vendor/faiss/faiss/gpu/utils/Timer.h +30 -29
  131. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +503 -0
  132. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +175 -0
  133. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +90 -120
  134. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +81 -65
  135. data/vendor/faiss/faiss/impl/FaissAssert.h +73 -58
  136. data/vendor/faiss/faiss/impl/FaissException.cpp +56 -48
  137. data/vendor/faiss/faiss/impl/FaissException.h +41 -29
  138. data/vendor/faiss/faiss/impl/HNSW.cpp +606 -617
  139. data/vendor/faiss/faiss/impl/HNSW.h +179 -200
  140. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +855 -0
  141. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +244 -0
  142. data/vendor/faiss/faiss/impl/NNDescent.cpp +487 -0
  143. data/vendor/faiss/faiss/impl/NNDescent.h +154 -0
  144. data/vendor/faiss/faiss/impl/NSG.cpp +679 -0
  145. data/vendor/faiss/faiss/impl/NSG.h +199 -0
  146. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +484 -454
  147. data/vendor/faiss/faiss/impl/PolysemousTraining.h +52 -55
  148. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +26 -47
  149. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +469 -459
  150. data/vendor/faiss/faiss/impl/ProductQuantizer.h +76 -87
  151. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +758 -0
  152. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +188 -0
  153. data/vendor/faiss/faiss/impl/ResultHandler.h +96 -132
  154. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +647 -707
  155. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +48 -46
  156. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +129 -131
  157. data/vendor/faiss/faiss/impl/ThreadedIndex.h +61 -55
  158. data/vendor/faiss/faiss/impl/index_read.cpp +631 -480
  159. data/vendor/faiss/faiss/impl/index_write.cpp +547 -407
  160. data/vendor/faiss/faiss/impl/io.cpp +76 -95
  161. data/vendor/faiss/faiss/impl/io.h +31 -41
  162. data/vendor/faiss/faiss/impl/io_macros.h +60 -29
  163. data/vendor/faiss/faiss/impl/kmeans1d.cpp +301 -0
  164. data/vendor/faiss/faiss/impl/kmeans1d.h +48 -0
  165. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +137 -186
  166. data/vendor/faiss/faiss/impl/lattice_Zn.h +40 -51
  167. data/vendor/faiss/faiss/impl/platform_macros.h +29 -8
  168. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +77 -124
  169. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +39 -48
  170. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +41 -52
  171. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +80 -117
  172. data/vendor/faiss/faiss/impl/simd_result_handlers.h +109 -137
  173. data/vendor/faiss/faiss/index_factory.cpp +619 -397
  174. data/vendor/faiss/faiss/index_factory.h +8 -6
  175. data/vendor/faiss/faiss/index_io.h +23 -26
  176. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +67 -75
  177. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +22 -24
  178. data/vendor/faiss/faiss/invlists/DirectMap.cpp +96 -112
  179. data/vendor/faiss/faiss/invlists/DirectMap.h +29 -33
  180. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +307 -364
  181. data/vendor/faiss/faiss/invlists/InvertedLists.h +151 -151
  182. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +29 -34
  183. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.h +17 -18
  184. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +257 -293
  185. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +50 -45
  186. data/vendor/faiss/faiss/python/python_callbacks.cpp +23 -26
  187. data/vendor/faiss/faiss/python/python_callbacks.h +9 -16
  188. data/vendor/faiss/faiss/utils/AlignedTable.h +79 -44
  189. data/vendor/faiss/faiss/utils/Heap.cpp +40 -48
  190. data/vendor/faiss/faiss/utils/Heap.h +186 -209
  191. data/vendor/faiss/faiss/utils/WorkerThread.cpp +67 -76
  192. data/vendor/faiss/faiss/utils/WorkerThread.h +32 -33
  193. data/vendor/faiss/faiss/utils/distances.cpp +305 -312
  194. data/vendor/faiss/faiss/utils/distances.h +170 -122
  195. data/vendor/faiss/faiss/utils/distances_simd.cpp +498 -508
  196. data/vendor/faiss/faiss/utils/extra_distances-inl.h +117 -0
  197. data/vendor/faiss/faiss/utils/extra_distances.cpp +113 -232
  198. data/vendor/faiss/faiss/utils/extra_distances.h +30 -29
  199. data/vendor/faiss/faiss/utils/hamming-inl.h +260 -209
  200. data/vendor/faiss/faiss/utils/hamming.cpp +375 -469
  201. data/vendor/faiss/faiss/utils/hamming.h +62 -85
  202. data/vendor/faiss/faiss/utils/ordered_key_value.h +16 -18
  203. data/vendor/faiss/faiss/utils/partitioning.cpp +393 -318
  204. data/vendor/faiss/faiss/utils/partitioning.h +26 -21
  205. data/vendor/faiss/faiss/utils/quantize_lut.cpp +78 -66
  206. data/vendor/faiss/faiss/utils/quantize_lut.h +22 -20
  207. data/vendor/faiss/faiss/utils/random.cpp +39 -63
  208. data/vendor/faiss/faiss/utils/random.h +13 -16
  209. data/vendor/faiss/faiss/utils/simdlib.h +4 -2
  210. data/vendor/faiss/faiss/utils/simdlib_avx2.h +88 -85
  211. data/vendor/faiss/faiss/utils/simdlib_emulated.h +226 -165
  212. data/vendor/faiss/faiss/utils/simdlib_neon.h +832 -0
  213. data/vendor/faiss/faiss/utils/utils.cpp +304 -287
  214. data/vendor/faiss/faiss/utils/utils.h +54 -49
  215. metadata +29 -4
@@ -9,11 +9,12 @@
9
9
 
10
10
  #include <faiss/Index2Layer.h>
11
11
 
12
+ #include <faiss/impl/platform_macros.h>
13
+ #include <stdint.h>
14
+ #include <cassert>
12
15
  #include <cinttypes>
13
16
  #include <cmath>
14
17
  #include <cstdio>
15
- #include <cassert>
16
- #include <stdint.h>
17
18
 
18
19
  #ifdef __SSE3__
19
20
  #include <immintrin.h>
@@ -23,39 +24,27 @@
23
24
 
24
25
  #include <faiss/IndexIVFPQ.h>
25
26
 
26
- #include <faiss/impl/FaissAssert.h>
27
- #include <faiss/utils/utils.h>
28
- #include <faiss/impl/AuxIndexStructures.h>
29
27
  #include <faiss/IndexFlat.h>
28
+ #include <faiss/impl/AuxIndexStructures.h>
29
+ #include <faiss/impl/FaissAssert.h>
30
30
  #include <faiss/utils/distances.h>
31
-
32
-
33
- /*
34
- #include <faiss/utils/Heap.h>
35
-
36
- #include <faiss/Clustering.h>
37
-
38
- #include <faiss/utils/hamming.h>
39
-
40
-
41
- */
42
-
31
+ #include <faiss/utils/utils.h>
43
32
 
44
33
  namespace faiss {
45
34
 
46
-
47
35
  /*************************************
48
36
  * Index2Layer implementation
49
37
  *************************************/
50
38
 
51
-
52
- Index2Layer::Index2Layer (Index * quantizer, size_t nlist,
53
- int M, int nbit,
54
- MetricType metric):
55
- Index (quantizer->d, metric),
56
- q1 (quantizer, nlist),
57
- pq (quantizer->d, M, nbit)
58
- {
39
+ Index2Layer::Index2Layer(
40
+ Index* quantizer,
41
+ size_t nlist,
42
+ int M,
43
+ int nbit,
44
+ MetricType metric)
45
+ : IndexFlatCodes(0, quantizer->d, metric),
46
+ q1(quantizer, nlist),
47
+ pq(quantizer->d, M, nbit) {
59
48
  is_trained = false;
60
49
  for (int nbyte = 0; nbyte < 7; nbyte++) {
61
50
  if ((1L << (8 * nbyte)) >= nlist) {
@@ -67,177 +56,94 @@ Index2Layer::Index2Layer (Index * quantizer, size_t nlist,
67
56
  code_size = code_size_1 + code_size_2;
68
57
  }
69
58
 
70
- Index2Layer::Index2Layer ()
71
- {
59
+ Index2Layer::Index2Layer() {
72
60
  code_size = code_size_1 = code_size_2 = 0;
73
61
  }
74
62
 
75
- Index2Layer::~Index2Layer ()
76
- {}
63
+ Index2Layer::~Index2Layer() {}
77
64
 
78
- void Index2Layer::train(idx_t n, const float* x)
79
- {
65
+ void Index2Layer::train(idx_t n, const float* x) {
80
66
  if (verbose) {
81
- printf ("training level-1 quantizer %" PRId64 " vectors in %dD\n",
82
- n, d);
67
+ printf("training level-1 quantizer %" PRId64 " vectors in %dD\n", n, d);
83
68
  }
84
69
 
85
- q1.train_q1 (n, x, verbose, metric_type);
70
+ q1.train_q1(n, x, verbose, metric_type);
86
71
 
87
72
  if (verbose) {
88
73
  printf("computing residuals\n");
89
74
  }
90
75
 
91
- const float * x_in = x;
76
+ const float* x_in = x;
92
77
 
93
- x = fvecs_maybe_subsample (
94
- d, (size_t*)&n, pq.cp.max_points_per_centroid * pq.ksub,
95
- x, verbose, pq.cp.seed);
78
+ x = fvecs_maybe_subsample(
79
+ d,
80
+ (size_t*)&n,
81
+ pq.cp.max_points_per_centroid * pq.ksub,
82
+ x,
83
+ verbose,
84
+ pq.cp.seed);
96
85
 
97
- ScopeDeleter<float> del_x (x_in == x ? nullptr : x);
86
+ ScopeDeleter<float> del_x(x_in == x ? nullptr : x);
98
87
 
99
88
  std::vector<idx_t> assign(n); // assignement to coarse centroids
100
- q1.quantizer->assign (n, x, assign.data());
89
+ q1.quantizer->assign(n, x, assign.data());
101
90
  std::vector<float> residuals(n * d);
102
91
  for (idx_t i = 0; i < n; i++) {
103
- q1.quantizer->compute_residual (
104
- x + i * d, residuals.data() + i * d, assign[i]);
92
+ q1.quantizer->compute_residual(
93
+ x + i * d, residuals.data() + i * d, assign[i]);
105
94
  }
106
95
 
107
96
  if (verbose)
108
- printf ("training %zdx%zd product quantizer on %" PRId64 " vectors in %dD\n",
109
- pq.M, pq.ksub, n, d);
97
+ printf("training %zdx%zd product quantizer on %" PRId64
98
+ " vectors in %dD\n",
99
+ pq.M,
100
+ pq.ksub,
101
+ n,
102
+ d);
110
103
  pq.verbose = verbose;
111
- pq.train (n, residuals.data());
104
+ pq.train(n, residuals.data());
112
105
 
113
106
  is_trained = true;
114
107
  }
115
108
 
116
- void Index2Layer::add(idx_t n, const float* x)
117
- {
118
- idx_t bs = 32768;
119
- if (n > bs) {
120
- for (idx_t i0 = 0; i0 < n; i0 += bs) {
121
- idx_t i1 = std::min(i0 + bs, n);
122
- if (verbose) {
123
- printf("Index2Layer::add: adding %" PRId64 ":%" PRId64 " / %" PRId64 "\n",
124
- i0, i1, n);
125
- }
126
- add (i1 - i0, x + i0 * d);
127
- }
128
- return;
129
- }
130
-
131
- std::vector<idx_t> codes1 (n);
132
- q1.quantizer->assign (n, x, codes1.data());
133
- std::vector<float> residuals(n * d);
134
- for (idx_t i = 0; i < n; i++) {
135
- q1.quantizer->compute_residual (
136
- x + i * d, residuals.data() + i * d, codes1[i]);
137
- }
138
- std::vector<uint8_t> codes2 (n * code_size_2);
139
-
140
- pq.compute_codes (residuals.data(), codes2.data(), n);
141
-
142
- codes.resize ((ntotal + n) * code_size);
143
- uint8_t *wp = &codes[ntotal * code_size];
144
-
145
- {
146
- int i = 0x11223344;
147
- const char *ip = (char*)&i;
148
- FAISS_THROW_IF_NOT_MSG (ip[0] == 0x44,
149
- "works only on a little-endian CPU");
150
- }
151
-
152
- // copy to output table
153
- for (idx_t i = 0; i < n; i++) {
154
- memcpy (wp, &codes1[i], code_size_1);
155
- wp += code_size_1;
156
- memcpy (wp, &codes2[i * code_size_2], code_size_2);
157
- wp += code_size_2;
158
- }
159
-
160
- ntotal += n;
161
-
162
- }
163
-
164
109
  void Index2Layer::search(
165
- idx_t /*n*/,
166
- const float* /*x*/,
167
- idx_t /*k*/,
168
- float* /*distances*/,
169
- idx_t* /*labels*/) const {
170
- FAISS_THROW_MSG("not implemented");
110
+ idx_t /*n*/,
111
+ const float* /*x*/,
112
+ idx_t /*k*/,
113
+ float* /*distances*/,
114
+ idx_t* /*labels*/) const {
115
+ FAISS_THROW_MSG("not implemented");
171
116
  }
172
117
 
118
+ void Index2Layer::transfer_to_IVFPQ(IndexIVFPQ& other) const {
119
+ FAISS_THROW_IF_NOT(other.nlist == q1.nlist);
120
+ FAISS_THROW_IF_NOT(other.code_size == code_size_2);
121
+ FAISS_THROW_IF_NOT(other.ntotal == 0);
173
122
 
174
- void Index2Layer::reconstruct_n(idx_t i0, idx_t ni, float* recons) const
175
- {
176
- std::vector<float> recons1(d);
177
- FAISS_THROW_IF_NOT (i0 >= 0 && i0 + ni <= ntotal);
178
- const uint8_t *rp = &codes[i0 * code_size];
179
-
180
- for (idx_t i = 0; i < ni; i++) {
181
- idx_t key = 0;
182
- memcpy (&key, rp, code_size_1);
183
- q1.quantizer->reconstruct (key, recons1.data());
184
- rp += code_size_1;
185
- pq.decode (rp, recons);
186
- for (idx_t j = 0; j < d; j++) {
187
- recons[j] += recons1[j];
188
- }
189
- rp += code_size_2;
190
- recons += d;
191
- }
192
- }
193
-
194
- void Index2Layer::transfer_to_IVFPQ (IndexIVFPQ & other) const
195
- {
196
- FAISS_THROW_IF_NOT (other.nlist == q1.nlist);
197
- FAISS_THROW_IF_NOT (other.code_size == code_size_2);
198
- FAISS_THROW_IF_NOT (other.ntotal == 0);
199
-
200
- const uint8_t *rp = codes.data();
123
+ const uint8_t* rp = codes.data();
201
124
 
202
125
  for (idx_t i = 0; i < ntotal; i++) {
203
126
  idx_t key = 0;
204
- memcpy (&key, rp, code_size_1);
127
+ memcpy(&key, rp, code_size_1);
205
128
  rp += code_size_1;
206
- other.invlists->add_entry (key, i, rp);
129
+ other.invlists->add_entry(key, i, rp);
207
130
  rp += code_size_2;
208
131
  }
209
132
 
210
133
  other.ntotal = ntotal;
211
-
212
- }
213
-
214
-
215
-
216
- void Index2Layer::reconstruct(idx_t key, float* recons) const
217
- {
218
- reconstruct_n (key, 1, recons);
219
134
  }
220
135
 
221
- void Index2Layer::reset()
222
- {
223
- ntotal = 0;
224
- codes.clear ();
225
- }
226
-
227
-
228
136
  namespace {
229
137
 
230
-
231
138
  struct Distance2Level : DistanceComputer {
232
139
  size_t d;
233
140
  const Index2Layer& storage;
234
141
  std::vector<float> buf;
235
- const float *q;
142
+ const float* q;
236
143
 
237
144
  const float *pq_l1_tab, *pq_l2_tab;
238
145
 
239
- explicit Distance2Level(const Index2Layer& storage)
240
- : storage(storage) {
146
+ explicit Distance2Level(const Index2Layer& storage) : storage(storage) {
241
147
  d = storage.d;
242
148
  FAISS_ASSERT(storage.pq.dsub == 4);
243
149
  pq_l2_tab = storage.pq.centroids.data();
@@ -250,67 +156,64 @@ struct Distance2Level : DistanceComputer {
250
156
  return fvec_L2sqr(buf.data() + d, buf.data(), d);
251
157
  }
252
158
 
253
- void set_query(const float *x) override {
159
+ void set_query(const float* x) override {
254
160
  q = x;
255
161
  }
256
162
  };
257
163
 
258
164
  // well optimized for xNN+PQNN
259
165
  struct DistanceXPQ4 : Distance2Level {
260
-
261
166
  int M, k;
262
167
 
263
168
  explicit DistanceXPQ4(const Index2Layer& storage)
264
- : Distance2Level (storage) {
265
- const IndexFlat *quantizer =
266
- dynamic_cast<IndexFlat*> (storage.q1.quantizer);
169
+ : Distance2Level(storage) {
170
+ const IndexFlat* quantizer =
171
+ dynamic_cast<IndexFlat*>(storage.q1.quantizer);
267
172
 
268
173
  FAISS_ASSERT(quantizer);
269
174
  M = storage.pq.M;
270
- pq_l1_tab = quantizer->xb.data();
175
+ pq_l1_tab = quantizer->get_xb();
271
176
  }
272
177
 
273
- float operator () (idx_t i) override {
178
+ float operator()(idx_t i) override {
274
179
  #ifdef __SSE3__
275
- const uint8_t *code = storage.codes.data() + i * storage.code_size;
180
+ const uint8_t* code = storage.codes.data() + i * storage.code_size;
276
181
  long key = 0;
277
- memcpy (&key, code, storage.code_size_1);
182
+ memcpy(&key, code, storage.code_size_1);
278
183
  code += storage.code_size_1;
279
184
 
280
185
  // walking pointers
281
- const float *qa = q;
282
- const __m128 *l1_t = (const __m128 *)(pq_l1_tab + d * key);
283
- const __m128 *pq_l2_t = (const __m128 *)pq_l2_tab;
186
+ const float* qa = q;
187
+ const __m128* l1_t = (const __m128*)(pq_l1_tab + d * key);
188
+ const __m128* pq_l2_t = (const __m128*)pq_l2_tab;
284
189
  __m128 accu = _mm_setzero_ps();
285
190
 
286
191
  for (int m = 0; m < M; m++) {
287
192
  __m128 qi = _mm_loadu_ps(qa);
288
- __m128 recons = l1_t[m] + pq_l2_t[*code++];
289
- __m128 diff = qi - recons;
290
- accu += diff * diff;
193
+ __m128 recons = _mm_add_ps(l1_t[m], pq_l2_t[*code++]);
194
+ __m128 diff = _mm_sub_ps(qi, recons);
195
+ accu = _mm_add_ps(accu, _mm_mul_ps(diff, diff));
291
196
  pq_l2_t += 256;
292
197
  qa += 4;
293
198
  }
294
199
 
295
- accu = _mm_hadd_ps (accu, accu);
296
- accu = _mm_hadd_ps (accu, accu);
297
- return _mm_cvtss_f32 (accu);
200
+ accu = _mm_hadd_ps(accu, accu);
201
+ accu = _mm_hadd_ps(accu, accu);
202
+ return _mm_cvtss_f32(accu);
298
203
  #else
299
204
  FAISS_THROW_MSG("not implemented for non-x64 platforms");
300
205
  #endif
301
206
  }
302
-
303
207
  };
304
208
 
305
209
  // well optimized for 2xNN+PQNN
306
210
  struct Distance2xXPQ4 : Distance2Level {
307
-
308
211
  int M_2, mi_nbits;
309
212
 
310
213
  explicit Distance2xXPQ4(const Index2Layer& storage)
311
- : Distance2Level(storage) {
312
- const MultiIndexQuantizer *mi =
313
- dynamic_cast<MultiIndexQuantizer*> (storage.q1.quantizer);
214
+ : Distance2Level(storage) {
215
+ const MultiIndexQuantizer* mi =
216
+ dynamic_cast<MultiIndexQuantizer*>(storage.q1.quantizer);
314
217
 
315
218
  FAISS_ASSERT(mi);
316
219
  FAISS_ASSERT(storage.pq.M % 2 == 0);
@@ -319,59 +222,55 @@ struct Distance2xXPQ4 : Distance2Level {
319
222
  pq_l1_tab = mi->pq.centroids.data();
320
223
  }
321
224
 
322
- float operator () (idx_t i) override {
323
- const uint8_t *code = storage.codes.data() + i * storage.code_size;
225
+ float operator()(idx_t i) override {
226
+ const uint8_t* code = storage.codes.data() + i * storage.code_size;
324
227
  long key01 = 0;
325
- memcpy (&key01, code, storage.code_size_1);
228
+ memcpy(&key01, code, storage.code_size_1);
326
229
  code += storage.code_size_1;
327
230
  #ifdef __SSE3__
328
231
 
329
232
  // walking pointers
330
- const float *qa = q;
331
- const __m128 *pq_l1_t = (const __m128 *)pq_l1_tab;
332
- const __m128 *pq_l2_t = (const __m128 *)pq_l2_tab;
233
+ const float* qa = q;
234
+ const __m128* pq_l1_t = (const __m128*)pq_l1_tab;
235
+ const __m128* pq_l2_t = (const __m128*)pq_l2_tab;
333
236
  __m128 accu = _mm_setzero_ps();
334
237
 
335
238
  for (int mi_m = 0; mi_m < 2; mi_m++) {
336
239
  long l1_idx = key01 & ((1L << mi_nbits) - 1);
337
- const __m128 * pq_l1 = pq_l1_t + M_2 * l1_idx;
240
+ const __m128* pq_l1 = pq_l1_t + M_2 * l1_idx;
338
241
 
339
242
  for (int m = 0; m < M_2; m++) {
340
243
  __m128 qi = _mm_loadu_ps(qa);
341
- __m128 recons = pq_l1[m] + pq_l2_t[*code++];
342
- __m128 diff = qi - recons;
343
- accu += diff * diff;
244
+ __m128 recons = _mm_add_ps(pq_l1[m], pq_l2_t[*code++]);
245
+ __m128 diff = _mm_sub_ps(qi, recons);
246
+ accu = _mm_add_ps(accu, _mm_mul_ps(diff, diff));
344
247
  pq_l2_t += 256;
345
248
  qa += 4;
346
249
  }
347
250
  pq_l1_t += M_2 << mi_nbits;
348
251
  key01 >>= mi_nbits;
349
252
  }
350
- accu = _mm_hadd_ps (accu, accu);
351
- accu = _mm_hadd_ps (accu, accu);
352
- return _mm_cvtss_f32 (accu);
253
+ accu = _mm_hadd_ps(accu, accu);
254
+ accu = _mm_hadd_ps(accu, accu);
255
+ return _mm_cvtss_f32(accu);
353
256
  #else
354
257
  FAISS_THROW_MSG("not implemented for non-x64 platforms");
355
258
  #endif
356
259
  }
357
-
358
260
  };
359
261
 
262
+ } // namespace
360
263
 
361
- } // namespace
362
-
363
-
364
- DistanceComputer * Index2Layer::get_distance_computer() const {
264
+ DistanceComputer* Index2Layer::get_distance_computer() const {
365
265
  #ifdef __SSE3__
366
- const MultiIndexQuantizer *mi =
367
- dynamic_cast<MultiIndexQuantizer*> (q1.quantizer);
266
+ const MultiIndexQuantizer* mi =
267
+ dynamic_cast<MultiIndexQuantizer*>(q1.quantizer);
368
268
 
369
269
  if (mi && pq.M % 2 == 0 && pq.dsub == 4) {
370
270
  return new Distance2xXPQ4(*this);
371
271
  }
372
272
 
373
- const IndexFlat *fl =
374
- dynamic_cast<IndexFlat*> (q1.quantizer);
273
+ const IndexFlat* fl = dynamic_cast<IndexFlat*>(q1.quantizer);
375
274
 
376
275
  if (fl && pq.dsub == 4) {
377
276
  return new DistanceXPQ4(*this);
@@ -381,57 +280,60 @@ DistanceComputer * Index2Layer::get_distance_computer() const {
381
280
  return Index::get_distance_computer();
382
281
  }
383
282
 
384
-
385
283
  /* The standalone codec interface */
386
- size_t Index2Layer::sa_code_size () const
387
- {
388
- return code_size;
389
- }
390
284
 
391
- void Index2Layer::sa_encode (idx_t n, const float *x, uint8_t *bytes) const
392
- {
393
- FAISS_THROW_IF_NOT (is_trained);
394
- std::unique_ptr<int64_t []> list_nos (new int64_t [n]);
395
- q1.quantizer->assign (n, x, list_nos.get());
285
+ void Index2Layer::sa_encode(idx_t n, const float* x, uint8_t* bytes) const {
286
+ FAISS_THROW_IF_NOT(is_trained);
287
+
288
+ idx_t bs = 32768;
289
+ if (n > bs) {
290
+ for (idx_t i0 = 0; i0 < n; i0 += bs) {
291
+ idx_t i1 = std::min(i0 + bs, n);
292
+ if (verbose) {
293
+ printf("Index2Layer::add: adding %" PRId64 ":%" PRId64
294
+ " / %" PRId64 "\n",
295
+ i0,
296
+ i1,
297
+ n);
298
+ }
299
+ sa_encode(i1 - i0, x + i0 * d, bytes + i0 * code_size);
300
+ }
301
+ return;
302
+ }
303
+
304
+ std::unique_ptr<int64_t[]> list_nos(new int64_t[n]);
305
+ q1.quantizer->assign(n, x, list_nos.get());
396
306
  std::vector<float> residuals(n * d);
397
307
  for (idx_t i = 0; i < n; i++) {
398
- q1.quantizer->compute_residual (
399
- x + i * d, residuals.data() + i * d, list_nos[i]);
308
+ q1.quantizer->compute_residual(
309
+ x + i * d, residuals.data() + i * d, list_nos[i]);
400
310
  }
401
- pq.compute_codes (residuals.data(), bytes, n);
311
+ pq.compute_codes(residuals.data(), bytes, n);
402
312
 
403
313
  for (idx_t i = n - 1; i >= 0; i--) {
404
- uint8_t * code = bytes + i * code_size;
405
- memmove (code + code_size_1,
406
- bytes + i * code_size_2, code_size_2);
407
- q1.encode_listno (list_nos[i], code);
314
+ uint8_t* code = bytes + i * code_size;
315
+ memmove(code + code_size_1, bytes + i * code_size_2, code_size_2);
316
+ q1.encode_listno(list_nos[i], code);
408
317
  }
409
-
410
318
  }
411
319
 
412
- void Index2Layer::sa_decode (idx_t n, const uint8_t *bytes, float *x) const
413
- {
414
-
320
+ void Index2Layer::sa_decode(idx_t n, const uint8_t* bytes, float* x) const {
415
321
  #pragma omp parallel
416
322
  {
417
- std::vector<float> residual (d);
323
+ std::vector<float> residual(d);
418
324
 
419
325
  #pragma omp for
420
326
  for (idx_t i = 0; i < n; i++) {
421
- const uint8_t *code = bytes + i * code_size;
422
- int64_t list_no = q1.decode_listno (code);
423
- float *xi = x + i * d;
424
- pq.decode (code + code_size_1, xi);
425
- q1.quantizer->reconstruct (list_no, residual.data());
327
+ const uint8_t* code = bytes + i * code_size;
328
+ int64_t list_no = q1.decode_listno(code);
329
+ float* xi = x + i * d;
330
+ pq.decode(code + code_size_1, xi);
331
+ q1.quantizer->reconstruct(list_no, residual.data());
426
332
  for (int j = 0; j < d; j++) {
427
333
  xi[j] += residual[j];
428
334
  }
429
335
  }
430
336
  }
431
-
432
337
  }
433
338
 
434
-
435
-
436
-
437
339
  } // namespace faiss
@@ -11,75 +11,61 @@
11
11
 
12
12
  #include <vector>
13
13
 
14
- #include <faiss/IndexPQ.h>
14
+ #include <faiss/IndexFlatCodes.h>
15
15
  #include <faiss/IndexIVF.h>
16
+ #include <faiss/IndexPQ.h>
16
17
 
17
18
  namespace faiss {
18
19
 
19
20
  struct IndexIVFPQ;
20
21
 
21
-
22
- /** Same as an IndexIVFPQ without the inverted lists: codes are stored sequentially
22
+ /** Same as an IndexIVFPQ without the inverted lists: codes are stored
23
+ * sequentially
23
24
  *
24
25
  * The class is mainly inteded to store encoded vectors that can be
25
26
  * accessed randomly, the search function is not implemented.
26
27
  */
27
- struct Index2Layer: Index {
28
+ struct Index2Layer : IndexFlatCodes {
28
29
  /// first level quantizer
29
30
  Level1Quantizer q1;
30
31
 
31
32
  /// second level quantizer is always a PQ
32
33
  ProductQuantizer pq;
33
34
 
34
- /// Codes. Size ntotal * code_size.
35
- std::vector<uint8_t> codes;
36
-
37
35
  /// size of the code for the first level (ceil(log8(q1.nlist)))
38
36
  size_t code_size_1;
39
37
 
40
38
  /// size of the code for the second level
41
39
  size_t code_size_2;
42
40
 
43
- /// code_size_1 + code_size_2
44
- size_t code_size;
45
-
46
- Index2Layer (Index * quantizer, size_t nlist,
47
- int M, int nbit = 8,
48
- MetricType metric = METRIC_L2);
41
+ Index2Layer(
42
+ Index* quantizer,
43
+ size_t nlist,
44
+ int M,
45
+ int nbit = 8,
46
+ MetricType metric = METRIC_L2);
49
47
 
50
- Index2Layer ();
51
- ~Index2Layer ();
48
+ Index2Layer();
49
+ ~Index2Layer();
52
50
 
53
51
  void train(idx_t n, const float* x) override;
54
52
 
55
- void add(idx_t n, const float* x) override;
56
-
57
53
  /// not implemented
58
54
  void search(
59
- idx_t n,
60
- const float* x,
61
- idx_t k,
62
- float* distances,
63
- idx_t* labels) const override;
55
+ idx_t n,
56
+ const float* x,
57
+ idx_t k,
58
+ float* distances,
59
+ idx_t* labels) const override;
64
60
 
65
- void reconstruct_n(idx_t i0, idx_t ni, float* recons) const override;
66
-
67
- void reconstruct(idx_t key, float* recons) const override;
68
-
69
- void reset() override;
70
-
71
- DistanceComputer * get_distance_computer() const override;
61
+ DistanceComputer* get_distance_computer() const override;
72
62
 
73
63
  /// transfer the flat codes to an IVFPQ index
74
- void transfer_to_IVFPQ(IndexIVFPQ & other) const;
75
-
64
+ void transfer_to_IVFPQ(IndexIVFPQ& other) const;
76
65
 
77
66
  /* The standalone codec interface */
78
- size_t sa_code_size () const override;
79
- void sa_encode (idx_t n, const float *x, uint8_t *bytes) const override;
80
- void sa_decode (idx_t n, const uint8_t *bytes, float *x) const override;
81
-
67
+ void sa_encode(idx_t n, const float* x, uint8_t* bytes) const override;
68
+ void sa_decode(idx_t n, const uint8_t* bytes, float* x) const override;
82
69
  };
83
70
 
84
-
85
71
  } // namespace faiss