faiss 0.3.1 → 0.3.2

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