faiss 0.6.1 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +3 -1
- data/vendor/faiss/faiss/Clustering.cpp +9 -1
- data/vendor/faiss/faiss/IVFlib.cpp +14 -3
- data/vendor/faiss/faiss/Index.h +2 -2
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +9 -10
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +2 -3
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +1 -2
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +10 -12
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +5 -7
- data/vendor/faiss/faiss/IndexEDEN.cpp +273 -0
- data/vendor/faiss/faiss/IndexEDEN.h +57 -0
- data/vendor/faiss/faiss/IndexFastScan.cpp +15 -4
- data/vendor/faiss/faiss/IndexFlat.cpp +13 -50
- data/vendor/faiss/faiss/IndexHNSW.cpp +177 -148
- data/vendor/faiss/faiss/IndexIDMap.cpp +16 -3
- data/vendor/faiss/faiss/IndexIDMap.h +2 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +19 -8
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +3 -3
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +3 -4
- data/vendor/faiss/faiss/IndexIVFEDEN.cpp +302 -0
- data/vendor/faiss/faiss/IndexIVFEDEN.h +70 -0
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +5 -6
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +6 -5
- data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +3 -3
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +42 -25
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +2 -3
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +23 -62
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +180 -76
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -4
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +8 -6
- data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
- data/vendor/faiss/faiss/IndexLattice.cpp +5 -0
- data/vendor/faiss/faiss/IndexNNDescent.cpp +10 -3
- data/vendor/faiss/faiss/IndexNSG.cpp +8 -4
- data/vendor/faiss/faiss/IndexPQ.cpp +6 -8
- data/vendor/faiss/faiss/IndexPreTransform.cpp +15 -0
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +2 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +1 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +5 -1
- data/vendor/faiss/faiss/IndexRefine.cpp +30 -1
- data/vendor/faiss/faiss/IndexReplicas.cpp +1 -2
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +68 -6
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +10 -0
- data/vendor/faiss/faiss/IndexShards.cpp +2 -2
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +2 -2
- data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
- data/vendor/faiss/faiss/SuperKMeans.cpp +256 -240
- data/vendor/faiss/faiss/SuperKMeans.h +30 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +33 -2
- data/vendor/faiss/faiss/clone_index.cpp +5 -0
- data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +1 -1
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +902 -12
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +702 -10
- data/vendor/faiss/faiss/factory_tools.cpp +51 -4
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
- data/vendor/faiss/faiss/gpu/GpuIndex.h +34 -11
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +47 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +17 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +16 -0
- data/vendor/faiss/faiss/gpu/GpuResources.h +3 -2
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +11 -12
- data/vendor/faiss/faiss/gpu/StandardGpuResources.h +3 -3
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
- data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -2
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +180 -0
- data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +87 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +7 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +177 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -0
- data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +48 -3
- data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +45 -0
- data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFFlat.h +193 -0
- data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h +134 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +2 -2
- data/vendor/faiss/faiss/impl/DistanceComputer.h +34 -0
- data/vendor/faiss/faiss/impl/EDENQuantizer.h +119 -0
- data/vendor/faiss/faiss/impl/HNSW.cpp +658 -344
- data/vendor/faiss/faiss/impl/HNSW.h +51 -13
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/impl/NSG.cpp +18 -12
- data/vendor/faiss/faiss/impl/Panorama.h +20 -7
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +59 -24
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +45 -37
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +175 -68
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +19 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +2 -11
- data/vendor/faiss/faiss/impl/ResultHandler.h +26 -31
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +522 -58
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +70 -0
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
- data/vendor/faiss/faiss/impl/VisitedTable.cpp +33 -13
- data/vendor/faiss/faiss/impl/VisitedTable.h +88 -33
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +1 -1
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +38 -3
- data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
- data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +35 -43
- data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +64 -15
- data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +86 -40
- data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +81 -50
- data/vendor/faiss/faiss/impl/index_read.cpp +476 -75
- data/vendor/faiss/faiss/impl/index_write.cpp +56 -4
- data/vendor/faiss/faiss/impl/io_macros.h +25 -0
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
- data/vendor/faiss/faiss/impl/platform_macros.h +15 -9
- data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +284 -0
- data/vendor/faiss/faiss/impl/polysemous_training/dispatch.h +115 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +0 -1
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +26 -15
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +6 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +2 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +2 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +20 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +36 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +5 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +105 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +2 -0
- data/vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp +195 -0
- data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +133 -0
- data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +281 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +72 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +228 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +882 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +6 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +336 -26
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +331 -32
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +553 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +558 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +284 -45
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +502 -3
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +157 -32
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +26 -0
- data/vendor/faiss/faiss/impl/simd_dispatch.h +86 -8
- data/vendor/faiss/faiss/index_factory.cpp +37 -7
- data/vendor/faiss/faiss/index_io.h +16 -0
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +5 -2
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +15 -15
- data/vendor/faiss/faiss/invlists/InvertedLists.h +2 -2
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +19 -4
- data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +60 -0
- data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +26 -1
- data/vendor/faiss/faiss/svs/IndexSVSFlat.h +13 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +150 -23
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +30 -7
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +3 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +65 -25
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +3 -2
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
- data/vendor/faiss/faiss/utils/bf16.h +34 -0
- data/vendor/faiss/faiss/utils/distances.cpp +14 -2
- data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -4
- data/vendor/faiss/faiss/utils/extra_distances.cpp +4 -14
- data/vendor/faiss/faiss/utils/extra_distances.h +1 -2
- data/vendor/faiss/faiss/utils/hamming.cpp +9 -9
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +2 -1
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +15 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +6 -30
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_spr.h +171 -0
- data/vendor/faiss/faiss/utils/partitioning.cpp +0 -2
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +29 -8
- data/vendor/faiss/faiss/utils/rabitq_simd.h +202 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +0 -1
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +263 -15
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +160 -18
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_simdlib256.h +14 -68
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +273 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_spr.cpp +435 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +11 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +143 -6
- data/vendor/faiss/faiss/utils/simd_levels.cpp +56 -2
- data/vendor/faiss/faiss/utils/simd_levels.h +14 -0
- data/vendor/faiss/faiss/utils/utils.cpp +9 -27
- metadata +27 -2
|
@@ -77,6 +77,12 @@ struct DCTemplate<Quantizer, Similarity, SIMDLevel::NONE> : SQDistanceComputer {
|
|
|
77
77
|
template <class Similarity, SIMDLevel SL>
|
|
78
78
|
struct DistanceComputerByte : SQDistanceComputer {};
|
|
79
79
|
|
|
80
|
+
// Byte-domain distance computer for QT_8bit_direct_signed (storage is
|
|
81
|
+
// value+128). Only specialized for AVX512_SPR; other levels fall back to
|
|
82
|
+
// the float-domain DCTemplate path via the dispatch logic.
|
|
83
|
+
template <class Similarity, SIMDLevel SL>
|
|
84
|
+
struct DistanceComputerByteSigned : SQDistanceComputer {};
|
|
85
|
+
|
|
80
86
|
template <class Similarity>
|
|
81
87
|
struct DistanceComputerByte<Similarity, SIMDLevel::NONE> : SQDistanceComputer {
|
|
82
88
|
using Sim = Similarity;
|
|
@@ -7,14 +7,44 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
+
#include <cmath>
|
|
11
|
+
|
|
12
|
+
// Hack for MSVC
|
|
13
|
+
#ifndef M_PI
|
|
14
|
+
#define M_PI 3.14159265358979323846
|
|
15
|
+
#endif
|
|
16
|
+
|
|
10
17
|
#include <algorithm>
|
|
18
|
+
#include <cstring>
|
|
11
19
|
|
|
12
20
|
#include <faiss/impl/FaissAssert.h>
|
|
21
|
+
#include <faiss/impl/RaBitQUtils.h>
|
|
13
22
|
#include <faiss/impl/ScalarQuantizer.h>
|
|
23
|
+
#include <faiss/impl/platform_macros.h>
|
|
14
24
|
#include <faiss/impl/simdlib/simdlib_dispatch.h>
|
|
15
25
|
#include <faiss/utils/bf16.h>
|
|
26
|
+
#include <faiss/utils/distances.h>
|
|
16
27
|
#include <faiss/utils/fp16.h>
|
|
28
|
+
#include <faiss/utils/random.h>
|
|
17
29
|
#include <faiss/utils/simd_levels.h>
|
|
30
|
+
#include <faiss/utils/utils.h>
|
|
31
|
+
|
|
32
|
+
extern "C" {
|
|
33
|
+
int sgemm_(
|
|
34
|
+
const char* transa,
|
|
35
|
+
const char* transb,
|
|
36
|
+
int* m,
|
|
37
|
+
int* n,
|
|
38
|
+
int* k,
|
|
39
|
+
const float* alpha,
|
|
40
|
+
const float* a,
|
|
41
|
+
int* lda,
|
|
42
|
+
const float* b,
|
|
43
|
+
int* ldb,
|
|
44
|
+
float* beta,
|
|
45
|
+
float* c,
|
|
46
|
+
int* ldc);
|
|
47
|
+
}
|
|
18
48
|
|
|
19
49
|
namespace faiss {
|
|
20
50
|
|
|
@@ -117,14 +147,13 @@ struct QuantizerTemplate<
|
|
|
117
147
|
};
|
|
118
148
|
|
|
119
149
|
/*******************************************************************
|
|
120
|
-
*
|
|
150
|
+
* Lloyd-Max scalar quantizer
|
|
121
151
|
*******************************************************************/
|
|
122
152
|
template <int NBits, SIMDLevel SL>
|
|
123
|
-
struct
|
|
153
|
+
struct QuantizerLloydMax;
|
|
124
154
|
|
|
125
155
|
template <int NBits>
|
|
126
|
-
struct
|
|
127
|
-
: ScalarQuantizer::SQuantizer {
|
|
156
|
+
struct QuantizerLloydMax<NBits, SIMDLevel::NONE> : ScalarQuantizer::SQuantizer {
|
|
128
157
|
static_assert(NBits >= 1 && NBits <= 8);
|
|
129
158
|
|
|
130
159
|
static constexpr size_t kCentroidsCount = size_t(1) << NBits;
|
|
@@ -135,22 +164,21 @@ struct QuantizerTurboQuantMSE<NBits, SIMDLevel::NONE>
|
|
|
135
164
|
const float* centroids;
|
|
136
165
|
const float* boundaries;
|
|
137
166
|
|
|
138
|
-
|
|
167
|
+
QuantizerLloydMax(size_t d_in, const std::vector<float>& trained)
|
|
139
168
|
: d(d_in), centroids(nullptr), boundaries(nullptr) {
|
|
140
169
|
FAISS_THROW_IF_NOT(trained.size() == 2 * kCentroidsCount - 1);
|
|
141
170
|
centroids = trained.data();
|
|
142
171
|
boundaries = trained.data() + kCentroidsCount;
|
|
143
172
|
}
|
|
144
173
|
|
|
145
|
-
|
|
174
|
+
uint8_t select_index(float x) const {
|
|
146
175
|
return static_cast<uint8_t>(
|
|
147
176
|
std::upper_bound(
|
|
148
177
|
boundaries, boundaries + (kCentroidsCount - 1), x) -
|
|
149
178
|
boundaries);
|
|
150
179
|
}
|
|
151
180
|
|
|
152
|
-
|
|
153
|
-
const {
|
|
181
|
+
void encode_index(uint8_t idx, uint8_t* code, size_t i) const {
|
|
154
182
|
const size_t bit_offset = i * NBits;
|
|
155
183
|
const size_t byte_offset = bit_offset >> 3;
|
|
156
184
|
const size_t bit_shift = bit_offset & 7;
|
|
@@ -162,8 +190,7 @@ struct QuantizerTurboQuantMSE<NBits, SIMDLevel::NONE>
|
|
|
162
190
|
}
|
|
163
191
|
}
|
|
164
192
|
|
|
165
|
-
|
|
166
|
-
decode_index(const uint8_t* code, size_t i) const {
|
|
193
|
+
uint8_t decode_index(const uint8_t* code, size_t i) const {
|
|
167
194
|
const size_t bit_offset = i * NBits;
|
|
168
195
|
const size_t byte_offset = bit_offset >> 3;
|
|
169
196
|
const size_t bit_shift = bit_offset & 7;
|
|
@@ -175,31 +202,31 @@ struct QuantizerTurboQuantMSE<NBits, SIMDLevel::NONE>
|
|
|
175
202
|
return static_cast<uint8_t>((packed >> bit_shift) & kIndexMask);
|
|
176
203
|
}
|
|
177
204
|
|
|
178
|
-
void encode_vector(const float* x, uint8_t* code) const
|
|
205
|
+
void encode_vector(const float* x, uint8_t* code) const override {
|
|
179
206
|
for (size_t i = 0; i < d; i++) {
|
|
180
207
|
encode_index(select_index(x[i]), code, i);
|
|
181
208
|
}
|
|
182
209
|
}
|
|
183
210
|
|
|
184
|
-
void decode_vector(const uint8_t* code, float* x) const
|
|
211
|
+
void decode_vector(const uint8_t* code, float* x) const override {
|
|
185
212
|
for (size_t i = 0; i < d; i++) {
|
|
186
213
|
x[i] = centroids[decode_index(code, i)];
|
|
187
214
|
}
|
|
188
215
|
}
|
|
189
216
|
|
|
190
|
-
|
|
191
|
-
const uint8_t* code,
|
|
192
|
-
size_t i) const {
|
|
217
|
+
float reconstruct_component(const uint8_t* code, size_t i) const {
|
|
193
218
|
return centroids[decode_index(code, i)];
|
|
194
219
|
}
|
|
195
220
|
};
|
|
196
221
|
|
|
197
222
|
template <int NBits, SIMDLevel SL>
|
|
198
|
-
struct
|
|
199
|
-
using
|
|
200
|
-
QuantizerTurboQuantMSE;
|
|
223
|
+
struct QuantizerLloydMax : QuantizerLloydMax<NBits, SIMDLevel::NONE> {
|
|
224
|
+
using QuantizerLloydMax<NBits, SIMDLevel::NONE>::QuantizerLloydMax;
|
|
201
225
|
};
|
|
202
226
|
|
|
227
|
+
template <int NBits, SIMDLevel SL>
|
|
228
|
+
using QuantizerTurboQuantMSE = QuantizerLloydMax<NBits, SL>;
|
|
229
|
+
|
|
203
230
|
/*******************************************************************
|
|
204
231
|
* FP16 quantizer
|
|
205
232
|
*******************************************************************/
|
|
@@ -252,16 +279,12 @@ struct QuantizerBF16<SIMDLevel::NONE> : ScalarQuantizer::SQuantizer {
|
|
|
252
279
|
QuantizerBF16(size_t d_in, const std::vector<float>& /* unused */)
|
|
253
280
|
: d(d_in) {}
|
|
254
281
|
|
|
255
|
-
void encode_vector(const float* x, uint8_t* code) const
|
|
256
|
-
|
|
257
|
-
((uint16_t*)code)[i] = encode_bf16(x[i]);
|
|
258
|
-
}
|
|
282
|
+
void encode_vector(const float* x, uint8_t* code) const override {
|
|
283
|
+
encode_bf16_simd(x, (uint16_t*)code, d);
|
|
259
284
|
}
|
|
260
285
|
|
|
261
|
-
void decode_vector(const uint8_t* code, float* x) const
|
|
262
|
-
|
|
263
|
-
x[i] = decode_bf16(((uint16_t*)code)[i]);
|
|
264
|
-
}
|
|
286
|
+
void decode_vector(const uint8_t* code, float* x) const override {
|
|
287
|
+
decode_bf16_simd((const uint16_t*)code, x, d);
|
|
265
288
|
}
|
|
266
289
|
|
|
267
290
|
FAISS_ALWAYS_INLINE float reconstruct_component(
|
|
@@ -276,6 +299,11 @@ struct QuantizerBF16 : QuantizerBF16<SIMDLevel::NONE> {
|
|
|
276
299
|
using QuantizerBF16<SIMDLevel::NONE>::QuantizerBF16;
|
|
277
300
|
};
|
|
278
301
|
|
|
302
|
+
template <>
|
|
303
|
+
struct QuantizerBF16<SIMDLevel::AVX512>;
|
|
304
|
+
template <>
|
|
305
|
+
struct QuantizerBF16<SIMDLevel::AVX512_SPR>;
|
|
306
|
+
|
|
279
307
|
/*******************************************************************
|
|
280
308
|
* 8bit_direct quantizer
|
|
281
309
|
*******************************************************************/
|
|
@@ -355,6 +383,288 @@ struct Quantizer8bitDirectSigned : Quantizer8bitDirectSigned<SIMDLevel::NONE> {
|
|
|
355
383
|
using Quantizer8bitDirectSigned<SIMDLevel::NONE>::Quantizer8bitDirectSigned;
|
|
356
384
|
};
|
|
357
385
|
|
|
386
|
+
/*******************************************************************
|
|
387
|
+
* Full TurboQuant (MSE + QJL) quantizer
|
|
388
|
+
*
|
|
389
|
+
* NBits = total bits per dimension (2-5).
|
|
390
|
+
* MSE bits = NBits - 1, QJL bits = 1.
|
|
391
|
+
*
|
|
392
|
+
* Trained vector layout:
|
|
393
|
+
* [centroids (k floats), boundaries (k-1 floats),
|
|
394
|
+
* seed_lo (float), seed_hi (float), qjl_type (float)]
|
|
395
|
+
* where k = 2^(NBits-1).
|
|
396
|
+
*******************************************************************/
|
|
397
|
+
|
|
398
|
+
FAISS_PACK_STRUCTS_BEGIN
|
|
399
|
+
struct SQTurboQFactors {
|
|
400
|
+
float norm = 0;
|
|
401
|
+
float gamma = 0;
|
|
402
|
+
};
|
|
403
|
+
FAISS_PACK_STRUCTS_END
|
|
404
|
+
|
|
405
|
+
template <int NBits, SIMDLevel SL>
|
|
406
|
+
struct QuantizerTurboQuantFull;
|
|
407
|
+
|
|
408
|
+
template <int NBits>
|
|
409
|
+
struct QuantizerTurboQuantFull<NBits, SIMDLevel::NONE>
|
|
410
|
+
: ScalarQuantizer::SQuantizer {
|
|
411
|
+
static_assert(NBits >= 2 && NBits <= 5);
|
|
412
|
+
|
|
413
|
+
static constexpr int kMSEBits = NBits - 1;
|
|
414
|
+
static constexpr size_t kCentroidsCount = size_t(1) << kMSEBits;
|
|
415
|
+
|
|
416
|
+
const size_t d;
|
|
417
|
+
const float* centroids;
|
|
418
|
+
const float* boundaries;
|
|
419
|
+
|
|
420
|
+
// QJL projection type: 0 = FWHT, 2 = Random Rotation
|
|
421
|
+
uint8_t qjl_type;
|
|
422
|
+
|
|
423
|
+
// FWHT state (qjl_type == 0)
|
|
424
|
+
size_t padded_d;
|
|
425
|
+
std::vector<float> fwht_signs;
|
|
426
|
+
|
|
427
|
+
// Random Rotation state (qjl_type == 2)
|
|
428
|
+
std::vector<float> rr_matrix; // d x d orthogonal matrix (row-major)
|
|
429
|
+
|
|
430
|
+
size_t mse_plane_bytes; // bytes for one bit-plane of d bits
|
|
431
|
+
size_t mse_total_bytes; // kMSEBits * mse_plane_bytes
|
|
432
|
+
size_t qjl_plane_bytes;
|
|
433
|
+
|
|
434
|
+
QuantizerTurboQuantFull(size_t d_in, const std::vector<float>& trained)
|
|
435
|
+
: d(d_in),
|
|
436
|
+
centroids(trained.data()),
|
|
437
|
+
boundaries(trained.data() + kCentroidsCount) {
|
|
438
|
+
// trained = [centroids(k), boundaries(k-1), seed_lo, seed_hi, qjl_type]
|
|
439
|
+
size_t k = kCentroidsCount;
|
|
440
|
+
FAISS_THROW_IF_NOT(trained.size() == 2 * k - 1 + 3);
|
|
441
|
+
|
|
442
|
+
mse_plane_bytes = (d + 7) / 8;
|
|
443
|
+
mse_total_bytes = kMSEBits * mse_plane_bytes;
|
|
444
|
+
qjl_plane_bytes = (d + 7) / 8;
|
|
445
|
+
|
|
446
|
+
// Extract seed from trained
|
|
447
|
+
uint64_t seed = ScalarQuantizer::TurboQuantRefine::unpack_seed(
|
|
448
|
+
trained[2 * k - 1], trained[2 * k]);
|
|
449
|
+
qjl_type = static_cast<uint8_t>(trained[2 * k + 1]);
|
|
450
|
+
|
|
451
|
+
if (qjl_type == 0) {
|
|
452
|
+
// FWHT mode
|
|
453
|
+
padded_d = 1;
|
|
454
|
+
while (padded_d < d) {
|
|
455
|
+
padded_d <<= 1;
|
|
456
|
+
}
|
|
457
|
+
fwht_signs.resize(padded_d);
|
|
458
|
+
RandomGenerator rng(seed);
|
|
459
|
+
for (size_t i = 0; i < padded_d; i++) {
|
|
460
|
+
fwht_signs[i] = (rng.rand_int(2) == 0) ? 1.0f : -1.0f;
|
|
461
|
+
}
|
|
462
|
+
} else {
|
|
463
|
+
// Random Rotation mode
|
|
464
|
+
padded_d = d; // no padding needed for dense multiply
|
|
465
|
+
rr_matrix.resize(d * d);
|
|
466
|
+
float_randn(rr_matrix.data(), d * d, static_cast<int64_t>(seed));
|
|
467
|
+
matrix_qr(
|
|
468
|
+
static_cast<int>(d), static_cast<int>(d), rr_matrix.data());
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
void fwht_inplace(float* x, size_t n) const {
|
|
473
|
+
for (size_t h = 1; h < n; h <<= 1) {
|
|
474
|
+
for (size_t i = 0; i < n; i += h << 1) {
|
|
475
|
+
for (size_t j = i; j < i + h; j++) {
|
|
476
|
+
float a = x[j];
|
|
477
|
+
float b = x[j + h];
|
|
478
|
+
x[j] = a + b;
|
|
479
|
+
x[j + h] = a - b;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/// Forward QJL projection: residual -> projected (d outputs)
|
|
486
|
+
void project_forward(const float* residual, float* out) const {
|
|
487
|
+
if (qjl_type == 0) {
|
|
488
|
+
std::vector<float> fwht_buf(padded_d);
|
|
489
|
+
for (size_t j = 0; j < d; j++) {
|
|
490
|
+
fwht_buf[j] = residual[j] * fwht_signs[j];
|
|
491
|
+
}
|
|
492
|
+
for (size_t j = d; j < padded_d; j++) {
|
|
493
|
+
fwht_buf[j] = 0.0f;
|
|
494
|
+
}
|
|
495
|
+
fwht_inplace(fwht_buf.data(), padded_d);
|
|
496
|
+
for (size_t j = 0; j < d; j++) {
|
|
497
|
+
out[j] = fwht_buf[j];
|
|
498
|
+
}
|
|
499
|
+
} else {
|
|
500
|
+
rr_forward(residual, out);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/// Inverse QJL projection: signs_buf -> reconstructed (d outputs)
|
|
505
|
+
void project_inverse(float* signs_buf, float* out) const {
|
|
506
|
+
if (qjl_type == 0) {
|
|
507
|
+
fwht_inplace(signs_buf, padded_d);
|
|
508
|
+
for (size_t j = 0; j < d; j++) {
|
|
509
|
+
out[j] = signs_buf[j] * fwht_signs[j];
|
|
510
|
+
}
|
|
511
|
+
} else {
|
|
512
|
+
rr_inverse(signs_buf, out);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
void rr_forward(const float* x, float* out) const {
|
|
517
|
+
float alpha = 1.0f;
|
|
518
|
+
float beta = 0.0f;
|
|
519
|
+
int di = static_cast<int>(d);
|
|
520
|
+
int one = 1;
|
|
521
|
+
sgemm_("T",
|
|
522
|
+
"N",
|
|
523
|
+
&di,
|
|
524
|
+
&one,
|
|
525
|
+
&di,
|
|
526
|
+
&alpha,
|
|
527
|
+
rr_matrix.data(),
|
|
528
|
+
&di,
|
|
529
|
+
x,
|
|
530
|
+
&di,
|
|
531
|
+
&beta,
|
|
532
|
+
out,
|
|
533
|
+
&di);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
void rr_inverse(const float* x, float* out) const {
|
|
537
|
+
float alpha = 1.0f;
|
|
538
|
+
float beta = 0.0f;
|
|
539
|
+
int di = static_cast<int>(d);
|
|
540
|
+
int one = 1;
|
|
541
|
+
sgemm_("N",
|
|
542
|
+
"N",
|
|
543
|
+
&di,
|
|
544
|
+
&one,
|
|
545
|
+
&di,
|
|
546
|
+
&alpha,
|
|
547
|
+
rr_matrix.data(),
|
|
548
|
+
&di,
|
|
549
|
+
x,
|
|
550
|
+
&di,
|
|
551
|
+
&beta,
|
|
552
|
+
out,
|
|
553
|
+
&di);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/// Store MSE index for dimension j using BIT-PLANE layout.
|
|
557
|
+
/// Plane p stores bit p of every dimension's index.
|
|
558
|
+
void store_mse_index(uint8_t idx, uint8_t* code, size_t j) const {
|
|
559
|
+
for (int p = 0; p < kMSEBits; p++) {
|
|
560
|
+
if (idx & (1 << p)) {
|
|
561
|
+
code[p * mse_plane_bytes + j / 8] |= (1 << (j % 8));
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/// Load MSE index for dimension j from BIT-PLANE layout.
|
|
567
|
+
uint8_t load_mse_index(const uint8_t* code, size_t j) const {
|
|
568
|
+
uint8_t idx = 0;
|
|
569
|
+
for (int p = 0; p < kMSEBits; p++) {
|
|
570
|
+
if (code[p * mse_plane_bytes + j / 8] & (1 << (j % 8))) {
|
|
571
|
+
idx |= (1 << p);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return idx;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
void encode_vector(const float* x, uint8_t* code) const final {
|
|
578
|
+
float sqrt_d = std::sqrt(static_cast<float>(d));
|
|
579
|
+
float inv_sqrt_d = 1.0f / sqrt_d;
|
|
580
|
+
|
|
581
|
+
float x_norm = std::sqrt(fvec_norm_L2sqr(x, d));
|
|
582
|
+
if (x_norm < 1e-30f) {
|
|
583
|
+
x_norm = 1e-30f;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// MSE quantize in scaled space + compute residual
|
|
587
|
+
std::vector<float> residual(padded_d);
|
|
588
|
+
for (size_t j = 0; j < d; j++) {
|
|
589
|
+
float v = x[j] / x_norm; // unit-normalized
|
|
590
|
+
float val = v * sqrt_d; // scaled for MSE lookup
|
|
591
|
+
uint8_t idx = static_cast<uint8_t>(
|
|
592
|
+
std::upper_bound(
|
|
593
|
+
boundaries,
|
|
594
|
+
boundaries + (kCentroidsCount - 1),
|
|
595
|
+
val) -
|
|
596
|
+
boundaries);
|
|
597
|
+
store_mse_index(idx, code, j);
|
|
598
|
+
residual[j] = v - centroids[idx] * inv_sqrt_d;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// QJL: project residual, take signs
|
|
602
|
+
std::vector<float> proj(d);
|
|
603
|
+
project_forward(residual.data(), proj.data());
|
|
604
|
+
|
|
605
|
+
uint8_t* qjl_code = code + mse_total_bytes;
|
|
606
|
+
for (size_t j = 0; j < d; j++) {
|
|
607
|
+
if (proj[j] > 0.0f) {
|
|
608
|
+
rabitq_utils::set_bit_standard(qjl_code, j);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Store per-vector factors
|
|
613
|
+
float gamma = std::sqrt(fvec_norm_L2sqr(residual.data(), d));
|
|
614
|
+
auto* factors = reinterpret_cast<SQTurboQFactors*>(
|
|
615
|
+
code + mse_total_bytes + qjl_plane_bytes);
|
|
616
|
+
factors->norm = x_norm;
|
|
617
|
+
factors->gamma = gamma;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
void decode_vector(const uint8_t* code, float* x) const final {
|
|
621
|
+
float inv_sqrt_d = 1.0f / std::sqrt(static_cast<float>(d));
|
|
622
|
+
float inv_sqrt_pd = 1.0f / std::sqrt(static_cast<float>(padded_d));
|
|
623
|
+
|
|
624
|
+
const auto* factors = reinterpret_cast<const SQTurboQFactors*>(
|
|
625
|
+
code + mse_total_bytes + qjl_plane_bytes);
|
|
626
|
+
|
|
627
|
+
// MSE reconstruction
|
|
628
|
+
for (size_t j = 0; j < d; j++) {
|
|
629
|
+
uint8_t idx = load_mse_index(code, j);
|
|
630
|
+
x[j] = centroids[idx] * inv_sqrt_d;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// QJL reconstruction: coeff * gamma * S^T * signs
|
|
634
|
+
const uint8_t* qjl_code = code + mse_total_bytes;
|
|
635
|
+
float coeff =
|
|
636
|
+
std::sqrt(M_PI / 2.0f) / static_cast<float>(d) * factors->gamma;
|
|
637
|
+
|
|
638
|
+
std::vector<float> signs_buf(padded_d);
|
|
639
|
+
for (size_t j = 0; j < d; j++) {
|
|
640
|
+
signs_buf[j] = rabitq_utils::extract_bit_standard(qjl_code, j)
|
|
641
|
+
? inv_sqrt_pd
|
|
642
|
+
: -inv_sqrt_pd;
|
|
643
|
+
}
|
|
644
|
+
for (size_t j = d; j < padded_d; j++) {
|
|
645
|
+
signs_buf[j] = 0.0f;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
std::vector<float> reconstructed(d);
|
|
649
|
+
project_inverse(signs_buf.data(), reconstructed.data());
|
|
650
|
+
for (size_t j = 0; j < d; j++) {
|
|
651
|
+
x[j] += coeff * reconstructed[j];
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// Scale by norm
|
|
655
|
+
for (size_t j = 0; j < d; j++) {
|
|
656
|
+
x[j] *= factors->norm;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
template <int NBits, SIMDLevel SL>
|
|
662
|
+
struct QuantizerTurboQuantFull
|
|
663
|
+
: QuantizerTurboQuantFull<NBits, SIMDLevel::NONE> {
|
|
664
|
+
using QuantizerTurboQuantFull<NBits, SIMDLevel::NONE>::
|
|
665
|
+
QuantizerTurboQuantFull;
|
|
666
|
+
};
|
|
667
|
+
|
|
358
668
|
/*******************************************************************
|
|
359
669
|
* Selection function
|
|
360
670
|
*******************************************************************/
|