faiss 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/faiss/version.rb +1 -1
  4. data/vendor/faiss/faiss/AutoTune.h +1 -1
  5. data/vendor/faiss/faiss/Clustering.cpp +35 -4
  6. data/vendor/faiss/faiss/Clustering.h +10 -1
  7. data/vendor/faiss/faiss/IVFlib.cpp +4 -1
  8. data/vendor/faiss/faiss/Index.h +21 -6
  9. data/vendor/faiss/faiss/IndexBinaryHNSW.h +1 -1
  10. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +1 -1
  11. data/vendor/faiss/faiss/IndexFastScan.cpp +22 -4
  12. data/vendor/faiss/faiss/IndexFlat.cpp +11 -7
  13. data/vendor/faiss/faiss/IndexFlatCodes.cpp +159 -5
  14. data/vendor/faiss/faiss/IndexFlatCodes.h +20 -3
  15. data/vendor/faiss/faiss/IndexHNSW.cpp +143 -90
  16. data/vendor/faiss/faiss/IndexHNSW.h +52 -3
  17. data/vendor/faiss/faiss/IndexIVF.cpp +3 -3
  18. data/vendor/faiss/faiss/IndexIVF.h +9 -1
  19. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +15 -0
  20. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +3 -0
  21. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +130 -57
  22. data/vendor/faiss/faiss/IndexIVFFastScan.h +14 -7
  23. data/vendor/faiss/faiss/IndexIVFPQ.cpp +1 -3
  24. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +21 -2
  25. data/vendor/faiss/faiss/IndexLattice.cpp +1 -19
  26. data/vendor/faiss/faiss/IndexLattice.h +3 -22
  27. data/vendor/faiss/faiss/IndexNNDescent.cpp +0 -29
  28. data/vendor/faiss/faiss/IndexNNDescent.h +1 -1
  29. data/vendor/faiss/faiss/IndexNSG.h +1 -1
  30. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +56 -0
  31. data/vendor/faiss/faiss/IndexNeuralNetCodec.h +49 -0
  32. data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
  33. data/vendor/faiss/faiss/IndexRefine.cpp +5 -5
  34. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +3 -1
  35. data/vendor/faiss/faiss/MetricType.h +7 -2
  36. data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +95 -17
  37. data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +152 -0
  38. data/vendor/faiss/faiss/cppcontrib/factory_tools.h +24 -0
  39. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +83 -30
  40. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +36 -4
  41. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +6 -0
  42. data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +1 -1
  43. data/vendor/faiss/faiss/gpu/GpuIndex.h +2 -8
  44. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +282 -0
  45. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +6 -0
  46. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +2 -0
  47. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +25 -0
  48. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +26 -21
  49. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +6 -0
  50. data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +8 -5
  51. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +65 -0
  52. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +1 -1
  53. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +6 -0
  54. data/vendor/faiss/faiss/gpu/utils/Timer.cpp +4 -1
  55. data/vendor/faiss/faiss/gpu/utils/Timer.h +1 -1
  56. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +25 -0
  57. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +9 -1
  58. data/vendor/faiss/faiss/impl/DistanceComputer.h +46 -0
  59. data/vendor/faiss/faiss/impl/FaissAssert.h +4 -2
  60. data/vendor/faiss/faiss/impl/HNSW.cpp +358 -190
  61. data/vendor/faiss/faiss/impl/HNSW.h +43 -22
  62. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +8 -8
  63. data/vendor/faiss/faiss/impl/LookupTableScaler.h +34 -0
  64. data/vendor/faiss/faiss/impl/NNDescent.cpp +13 -8
  65. data/vendor/faiss/faiss/impl/NSG.cpp +0 -29
  66. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +1 -0
  67. data/vendor/faiss/faiss/impl/ProductQuantizer.h +5 -1
  68. data/vendor/faiss/faiss/impl/ResultHandler.h +151 -32
  69. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +719 -102
  70. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +3 -0
  71. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +5 -0
  72. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx512.h +248 -0
  73. data/vendor/faiss/faiss/impl/index_read.cpp +29 -15
  74. data/vendor/faiss/faiss/impl/index_read_utils.h +37 -0
  75. data/vendor/faiss/faiss/impl/index_write.cpp +28 -10
  76. data/vendor/faiss/faiss/impl/io.cpp +13 -5
  77. data/vendor/faiss/faiss/impl/io.h +4 -4
  78. data/vendor/faiss/faiss/impl/io_macros.h +6 -0
  79. data/vendor/faiss/faiss/impl/platform_macros.h +22 -0
  80. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +11 -0
  81. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +1 -1
  82. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +448 -1
  83. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +5 -5
  84. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
  85. data/vendor/faiss/faiss/impl/simd_result_handlers.h +143 -59
  86. data/vendor/faiss/faiss/index_factory.cpp +31 -13
  87. data/vendor/faiss/faiss/index_io.h +12 -5
  88. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +28 -8
  89. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +3 -0
  90. data/vendor/faiss/faiss/invlists/DirectMap.cpp +9 -1
  91. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +55 -17
  92. data/vendor/faiss/faiss/invlists/InvertedLists.h +18 -9
  93. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +21 -6
  94. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +2 -1
  95. data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -3
  96. data/vendor/faiss/faiss/utils/Heap.h +105 -0
  97. data/vendor/faiss/faiss/utils/NeuralNet.cpp +342 -0
  98. data/vendor/faiss/faiss/utils/NeuralNet.h +147 -0
  99. data/vendor/faiss/faiss/utils/bf16.h +36 -0
  100. data/vendor/faiss/faiss/utils/distances.cpp +58 -88
  101. data/vendor/faiss/faiss/utils/distances.h +5 -5
  102. data/vendor/faiss/faiss/utils/distances_simd.cpp +997 -9
  103. data/vendor/faiss/faiss/utils/extra_distances-inl.h +70 -0
  104. data/vendor/faiss/faiss/utils/extra_distances.cpp +85 -137
  105. data/vendor/faiss/faiss/utils/extra_distances.h +3 -2
  106. data/vendor/faiss/faiss/utils/hamming.cpp +1 -1
  107. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +4 -1
  108. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +2 -1
  109. data/vendor/faiss/faiss/utils/random.cpp +43 -0
  110. data/vendor/faiss/faiss/utils/random.h +25 -0
  111. data/vendor/faiss/faiss/utils/simdlib.h +10 -1
  112. data/vendor/faiss/faiss/utils/simdlib_avx512.h +296 -0
  113. data/vendor/faiss/faiss/utils/simdlib_neon.h +5 -2
  114. data/vendor/faiss/faiss/utils/simdlib_ppc64.h +1084 -0
  115. data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +176 -0
  116. data/vendor/faiss/faiss/utils/utils.cpp +10 -3
  117. data/vendor/faiss/faiss/utils/utils.h +3 -0
  118. metadata +16 -4
  119. data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +0 -102
