faiss 0.2.0 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
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