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
|
@@ -214,6 +214,12 @@ struct QuantizerTemplate<
|
|
|
214
214
|
return simd16float32(_mm512_fmadd_ps(
|
|
215
215
|
xi, _mm512_set1_ps(this->vdiff), _mm512_set1_ps(this->vmin)));
|
|
216
216
|
}
|
|
217
|
+
|
|
218
|
+
/// Raw codec decode without denormalization
|
|
219
|
+
FAISS_ALWAYS_INLINE simd16float32
|
|
220
|
+
decode_16_raw(const uint8_t* code, int i) const {
|
|
221
|
+
return Codec::decode_16_components(code, i);
|
|
222
|
+
}
|
|
217
223
|
};
|
|
218
224
|
|
|
219
225
|
template <class Codec>
|
|
@@ -244,41 +250,87 @@ struct QuantizerTemplate<
|
|
|
244
250
|
};
|
|
245
251
|
|
|
246
252
|
/**********************************************************
|
|
247
|
-
*
|
|
253
|
+
* Lloyd-Max scalar quantizer
|
|
248
254
|
**********************************************************/
|
|
249
255
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
256
|
+
// 1-bit Lloyd-Max AVX512: 16 comparisons → 2 bytes via mask compare.
|
|
257
|
+
template <>
|
|
258
|
+
struct QuantizerLloydMax<1, SIMDLevel::AVX512>
|
|
259
|
+
: QuantizerLloydMax<1, SIMDLevel::NONE> {
|
|
260
|
+
using Base = QuantizerLloydMax<1, SIMDLevel::NONE>;
|
|
261
|
+
|
|
262
|
+
QuantizerLloydMax(size_t d, const std::vector<float>& trained)
|
|
263
|
+
: Base(d, trained) {
|
|
264
|
+
assert(d % 16 == 0);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
FAISS_ALWAYS_INLINE simd16float32
|
|
268
|
+
reconstruct_16_components(const uint8_t* code, int i) const {
|
|
269
|
+
return simd16float32(_mm512_i32gather_ps(
|
|
270
|
+
unpack_16x1bit_to_u32(code, i),
|
|
271
|
+
this->centroids,
|
|
272
|
+
sizeof(float)));
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
void encode_vector(const float* x, uint8_t* code) const final {
|
|
276
|
+
__m512 boundary = _mm512_set1_ps(this->boundaries[0]);
|
|
277
|
+
for (size_t i = 0; i < this->d; i += 16) {
|
|
278
|
+
__m512 vals = _mm512_loadu_ps(x + i);
|
|
279
|
+
__mmask16 mask = _mm512_cmp_ps_mask(vals, boundary, _CMP_GT_OQ);
|
|
280
|
+
uint16_t bits = _cvtmask16_u32(mask);
|
|
281
|
+
memcpy(code + i / 8, &bits, sizeof(uint16_t));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
void decode_vector(const uint8_t* code, float* x) const final {
|
|
286
|
+
for (size_t i = 0; i < this->d; i += 16) {
|
|
287
|
+
simd16float32 xi =
|
|
288
|
+
reconstruct_16_components(code, static_cast<int>(i));
|
|
289
|
+
_mm512_storeu_ps(x + i, xi.f);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
};
|
|
275
293
|
|
|
294
|
+
// 2-4 bit Lloyd-Max AVX512: decode via gather, encode stays scalar.
|
|
295
|
+
#define DEFINE_LLOYD_MAX_AVX512_MULTIBIT(NBITS, UNPACK_EXPR) \
|
|
296
|
+
template <> \
|
|
297
|
+
struct QuantizerLloydMax<NBITS, SIMDLevel::AVX512> \
|
|
298
|
+
: QuantizerLloydMax<NBITS, SIMDLevel::NONE> { \
|
|
299
|
+
using Base = QuantizerLloydMax<NBITS, SIMDLevel::NONE>; \
|
|
300
|
+
\
|
|
301
|
+
QuantizerLloydMax(size_t d, const std::vector<float>& trained) \
|
|
302
|
+
: Base(d, trained) { \
|
|
303
|
+
assert(d % 16 == 0); \
|
|
304
|
+
} \
|
|
305
|
+
\
|
|
306
|
+
FAISS_ALWAYS_INLINE simd16float32 \
|
|
307
|
+
reconstruct_16_components(const uint8_t* code, int i) const { \
|
|
308
|
+
return simd16float32(_mm512_i32gather_ps( \
|
|
309
|
+
(UNPACK_EXPR), this->centroids, sizeof(float))); \
|
|
310
|
+
} \
|
|
311
|
+
\
|
|
312
|
+
void decode_vector(const uint8_t* code, float* x) const final { \
|
|
313
|
+
for (size_t i = 0; i < this->d; i += 16) { \
|
|
314
|
+
simd16float32 xi = \
|
|
315
|
+
reconstruct_16_components(code, static_cast<int>(i)); \
|
|
316
|
+
_mm512_storeu_ps(x + i, xi.f); \
|
|
317
|
+
} \
|
|
318
|
+
} \
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
DEFINE_LLOYD_MAX_AVX512_MULTIBIT(2, unpack_16x2bit_to_u32(code, i));
|
|
322
|
+
DEFINE_LLOYD_MAX_AVX512_MULTIBIT(3, unpack_16x3bit_to_u32(code, i));
|
|
323
|
+
DEFINE_LLOYD_MAX_AVX512_MULTIBIT(4, unpack_16x4bit_to_u32(code, i));
|
|
324
|
+
|
|
325
|
+
#undef DEFINE_LLOYD_MAX_AVX512_MULTIBIT
|
|
326
|
+
|
|
327
|
+
// 8-bit Lloyd-Max AVX512
|
|
276
328
|
template <>
|
|
277
|
-
struct
|
|
278
|
-
:
|
|
279
|
-
using Base =
|
|
329
|
+
struct QuantizerLloydMax<8, SIMDLevel::AVX512>
|
|
330
|
+
: QuantizerLloydMax<8, SIMDLevel::NONE> {
|
|
331
|
+
using Base = QuantizerLloydMax<8, SIMDLevel::NONE>;
|
|
280
332
|
|
|
281
|
-
|
|
333
|
+
QuantizerLloydMax(size_t d, const std::vector<float>& trained)
|
|
282
334
|
: Base(d, trained) {
|
|
283
335
|
assert(d % 16 == 0);
|
|
284
336
|
}
|
|
@@ -291,6 +343,14 @@ struct QuantizerTurboQuantMSE<8, SIMDLevel::AVX512>
|
|
|
291
343
|
return simd16float32(
|
|
292
344
|
_mm512_i32gather_ps(indices, this->centroids, sizeof(float)));
|
|
293
345
|
}
|
|
346
|
+
|
|
347
|
+
void decode_vector(const uint8_t* code, float* x) const final {
|
|
348
|
+
for (size_t i = 0; i < this->d; i += 16) {
|
|
349
|
+
simd16float32 xi =
|
|
350
|
+
reconstruct_16_components(code, static_cast<int>(i));
|
|
351
|
+
_mm512_storeu_ps(x + i, xi.f);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
294
354
|
};
|
|
295
355
|
|
|
296
356
|
/**********************************************************
|
|
@@ -411,6 +471,22 @@ struct SimilarityL2<SIMDLevel::AVX512> {
|
|
|
411
471
|
FAISS_ALWAYS_INLINE float result_16() {
|
|
412
472
|
return horizontal_add(accu16);
|
|
413
473
|
}
|
|
474
|
+
|
|
475
|
+
static void adjust_query_for_raw_decode(
|
|
476
|
+
const float* x,
|
|
477
|
+
float* q_adj,
|
|
478
|
+
size_t d,
|
|
479
|
+
float vmin,
|
|
480
|
+
float vdiff,
|
|
481
|
+
float& scale_factor,
|
|
482
|
+
float& bias) {
|
|
483
|
+
float inv_vdiff = (vdiff != 0) ? 1.0f / vdiff : 0.0f;
|
|
484
|
+
for (size_t i = 0; i < d; i++) {
|
|
485
|
+
q_adj[i] = (x[i] - vmin) * inv_vdiff;
|
|
486
|
+
}
|
|
487
|
+
scale_factor = vdiff * vdiff;
|
|
488
|
+
bias = 0;
|
|
489
|
+
}
|
|
414
490
|
};
|
|
415
491
|
|
|
416
492
|
template <>
|
|
@@ -445,6 +521,23 @@ struct SimilarityIP<SIMDLevel::AVX512> {
|
|
|
445
521
|
FAISS_ALWAYS_INLINE float result_16() {
|
|
446
522
|
return horizontal_add(accu16);
|
|
447
523
|
}
|
|
524
|
+
|
|
525
|
+
static void adjust_query_for_raw_decode(
|
|
526
|
+
const float* x,
|
|
527
|
+
float* q_adj,
|
|
528
|
+
size_t d,
|
|
529
|
+
float vmin,
|
|
530
|
+
float vdiff,
|
|
531
|
+
float& scale_factor,
|
|
532
|
+
float& bias) {
|
|
533
|
+
float sum_q = 0;
|
|
534
|
+
for (size_t i = 0; i < d; i++) {
|
|
535
|
+
q_adj[i] = x[i];
|
|
536
|
+
sum_q += x[i];
|
|
537
|
+
}
|
|
538
|
+
scale_factor = vdiff;
|
|
539
|
+
bias = vmin * sum_q;
|
|
540
|
+
}
|
|
448
541
|
};
|
|
449
542
|
|
|
450
543
|
/**********************************************************
|
|
@@ -458,8 +551,23 @@ struct DCTemplate<Quantizer, Similarity, SIMDLevel::AVX512>
|
|
|
458
551
|
|
|
459
552
|
Quantizer quant;
|
|
460
553
|
|
|
554
|
+
// Pre-adjusted query buffer for uniform quantizers
|
|
555
|
+
std::vector<float> q_adj;
|
|
556
|
+
float scale_factor = 0;
|
|
557
|
+
float bias = 0;
|
|
558
|
+
|
|
559
|
+
static constexpr bool has_decode_raw() {
|
|
560
|
+
return requires(const Quantizer& q, const uint8_t* c, int i) {
|
|
561
|
+
{ q.decode_16_raw(c, i) };
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
461
565
|
DCTemplate(size_t d, const std::vector<float>& trained)
|
|
462
|
-
: quant(d, trained) {
|
|
566
|
+
: quant(d, trained) {
|
|
567
|
+
if constexpr (has_decode_raw()) {
|
|
568
|
+
q_adj.resize(d);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
463
571
|
|
|
464
572
|
float compute_distance(const float* x, const uint8_t* code) const {
|
|
465
573
|
Similarity sim(x);
|
|
@@ -485,6 +593,26 @@ struct DCTemplate<Quantizer, Similarity, SIMDLevel::AVX512>
|
|
|
485
593
|
|
|
486
594
|
void set_query(const float* x) final {
|
|
487
595
|
q = x;
|
|
596
|
+
if constexpr (has_decode_raw()) {
|
|
597
|
+
Sim::adjust_query_for_raw_decode(
|
|
598
|
+
x,
|
|
599
|
+
q_adj.data(),
|
|
600
|
+
quant.d,
|
|
601
|
+
quant.vmin,
|
|
602
|
+
quant.vdiff,
|
|
603
|
+
scale_factor,
|
|
604
|
+
bias);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
float query_to_code_predecoded(const uint8_t* code) const {
|
|
609
|
+
Similarity sim(q_adj.data());
|
|
610
|
+
sim.begin_16();
|
|
611
|
+
for (size_t i = 0; i < quant.d; i += 16) {
|
|
612
|
+
simd16float32 xi = quant.decode_16_raw(code, i);
|
|
613
|
+
sim.add_16_components(xi);
|
|
614
|
+
}
|
|
615
|
+
return bias + scale_factor * sim.result_16();
|
|
488
616
|
}
|
|
489
617
|
|
|
490
618
|
float symmetric_dis(idx_t i, idx_t j) override {
|
|
@@ -493,7 +621,11 @@ struct DCTemplate<Quantizer, Similarity, SIMDLevel::AVX512>
|
|
|
493
621
|
}
|
|
494
622
|
|
|
495
623
|
float query_to_code(const uint8_t* code) const final {
|
|
496
|
-
|
|
624
|
+
if constexpr (has_decode_raw()) {
|
|
625
|
+
return query_to_code_predecoded(code);
|
|
626
|
+
} else {
|
|
627
|
+
return compute_distance(q, code);
|
|
628
|
+
}
|
|
497
629
|
}
|
|
498
630
|
|
|
499
631
|
void query_to_codes_batch_4(
|
|
@@ -545,24 +677,36 @@ struct DistanceComputerByte<Similarity, SIMDLevel::AVX512>
|
|
|
545
677
|
|
|
546
678
|
int compute_code_distance(const uint8_t* code1, const uint8_t* code2)
|
|
547
679
|
const {
|
|
548
|
-
// compute
|
|
680
|
+
// compute 32 lanes of 16-bit products (32-bytes) at once for
|
|
549
681
|
// the supported metrics
|
|
550
682
|
__m512i accu = _mm512_setzero_si512();
|
|
551
|
-
constexpr int kLanes =
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
__m512i
|
|
557
|
-
|
|
558
|
-
__m512i v;
|
|
683
|
+
constexpr int kLanes = 32;
|
|
684
|
+
int i = 0;
|
|
685
|
+
for (; i + kLanes <= d; i += kLanes) {
|
|
686
|
+
__m256i c1 = _mm256_loadu_epi8(code1 + i);
|
|
687
|
+
__m256i c2 = _mm256_loadu_epi8(code2 + i);
|
|
688
|
+
__m512i c1i16 = _mm512_cvtepu8_epi16(c1);
|
|
689
|
+
__m512i c2i16 = _mm512_cvtepu8_epi16(c2);
|
|
559
690
|
if (Sim::metric_type == METRIC_INNER_PRODUCT) {
|
|
560
|
-
|
|
691
|
+
accu = _mm512_add_epi32(accu, _mm512_madd_epi16(c1i16, c2i16));
|
|
561
692
|
} else {
|
|
562
|
-
__m512i diff =
|
|
563
|
-
|
|
693
|
+
__m512i diff = _mm512_sub_epi16(c1i16, c2i16);
|
|
694
|
+
accu = _mm512_add_epi32(accu, _mm512_madd_epi16(diff, diff));
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
// tail handling for dimensions not divisible by 32
|
|
698
|
+
if (i < d) {
|
|
699
|
+
__mmask32 mask = (__mmask32)((1ULL << (d - i)) - 1ULL);
|
|
700
|
+
__m256i c1 = _mm256_maskz_loadu_epi8(mask, code1 + i);
|
|
701
|
+
__m256i c2 = _mm256_maskz_loadu_epi8(mask, code2 + i);
|
|
702
|
+
__m512i c1i16 = _mm512_cvtepu8_epi16(c1);
|
|
703
|
+
__m512i c2i16 = _mm512_cvtepu8_epi16(c2);
|
|
704
|
+
if (Sim::metric_type == METRIC_INNER_PRODUCT) {
|
|
705
|
+
accu = _mm512_add_epi32(accu, _mm512_madd_epi16(c1i16, c2i16));
|
|
706
|
+
} else {
|
|
707
|
+
__m512i diff = _mm512_sub_epi16(c1i16, c2i16);
|
|
708
|
+
accu = _mm512_add_epi32(accu, _mm512_madd_epi16(diff, diff));
|
|
564
709
|
}
|
|
565
|
-
accu = _mm512_add_epi32(accu, v);
|
|
566
710
|
}
|
|
567
711
|
return _mm512_reduce_add_epi32(accu);
|
|
568
712
|
}
|
|
@@ -588,10 +732,105 @@ struct DistanceComputerByte<Similarity, SIMDLevel::AVX512>
|
|
|
588
732
|
}
|
|
589
733
|
};
|
|
590
734
|
|
|
735
|
+
template <class Similarity>
|
|
736
|
+
struct DistanceComputerByteSigned<Similarity, SIMDLevel::AVX512>
|
|
737
|
+
: SQDistanceComputer {
|
|
738
|
+
using Sim = Similarity;
|
|
739
|
+
|
|
740
|
+
int d;
|
|
741
|
+
std::vector<uint8_t> tmp;
|
|
742
|
+
|
|
743
|
+
DistanceComputerByteSigned(int d, const std::vector<float>&)
|
|
744
|
+
: d(d), tmp(d) {}
|
|
745
|
+
|
|
746
|
+
int compute_code_distance(const uint8_t* code1, const uint8_t* code2)
|
|
747
|
+
const {
|
|
748
|
+
// codes store value + 128. madd_epi16 is signed, so IP unbiases the
|
|
749
|
+
// bytes before multiplying; for L2 the +128 cancels in the difference.
|
|
750
|
+
// Only dispatched for d % 32 == 0, so the loop needs no tail.
|
|
751
|
+
__m512i accu = _mm512_setzero_si512();
|
|
752
|
+
constexpr int kLanes = 32;
|
|
753
|
+
for (int i = 0; i + kLanes <= d; i += kLanes) {
|
|
754
|
+
__m512i c1 = _mm512_cvtepu8_epi16(_mm256_loadu_epi8(code1 + i));
|
|
755
|
+
__m512i c2 = _mm512_cvtepu8_epi16(_mm256_loadu_epi8(code2 + i));
|
|
756
|
+
if (Sim::metric_type == METRIC_INNER_PRODUCT) {
|
|
757
|
+
const __m512i bias = _mm512_set1_epi16(128);
|
|
758
|
+
c1 = _mm512_sub_epi16(c1, bias);
|
|
759
|
+
c2 = _mm512_sub_epi16(c2, bias);
|
|
760
|
+
accu = _mm512_add_epi32(accu, _mm512_madd_epi16(c1, c2));
|
|
761
|
+
} else {
|
|
762
|
+
__m512i diff = _mm512_sub_epi16(c1, c2);
|
|
763
|
+
accu = _mm512_add_epi32(accu, _mm512_madd_epi16(diff, diff));
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
return _mm512_reduce_add_epi32(accu);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
void set_query(const float* x) final {
|
|
770
|
+
for (int i = 0; i < d; i++) {
|
|
771
|
+
tmp[i] = uint8_t(int(x[i]) + 128);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
int compute_distance(const float* x, const uint8_t* code) {
|
|
776
|
+
set_query(x);
|
|
777
|
+
return compute_code_distance(tmp.data(), code);
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
float symmetric_dis(idx_t i, idx_t j) override {
|
|
781
|
+
return compute_code_distance(
|
|
782
|
+
codes + i * code_size, codes + j * code_size);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
float query_to_code(const uint8_t* code) const final {
|
|
786
|
+
return compute_code_distance(tmp.data(), code);
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
|
|
790
|
+
/**********************************************************
|
|
791
|
+
* TurboQuant masked_sum AVX512 specialization
|
|
792
|
+
**********************************************************/
|
|
793
|
+
|
|
794
|
+
template <SIMDLevel SL0>
|
|
795
|
+
float turboq_masked_sum(const float* arr, const uint8_t* bits, size_t d);
|
|
796
|
+
|
|
797
|
+
template <>
|
|
798
|
+
float turboq_masked_sum<SIMDLevel::AVX512>(
|
|
799
|
+
const float* arr,
|
|
800
|
+
const uint8_t* bits,
|
|
801
|
+
size_t d) {
|
|
802
|
+
__m512 acc = _mm512_setzero_ps();
|
|
803
|
+
size_t i = 0;
|
|
804
|
+
size_t full_16 = (d / 16) * 16;
|
|
805
|
+
for (; i < full_16; i += 16) {
|
|
806
|
+
uint16_t mask16;
|
|
807
|
+
memcpy(&mask16, bits + i / 8, sizeof(mask16));
|
|
808
|
+
__mmask16 k = _cvtu32_mask16(mask16);
|
|
809
|
+
__m512 vals = _mm512_loadu_ps(arr + i);
|
|
810
|
+
acc = _mm512_mask_add_ps(acc, k, acc, vals);
|
|
811
|
+
}
|
|
812
|
+
float result = _mm512_reduce_add_ps(acc);
|
|
813
|
+
if (i < d) {
|
|
814
|
+
size_t remaining = d - i;
|
|
815
|
+
__mmask16 tail_mask = _cvtu32_mask16((1u << remaining) - 1);
|
|
816
|
+
__m512 tail_vals = _mm512_maskz_loadu_ps(tail_mask, arr + i);
|
|
817
|
+
uint16_t bits_tail = 0;
|
|
818
|
+
size_t bytes_remaining = (remaining + 7) / 8;
|
|
819
|
+
memcpy(&bits_tail, bits + i / 8, bytes_remaining);
|
|
820
|
+
__mmask16 bits_k = _cvtu32_mask16(bits_tail);
|
|
821
|
+
__mmask16 combined = _kand_mask16(tail_mask, bits_k);
|
|
822
|
+
__m512 masked_tail = _mm512_maskz_mov_ps(combined, tail_vals);
|
|
823
|
+
result += _mm512_reduce_add_ps(masked_tail);
|
|
824
|
+
}
|
|
825
|
+
return result;
|
|
826
|
+
}
|
|
827
|
+
|
|
591
828
|
} // namespace scalar_quantizer
|
|
592
829
|
} // namespace faiss
|
|
593
830
|
|
|
831
|
+
#ifndef SQ_AVX512_SKIP_DISPATCH
|
|
594
832
|
#define THE_LEVEL_TO_DISPATCH SIMDLevel::AVX512
|
|
595
833
|
#include <faiss/impl/scalar_quantizer/sq-dispatch.h>
|
|
834
|
+
#endif
|
|
596
835
|
|
|
597
836
|
#endif // COMPILE_SIMD_AVX512
|