@@ -58,35 +58,6 @@ using storage_idx_t = NNDescent::storage_idx_t;
58
58
 
59
59
  namespace {
60
60
 
61
- /* Wrap the distance computer into one that negates the
62
- distances. This makes supporting INNER_PRODUCE search easier */
63
-
64
- struct NegativeDistanceComputer : DistanceComputer {
65
- /// owned by this
66
- DistanceComputer* basedis;
67
-
68
- explicit NegativeDistanceComputer(DistanceComputer* basedis)
69
- : basedis(basedis) {}
70
-
71
- void set_query(const float* x) override {
72
- basedis->set_query(x);
73
- }
74
-
75
- /// compute distance of vector i to current query
76
- float operator()(idx_t i) override {
77
- return -(*basedis)(i);
78
- }
79
-
80
- /// compute distance between two stored vectors
81
- float symmetric_dis(idx_t i, idx_t j) override {
82
- return -basedis->symmetric_dis(i, j);
83
- }
84
-
85
- ~NegativeDistanceComputer() override {
86
- delete basedis;
87
- }
88
- };
89
-
90
61
  DistanceComputer* storage_distance_computer(const Index* storage) {
91
62
  if (is_similarity_metric(storage->metric_type)) {
92
63
  return new NegativeDistanceComputer(storage->get_distance_computer());
@@ -26,7 +26,7 @@ struct IndexNNDescent : Index {
26
26
 
27
27
  /// Faiss results are 64-bit
28
28
 
29
- // the link strcuture
29
+ // the link structure
30
30
  NNDescent nndescent;
31
31
 
32
32
  // the sequential storage
@@ -24,7 +24,7 @@ namespace faiss {
24
24
  * link structure built on top */
25
25
 
26
26
  struct IndexNSG : Index {
27
- /// the link strcuture
27
+ /// the link structure
28
28
  NSG nsg;
29
29
 
30
30
  /// the sequential storage
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #include <faiss/IndexNeuralNetCodec.h>
9
+ #include <faiss/impl/FaissAssert.h>
10
+ #include <faiss/utils/hamming.h>
11
+
12
+ namespace faiss {
13
+
14
+ /*********************************************************
15
+ * IndexNeuralNetCodec implementation
16
+ *********************************************************/
17
+
18
+ IndexNeuralNetCodec::IndexNeuralNetCodec(
19
+ int d,
20
+ int M,
21
+ int nbits,
22
+ MetricType metric)
23
+ : IndexFlatCodes((M * nbits + 7) / 8, d, metric), M(M), nbits(nbits) {
24
+ is_trained = false;
25
+ }
26
+
27
+ void IndexNeuralNetCodec::train(idx_t n, const float* x) {
28
+ FAISS_THROW_MSG("Training not implemented in C++, use Pytorch");
29
+ }
30
+
31
+ void IndexNeuralNetCodec::sa_encode(idx_t n, const float* x, uint8_t* codes)
32
+ const {
33
+ nn::Tensor2D x_tensor(n, d, x);
34
+ nn::Int32Tensor2D codes_tensor = net->encode(x_tensor);
35
+ pack_bitstrings(n, M, nbits, codes_tensor.data(), codes, code_size);
36
+ }
37
+
38
+ void IndexNeuralNetCodec::sa_decode(idx_t n, const uint8_t* codes, float* x)
39
+ const {
40
+ nn::Int32Tensor2D codes_tensor(n, M);
41
+ unpack_bitstrings(n, M, nbits, codes, code_size, codes_tensor.data());
42
+ nn::Tensor2D x_tensor = net->decode(codes_tensor);
43
+ memcpy(x, x_tensor.data(), d * n * sizeof(float));
44
+ }
45
+
46
+ /*********************************************************
47
+ * IndexQINeuralNetCodec implementation
48
+ *********************************************************/
49
+
50
+ IndexQINCo::IndexQINCo(int d, int M, int nbits, int L, int h, MetricType metric)
51
+ : IndexNeuralNetCodec(d, M, nbits, metric),
52
+ qinco(d, 1 << nbits, L, M, h) {
53
+ net = &qinco;
54
+ }
55
+
56
+ } // namespace faiss
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #pragma once
9
+
10
+ #include <vector>
11
+
12
+ #include <faiss/IndexFlatCodes.h>
13
+ #include <faiss/utils/NeuralNet.h>
14
+
15
+ namespace faiss {
16
+
17
+ struct IndexNeuralNetCodec : IndexFlatCodes {
18
+ NeuralNetCodec* net = nullptr;
19
+ size_t M, nbits;
20
+
21
+ explicit IndexNeuralNetCodec(
22
+ int d = 0,
23
+ int M = 0,
24
+ int nbits = 0,
25
+ MetricType metric = METRIC_L2);
26
+
27
+ void train(idx_t n, const float* x) override;
28
+
29
+ void sa_encode(idx_t n, const float* x, uint8_t* codes) const override;
30
+ void sa_decode(idx_t n, const uint8_t* codes, float* x) const override;
31
+
32
+ ~IndexNeuralNetCodec() {}
33
+ };
34
+
35
+ struct IndexQINCo : IndexNeuralNetCodec {
36
+ QINCo qinco;
37
+
38
+ IndexQINCo(
39
+ int d,
40
+ int M,
41
+ int nbits,
42
+ int L,
43
+ int h,
44
+ MetricType metric = METRIC_L2);
45
+
46
+ ~IndexQINCo() {}
47
+ };
48
+
49
+ } // namespace faiss
@@ -23,7 +23,7 @@ struct SearchParametersPreTransform : SearchParameters {
23
23
  /** Index that applies a LinearTransform transform on vectors before
24
24
  * handing them over to a sub-index */
25
25
  struct IndexPreTransform : Index {
26
- std::vector<VectorTransform*> chain; ///! chain of tranforms
26
+ std::vector<VectorTransform*> chain; ///! chain of transforms
27
27
  Index* index; ///! the sub-index
28
28
 
29
29
  bool own_fields; ///! whether pointers are deleted in destructor
@@ -68,12 +68,12 @@ template <class C>
68
68
  static void reorder_2_heaps(
69
69
  idx_t n,
70
70
  idx_t k,
71
- idx_t* labels,
72
- float* distances,
71
+ idx_t* __restrict labels,
72
+ float* __restrict distances,
73
73
  idx_t k_base,
74
- const idx_t* base_labels,
75
- const float* base_distances) {
76
- #pragma omp parallel for
74
+ const idx_t* __restrict base_labels,
75
+ const float* __restrict base_distances) {
76
+ #pragma omp parallel for if (n > 1)
77
77
  for (idx_t i = 0; i < n; i++) {
78
78
  idx_t* idxo = labels + i * k;
79
79
  float* diso = distances + i * k;
@@ -32,7 +32,9 @@ IndexScalarQuantizer::IndexScalarQuantizer(
32
32
  MetricType metric)
33
33
  : IndexFlatCodes(0, d, metric), sq(d, qtype) {
34
34
  is_trained = qtype == ScalarQuantizer::QT_fp16 ||
35
- qtype == ScalarQuantizer::QT_8bit_direct;
35
+ qtype == ScalarQuantizer::QT_8bit_direct ||
36
+ qtype == ScalarQuantizer::QT_bf16 ||
37
+ qtype == ScalarQuantizer::QT_8bit_direct_signed;
36
38
  code_size = sq.code_size;
37
39
  }
38
40
 
@@ -31,8 +31,13 @@ enum MetricType {
31
31
  METRIC_Canberra = 20,
32
32
  METRIC_BrayCurtis,
33
33
  METRIC_JensenShannon,
34
- METRIC_Jaccard, ///< defined as: sum_i(min(a_i, b_i)) / sum_i(max(a_i, b_i))
35
- ///< where a_i, b_i > 0
34
+
35
+ /// sum_i(min(a_i, b_i)) / sum_i(max(a_i, b_i)) where a_i, b_i > 0
36
+ METRIC_Jaccard,
37
+ /// Squared Eucliden distance, ignoring NaNs
38
+ METRIC_NaNEuclidean,
39
+ /// abs(x | y): the distance to a hyperplane
40
+ METRIC_ABS_INNER_PRODUCT,
36
41
  };
37
42
 
38
43
  /// all vector indices are this type
@@ -7,6 +7,7 @@
7
7
 
8
8
  #pragma once
9
9
 
10
+ #include <faiss/impl/platform_macros.h>
10
11
  #include <cstdint>
11
12
 
12
13
  namespace faiss {
@@ -31,7 +32,11 @@ struct Uint8Reader {
31
32
  if (N_ELEMENTS > CPOS + 3) {
32
33
  const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
33
34
  codes + ELEMENT_TO_READ * 4);
35
+ #ifdef FAISS_BIG_ENDIAN
36
+ return (code32) >> 24;
37
+ #else
34
38
  return (code32 & 0x000000FF);
39
+ #endif
35
40
  } else {
36
41
  return codes[CPOS];
37
42
  }
@@ -40,7 +45,11 @@ struct Uint8Reader {
40
45
  if (N_ELEMENTS > CPOS + 2) {
41
46
  const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
42
47
  codes + ELEMENT_TO_READ * 4);
48
+ #ifdef FAISS_BIG_ENDIAN
49
+ return (code32 & 0x00FF0000) >> 16;
50
+ #else
43
51
  return (code32 & 0x0000FF00) >> 8;
52
+ #endif
44
53
  } else {
45
54
  return codes[CPOS];
46
55
  }
@@ -49,7 +58,11 @@ struct Uint8Reader {
49
58
  if (N_ELEMENTS > CPOS + 1) {
50
59
  const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
51
60
  codes + ELEMENT_TO_READ * 4);
61
+ #ifdef FAISS_BIG_ENDIAN
62
+ return (code32 & 0x0000FF00) >> 8;
63
+ #else
52
64
  return (code32 & 0x00FF0000) >> 16;
65
+ #endif
53
66
  } else {
54
67
  return codes[CPOS];
55
68
  }
@@ -58,7 +71,11 @@ struct Uint8Reader {
58
71
  if (N_ELEMENTS > CPOS) {
59
72
  const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
60
73
  codes + ELEMENT_TO_READ * 4);
74
+ #ifdef FAISS_BIG_ENDIAN
75
+ return (code32 & 0x000000FF);
76
+ #else
61
77
  return (code32) >> 24;
78
+ #endif
62
79
  } else {
63
80
  return codes[CPOS];
64
81
  }
@@ -87,40 +104,61 @@ struct Uint10Reader {
87
104
  switch (SUB_ELEMENT) {
88
105
  case 0: {
89
106
  if (N_ELEMENTS > CPOS + 2) {
90
- const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
107
+ uint32_t code32 = *reinterpret_cast<const uint32_t*>(
91
108
  codes + ELEMENT_TO_READ * 5);
109
+ #ifdef FAISS_BIG_ENDIAN
110
+ code32 = Swap4Bytes(code32);
111
+ #endif
92
112
  return (code32 & 0b0000001111111111);
93
113
  } else {
94
- const uint16_t code16 = *reinterpret_cast<const uint16_t*>(
114
+ uint16_t code16 = *reinterpret_cast<const uint16_t*>(
95
115
  codes + ELEMENT_TO_READ * 5 + 0);
116
+ #ifdef FAISS_BIG_ENDIAN
117
+ code16 = Swap2Bytes(code16);
118
+ #endif
96
119
  return (code16 & 0b0000001111111111);
97
120
  }
98
121
  }
99
122
  case 1: {
100
123
  if (N_ELEMENTS > CPOS + 1) {
101
- const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
124
+ uint32_t code32 = *reinterpret_cast<const uint32_t*>(
102
125
  codes + ELEMENT_TO_READ * 5);
126
+ #ifdef FAISS_BIG_ENDIAN
127
+ code32 = Swap4Bytes(code32);
128
+ #endif
103
129
  return (code32 & 0b000011111111110000000000) >> 10;
104
130
  } else {
105
- const uint16_t code16 = *reinterpret_cast<const uint16_t*>(
131
+ uint16_t code16 = *reinterpret_cast<const uint16_t*>(
106
132
  codes + ELEMENT_TO_READ * 5 + 1);
133
+ #ifdef FAISS_BIG_ENDIAN
134
+ code16 = Swap2Bytes(code16);
135
+ #endif
107
136
  return (code16 & 0b0000111111111100) >> 2;
108
137
  }
109
138
  }
110
139
  case 2: {
111
140
  if (N_ELEMENTS > CPOS) {
112
- const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
141
+ uint32_t code32 = *reinterpret_cast<const uint32_t*>(
113
142
  codes + ELEMENT_TO_READ * 5);
143
+ #ifdef FAISS_BIG_ENDIAN
144
+ code32 = Swap4Bytes(code32);
145
+ #endif
114
146
  return (code32 & 0b00111111111100000000000000000000) >> 20;
115
147
  } else {
116
- const uint16_t code16 = *reinterpret_cast<const uint16_t*>(
148
+ uint16_t code16 = *reinterpret_cast<const uint16_t*>(
117
149
  codes + ELEMENT_TO_READ * 5 + 2);
150
+ #ifdef FAISS_BIG_ENDIAN
151
+ code16 = Swap2Bytes(code16);
152
+ #endif
118
153
  return (code16 & 0b0011111111110000) >> 4;
119
154
  }
120
155
  }
121
156
  case 3: {
122
- const uint16_t code16 = *reinterpret_cast<const uint16_t*>(
157
+ uint16_t code16 = *reinterpret_cast<const uint16_t*>(
123
158
  codes + ELEMENT_TO_READ * 5 + 3);
159
+ #ifdef FAISS_BIG_ENDIAN
160
+ code16 = Swap2Bytes(code16);
161
+ #endif
124
162
  return (code16 & 0b1111111111000000) >> 6;
125
163
  }
126
164
  }
@@ -147,45 +185,69 @@ struct Uint12Reader {
147
185
  switch (SUB_ELEMENT) {
148
186
  case 0: {
149
187
  if (N_ELEMENTS > CPOS + 2) {
150
- const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
188
+ uint32_t code32 = *reinterpret_cast<const uint32_t*>(
151
189
  codes + ELEMENT_TO_READ * 6);
190
+ #ifdef FAISS_BIG_ENDIAN
191
+ code32 = Swap4Bytes(code32);
192
+ #endif
152
193
  return (code32 & 0b0000111111111111);
153
194
  } else {
154
- const uint16_t code16 = *reinterpret_cast<const uint16_t*>(
195
+ uint16_t code16 = *reinterpret_cast<const uint16_t*>(
155
196
  codes + ELEMENT_TO_READ * 6 + 0);
197
+ #ifdef FAISS_BIG_ENDIAN
198
+ code16 = Swap2Bytes(code16);
199
+ #endif
156
200
  return (code16 & 0b0000111111111111);
157
201
  }
158
202
  }
159
203
  case 1: {
160
204
  if (N_ELEMENTS > CPOS + 1) {
161
- const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
205
+ uint32_t code32 = *reinterpret_cast<const uint32_t*>(
162
206
  codes + ELEMENT_TO_READ * 6);
207
+ #ifdef FAISS_BIG_ENDIAN
208
+ code32 = Swap4Bytes(code32);
209
+ #endif
163
210
  return (code32 & 0b111111111111000000000000) >> 12;
164
211
  } else {
165
- const uint16_t code16 = *reinterpret_cast<const uint16_t*>(
212
+ uint16_t code16 = *reinterpret_cast<const uint16_t*>(
166
213
  codes + ELEMENT_TO_READ * 6 + 1);
214
+ #ifdef FAISS_BIG_ENDIAN
215
+ code16 = Swap2Bytes(code16);
216
+ #endif
167
217
  return (code16 & 0b1111111111110000) >> 4;
168
218
  }
169
219
  }
170
220
  case 2: {
171
221
  if (N_ELEMENTS > CPOS + 1) {
172
- const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
222
+ uint32_t code32 = *reinterpret_cast<const uint32_t*>(
173
223
  codes + ELEMENT_TO_READ * 6 + 2);
224
+ #ifdef FAISS_BIG_ENDIAN
225
+ code32 = Swap4Bytes(code32);
226
+ #endif
174
227
  return (code32 & 0b000011111111111100000000) >> 8;
175
228
  } else {
176
- const uint16_t code16 = *reinterpret_cast<const uint16_t*>(
229
+ uint16_t code16 = *reinterpret_cast<const uint16_t*>(
177
230
  codes + ELEMENT_TO_READ * 6 + 3);
231
+ #ifdef FAISS_BIG_ENDIAN
232
+ code16 = Swap2Bytes(code16);
233
+ #endif
178
234
  return (code16 & 0b0000111111111111);
179
235
  }
180
236
  }
181
237
  case 3: {
182
238
  if (N_ELEMENTS > CPOS) {
183
- const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
239
+ uint32_t code32 = *reinterpret_cast<const uint32_t*>(
184
240
  codes + ELEMENT_TO_READ * 6 + 2);
241
+ #ifdef FAISS_BIG_ENDIAN
242
+ code32 = Swap4Bytes(code32);
243
+ #endif
185
244
  return (code32 & 0b11111111111100000000000000000000) >> 20;
186
245
  } else {
187
- const uint16_t code16 = *reinterpret_cast<const uint16_t*>(
246
+ uint16_t code16 = *reinterpret_cast<const uint16_t*>(
188
247
  codes + ELEMENT_TO_READ * 6 + 4);
248
+ #ifdef FAISS_BIG_ENDIAN
249
+ code16 = Swap2Bytes(code16);
250
+ #endif
189
251
  return (code16 & 0b1111111111110000) >> 4;
190
252
  }
191
253
  }
@@ -208,23 +270,39 @@ struct Uint16Reader {
208
270
  switch (SUB_ELEMENT) {
209
271
  case 0: {
210
272
  if (N_ELEMENTS > CPOS + 1) {
211
- const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
273
+ uint32_t code32 = *reinterpret_cast<const uint32_t*>(
212
274
  codes + ELEMENT_TO_READ * 4);
275
+ #ifdef FAISS_BIG_ENDIAN
276
+ code32 = Swap4Bytes(code32);
277
+ #endif
213
278
  return (code32 & 0x0000FFFF);
214
279
  } else {
215
280
  const uint16_t* const __restrict codesFp16 =
216
281
  reinterpret_cast<const uint16_t*>(codes);
282
+ #ifdef FAISS_BIG_ENDIAN
283
+ uint16_t rt = codesFp16[CPOS];
284
+ rt = Swap2Bytes(rt);
285
+ return rt;
286
+ #endif
217
287
  return codesFp16[CPOS];
218
288
  }
219
289
  }
220
290
  case 1: {
221
291
  if (N_ELEMENTS > CPOS) {
222
- const uint32_t code32 = *reinterpret_cast<const uint32_t*>(
292
+ uint32_t code32 = *reinterpret_cast<const uint32_t*>(
223
293
  codes + ELEMENT_TO_READ * 4);
294
+ #ifdef FAISS_BIG_ENDIAN
295
+ code32 = Swap4Bytes(code32);
296
+ #endif
224
297
  return code32 >> 16;
225
298
  } else {
226
299
  const uint16_t* const __restrict codesFp16 =
227
300
  reinterpret_cast<const uint16_t*>(codes);
301
+ #ifdef FAISS_BIG_ENDIAN
302
+ uint16_t rt = codesFp16[CPOS];
303
+ rt = Swap2Bytes(rt);
304
+ return rt;
305
+ #endif
228
306
  return codesFp16[CPOS];
229
307
  }
230
308
  }
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ // -*- c++ -*-
9
+
10
+ #include <faiss/cppcontrib/factory_tools.h>
11
+ #include <map>
12
+
13
+ namespace faiss {
14
+
15
+ namespace {
16
+
17
+ const std::map<faiss::ScalarQuantizer::QuantizerType, std::string> sq_types = {
18
+ {faiss::ScalarQuantizer::QT_8bit, "SQ8"},
19
+ {faiss::ScalarQuantizer::QT_4bit, "SQ4"},
20
+ {faiss::ScalarQuantizer::QT_6bit, "SQ6"},
21
+ {faiss::ScalarQuantizer::QT_fp16, "SQfp16"},
22
+ {faiss::ScalarQuantizer::QT_bf16, "SQbf16"},
23
+ {faiss::ScalarQuantizer::QT_8bit_direct_signed, "SQ8_direct_signed"},
24
+ {faiss::ScalarQuantizer::QT_8bit_direct, "SQ8_direct"},
25
+ };
26
+
27
+ int get_hnsw_M(const faiss::IndexHNSW* index) {
28
+ if (index->hnsw.cum_nneighbor_per_level.size() >= 1) {
29
+ return index->hnsw.cum_nneighbor_per_level[1] / 2;
30
+ }
31
+ // Avoid runtime error, just return 0.
32
+ return 0;
33
+ }
34
+
35
+ } // namespace
36
+
37
+ // Reference for reverse_index_factory:
38
+ // https://github.com/facebookresearch/faiss/blob/838612c9d7f2f619811434ec9209c020f44107cb/contrib/factory_tools.py#L81
39
+ std::string reverse_index_factory(const faiss::Index* index) {
40
+ std::string prefix;
41
+ if (dynamic_cast<const faiss::IndexFlat*>(index)) {
42
+ return "Flat";
43
+ } else if (
44
+ const faiss::IndexIVF* ivf_index =
45
+ dynamic_cast<const faiss::IndexIVF*>(index)) {
46
+ const faiss::Index* quantizer = ivf_index->quantizer;
47
+
48
+ if (dynamic_cast<const faiss::IndexFlat*>(quantizer)) {
49
+ prefix = "IVF" + std::to_string(ivf_index->nlist);
50
+ } else if (
51
+ const faiss::MultiIndexQuantizer* miq =
52
+ dynamic_cast<const faiss::MultiIndexQuantizer*>(
53
+ quantizer)) {
54
+ prefix = "IMI" + std::to_string(miq->pq.M) + "x" +
55
+ std::to_string(miq->pq.nbits);
56
+ } else if (
57
+ const faiss::IndexHNSW* hnsw_index =
58
+ dynamic_cast<const faiss::IndexHNSW*>(quantizer)) {
59
+ prefix = "IVF" + std::to_string(ivf_index->nlist) + "_HNSW" +
60
+ std::to_string(get_hnsw_M(hnsw_index));
61
+ } else {
62
+ prefix = "IVF" + std::to_string(ivf_index->nlist) + "(" +
63
+ reverse_index_factory(quantizer) + ")";
64
+ }
65
+
66
+ if (dynamic_cast<const faiss::IndexIVFFlat*>(ivf_index)) {
67
+ return prefix + ",Flat";
68
+ } else if (
69
+ auto sq_index =
70
+ dynamic_cast<const faiss::IndexIVFScalarQuantizer*>(
71
+ ivf_index)) {
72
+ return prefix + "," + sq_types.at(sq_index->sq.qtype);
73
+ } else if (
74
+ const faiss::IndexIVFPQ* ivfpq_index =
75
+ dynamic_cast<const faiss::IndexIVFPQ*>(ivf_index)) {
76
+ return prefix + ",PQ" + std::to_string(ivfpq_index->pq.M) + "x" +
77
+ std::to_string(ivfpq_index->pq.nbits);
78
+ } else if (
79
+ const faiss::IndexIVFPQFastScan* ivfpqfs_index =
80
+ dynamic_cast<const faiss::IndexIVFPQFastScan*>(
81
+ ivf_index)) {
82
+ return prefix + ",PQ" + std::to_string(ivfpqfs_index->pq.M) + "x" +
83
+ std::to_string(ivfpqfs_index->pq.nbits) + "fs";
84
+ }
85
+ } else if (
86
+ const faiss::IndexPreTransform* pretransform_index =
87
+ dynamic_cast<const faiss::IndexPreTransform*>(index)) {
88
+ if (pretransform_index->chain.size() != 1) {
89
+ // Avoid runtime error, just return empty string for logging.
90
+ return "";
91
+ }
92
+ const faiss::VectorTransform* vt = pretransform_index->chain.at(0);
93
+ if (const faiss::OPQMatrix* opq_matrix =
94
+ dynamic_cast<const faiss::OPQMatrix*>(vt)) {
95
+ prefix = "OPQ" + std::to_string(opq_matrix->M) + "_" +
96
+ std::to_string(opq_matrix->d_out);
97
+ } else if (
98
+ const faiss::ITQTransform* itq_transform =
99
+ dynamic_cast<const faiss::ITQTransform*>(vt)) {
100
+ prefix = "ITQ" + std::to_string(itq_transform->itq.d_out);
101
+ } else if (
102
+ const faiss::PCAMatrix* pca_matrix =
103
+ dynamic_cast<const faiss::PCAMatrix*>(vt)) {
104
+ assert(pca_matrix->eigen_power == 0);
105
+ prefix = "PCA" +
106
+ std::string(pca_matrix->random_rotation ? "R" : "") +
107
+ std::to_string(pca_matrix->d_out);
108
+ } else {
109
+ // Avoid runtime error, just return empty string for logging.
110
+ return "";
111
+ }
112
+ return prefix + "," + reverse_index_factory(pretransform_index->index);
113
+ } else if (
114
+ const faiss::IndexHNSW* hnsw_index =
115
+ dynamic_cast<const faiss::IndexHNSW*>(index)) {
116
+ return "HNSW" + std::to_string(get_hnsw_M(hnsw_index));
117
+ } else if (
118
+ const faiss::IndexRefine* refine_index =
119
+ dynamic_cast<const faiss::IndexRefine*>(index)) {
120
+ return reverse_index_factory(refine_index->base_index) + ",Refine(" +
121
+ reverse_index_factory(refine_index->refine_index) + ")";
122
+ } else if (
123
+ const faiss::IndexPQFastScan* pqfs_index =
124
+ dynamic_cast<const faiss::IndexPQFastScan*>(index)) {
125
+ return std::string("PQ") + std::to_string(pqfs_index->pq.M) + "x" +
126
+ std::to_string(pqfs_index->pq.nbits) + "fs";
127
+ } else if (
128
+ const faiss::IndexPQ* pq_index =
129
+ dynamic_cast<const faiss::IndexPQ*>(index)) {
130
+ return std::string("PQ") + std::to_string(pq_index->pq.M) + "x" +
131
+ std::to_string(pq_index->pq.nbits);
132
+ } else if (
133
+ const faiss::IndexLSH* lsh_index =
134
+ dynamic_cast<const faiss::IndexLSH*>(index)) {
135
+ std::string result = "LSH";
136
+ if (lsh_index->rotate_data) {
137
+ result += "r";
138
+ }
139
+ if (lsh_index->train_thresholds) {
140
+ result += "t";
141
+ }
142
+ return result;
143
+ } else if (
144
+ const faiss::IndexScalarQuantizer* sq_index =
145
+ dynamic_cast<const faiss::IndexScalarQuantizer*>(index)) {
146
+ return std::string("SQ") + sq_types.at(sq_index->sq.qtype);
147
+ }
148
+ // Avoid runtime error, just return empty string for logging.
149
+ return "";
150
+ }
151
+
152
+ } // namespace faiss
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ // -*- c++ -*-
9
+
10
+ #pragma once
11
+
12
+ #include <faiss/IndexHNSW.h>
13
+ #include <faiss/IndexIVFFlat.h>
14
+ #include <faiss/IndexIVFPQFastScan.h>
15
+ #include <faiss/IndexLSH.h>
16
+ #include <faiss/IndexPQFastScan.h>
17
+ #include <faiss/IndexPreTransform.h>
18
+ #include <faiss/IndexRefine.h>
19
+
20
+ namespace faiss {
21
+
22
+ std::string reverse_index_factory(const faiss::Index* index);
23
+
24
+ } // namespace faiss