faiss 0.6.4 → 0.6.5
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 +4 -0
- data/ext/faiss/extconf.rb +1 -1
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +175 -0
- data/vendor/faiss/faiss/Clustering.cpp +150 -60
- data/vendor/faiss/faiss/Clustering.h +29 -0
- data/vendor/faiss/faiss/IVFlib.cpp +99 -0
- data/vendor/faiss/faiss/IVFlib.h +15 -0
- data/vendor/faiss/faiss/Index.cpp +44 -0
- data/vendor/faiss/faiss/Index.h +19 -14
- data/vendor/faiss/faiss/IndexBinary.cpp +8 -0
- data/vendor/faiss/faiss/IndexBinary.h +8 -0
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +82 -4
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +19 -0
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +34 -0
- data/vendor/faiss/faiss/IndexFastScan.cpp +33 -17
- data/vendor/faiss/faiss/IndexFastScan.h +6 -3
- data/vendor/faiss/faiss/IndexFlat.cpp +56 -0
- data/vendor/faiss/faiss/IndexFlat.h +31 -0
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +6 -1
- data/vendor/faiss/faiss/IndexHNSW.cpp +456 -10
- data/vendor/faiss/faiss/IndexHNSW.h +38 -0
- data/vendor/faiss/faiss/IndexIDMap.cpp +32 -0
- data/vendor/faiss/faiss/IndexIDMap.h +7 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +281 -31
- data/vendor/faiss/faiss/IndexIVF.h +53 -1
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +46 -14
- data/vendor/faiss/faiss/IndexIVFFastScan.h +4 -2
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +33 -0
- data/vendor/faiss/faiss/IndexIVFFlat.h +16 -0
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +1 -0
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +3 -20
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +50 -14
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -2
- data/vendor/faiss/faiss/IndexIVFSQFastScan.cpp +855 -0
- data/vendor/faiss/faiss/IndexIVFSQFastScan.h +145 -0
- data/vendor/faiss/faiss/IndexNNDescent.cpp +0 -3
- data/vendor/faiss/faiss/IndexPiPNN.cpp +201 -0
- data/vendor/faiss/faiss/IndexPiPNN.h +83 -0
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +6 -3
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +10 -4
- data/vendor/faiss/faiss/IndexReplicas.cpp +20 -0
- data/vendor/faiss/faiss/IndexReplicas.h +9 -0
- data/vendor/faiss/faiss/IndexSQFastScan.cpp +648 -0
- data/vendor/faiss/faiss/IndexSQFastScan.h +129 -0
- data/vendor/faiss/faiss/IndexShards.cpp +10 -0
- data/vendor/faiss/faiss/IndexShards.h +5 -0
- data/vendor/faiss/faiss/SuperKMeans.cpp +57 -15
- data/vendor/faiss/faiss/SuperKMeans.h +9 -4
- data/vendor/faiss/faiss/VectorTransform.cpp +3 -2
- data/vendor/faiss/faiss/clone_index.cpp +24 -0
- data/vendor/faiss/faiss/gpu/Dataset.h +112 -0
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +16 -13
- data/vendor/faiss/faiss/gpu/GpuCloner.h +4 -0
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +3 -0
- data/vendor/faiss/faiss/gpu/GpuIndex.h +4 -13
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryCagra.h +26 -13
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +45 -22
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +6 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuDatasetHeader.cpp +18 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +215 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +98 -0
- data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +11 -0
- data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +1 -1
- data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +11 -0
- data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +92 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +4 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexBinaryFlat.h +69 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +38 -0
- data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +106 -0
- data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +10 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +2 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +1 -6
- data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +134 -45
- data/vendor/faiss/faiss/impl/ClusteringHelpers.h +36 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +286 -136
- data/vendor/faiss/faiss/impl/DistanceComputer.cpp +63 -0
- data/vendor/faiss/faiss/impl/DistanceComputer.h +3 -29
- data/vendor/faiss/faiss/impl/HNSW.cpp +46 -10
- data/vendor/faiss/faiss/impl/HNSW.h +72 -0
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +6 -19
- data/vendor/faiss/faiss/impl/NNDescent.cpp +2 -1
- data/vendor/faiss/faiss/impl/NSG.cpp +3 -2
- data/vendor/faiss/faiss/impl/Panorama.h +3 -2
- data/vendor/faiss/faiss/impl/PiPNN.cpp +822 -0
- data/vendor/faiss/faiss/impl/PiPNN.h +122 -0
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +54 -11
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +1 -1
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +81 -57
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +15 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +29 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +1 -6
- data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +5 -2
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +0 -4
- data/vendor/faiss/faiss/impl/expanded_scanners.h +88 -0
- data/vendor/faiss/faiss/impl/fast_scan/FastScanDistancePostProcessing.h +4 -0
- data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +61 -64
- data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +13 -14
- data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +17 -129
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +25 -19
- data/vendor/faiss/faiss/impl/fast_scan/fast_scan.cpp +5 -0
- data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +0 -88
- data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/kernels_neon.h +155 -0
- data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +22 -1
- data/vendor/faiss/faiss/impl/fast_scan/kernels_simd512.h +3 -2
- data/vendor/faiss/faiss/impl/fast_scan/simd_result_handlers.h +41 -23
- data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/index_read.cpp +172 -0
- data/vendor/faiss/faiss/impl/index_write.cpp +95 -0
- data/vendor/faiss/faiss/impl/pipnn/HashPrune.cpp +159 -0
- data/vendor/faiss/faiss/impl/pipnn/HashPrune.h +69 -0
- data/vendor/faiss/faiss/impl/pipnn/Partition.cpp +587 -0
- data/vendor/faiss/faiss/impl/pipnn/Partition.h +93 -0
- data/vendor/faiss/faiss/impl/pipnn/kernels.cpp +326 -0
- data/vendor/faiss/faiss/impl/pipnn/kernels.h +92 -0
- data/vendor/faiss/faiss/impl/platform_macros.h +45 -0
- data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +79 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +6 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-avx2.h +4 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-avx512.h +4 -1
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +19 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +6 -6
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +131 -6
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_rvv_kernel.h +89 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +21 -10
- data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +45 -18
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +2 -1
- data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +5 -1
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +28 -52
- data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +59 -11
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +226 -77
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +482 -103
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +2 -149
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +3 -698
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +66 -57
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +101 -96
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +3185 -144
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq8_coefficients.h +48 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq8_rvv_kernel.h +546 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +2 -2
- data/vendor/faiss/faiss/impl/simd_dispatch.h +7 -0
- data/vendor/faiss/faiss/impl/simdlib/simdlib_avx2.h +14 -0
- data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +7 -8
- data/vendor/faiss/faiss/impl/sq_fastscan_utils.h +232 -0
- data/vendor/faiss/faiss/index_factory.cpp +76 -0
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +3 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +3 -2
- data/vendor/faiss/faiss/utils/AlignedTable.h +6 -1
- data/vendor/faiss/faiss/utils/Heap.cpp +4 -3
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +16 -5
- data/vendor/faiss/faiss/utils/bf16.h +36 -0
- data/vendor/faiss/faiss/utils/distances.cpp +226 -15
- data/vendor/faiss/faiss/utils/distances.h +34 -0
- data/vendor/faiss/faiss/utils/distances_dispatch.h +6 -4
- data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +2 -5
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +0 -14
- data/vendor/faiss/faiss/utils/distances_fused/rvv.cpp +25 -0
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +0 -4
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +2 -1
- data/vendor/faiss/faiss/utils/distances_simd.cpp +9 -0
- data/vendor/faiss/faiss/utils/fp16-fp16c.h +4 -0
- data/vendor/faiss/faiss/utils/fp16-inl.h +26 -52
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_vpopcnt.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +33 -5
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_vpopcnt.h +15 -30
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-neon.h +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +2 -1
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_rvv.cpp +0 -4
- data/vendor/faiss/faiss/utils/pq_code_distance.h +8 -4
- data/vendor/faiss/faiss/utils/prefetch.h +1 -26
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +26 -27
- data/vendor/faiss/faiss/utils/quantize_lut.h +11 -0
- data/vendor/faiss/faiss/utils/rabitq_simd.h +51 -16
- data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +9 -4
- data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +37 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +64 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +64 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +353 -71
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv_kernel.h +68 -0
- data/vendor/faiss/faiss/utils/simd_impl/exhaustive_L2sqr_blas_cmax.h +93 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels.h +76 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_avx2.cpp +52 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_avx512.cpp +52 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_neon.cpp +48 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum-avx2.h +44 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum-avx512.h +43 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum.h +38 -0
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +54 -15
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +38 -21
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_vpopcnt.cpp +51 -14
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +297 -10
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_sve.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_levels.cpp +19 -3
- data/vendor/faiss/faiss/utils/simd_levels.h +74 -1
- data/vendor/faiss/faiss/utils/transpose/transpose-avx2-inl.h +0 -4
- data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +0 -4
- data/vendor/faiss/faiss/utils/utils.cpp +80 -0
- data/vendor/faiss/faiss/utils/utils.h +24 -0
- metadata +33 -1
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
#ifdef COMPILE_SIMD_AVX2
|
|
9
|
-
|
|
10
8
|
#include <faiss/impl/simdlib/simdlib_avx2.h>
|
|
11
9
|
|
|
12
10
|
#include <cstring>
|
|
@@ -16,6 +14,8 @@
|
|
|
16
14
|
#include <faiss/impl/scalar_quantizer/quantizers.h>
|
|
17
15
|
#include <faiss/impl/scalar_quantizer/scanners.h>
|
|
18
16
|
#include <faiss/impl/scalar_quantizer/similarities.h>
|
|
17
|
+
#include <faiss/impl/scalar_quantizer/sq8_coefficients.h>
|
|
18
|
+
#include <faiss/utils/simd_impl/masked_sum-avx2.h>
|
|
19
19
|
|
|
20
20
|
namespace faiss {
|
|
21
21
|
|
|
@@ -236,13 +236,14 @@ struct QuantizerTemplate<
|
|
|
236
236
|
**********************************************************/
|
|
237
237
|
|
|
238
238
|
// 1-bit MSE: boundary is always at centroids midpoint.
|
|
239
|
-
// Encode: 8 comparisons → 1 byte via movemask.
|
|
239
|
+
// Encode: 8 comparisons → 1 byte via movemask. NLT_UQ is !(x < b), matching
|
|
240
|
+
// the scalar upper_bound tie-break: x == b (and NaN) encodes to the upper bin.
|
|
240
241
|
// Decode: gather 8 centroids via index unpack.
|
|
241
242
|
// NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization,facebook-hte-ShadowingClass)
|
|
242
243
|
template <>
|
|
243
244
|
struct QuantizerLloydMax<1, SIMDLevel::AVX2>
|
|
244
|
-
:
|
|
245
|
-
using Base =
|
|
245
|
+
: QuantizerLloydMaxBase<1, SIMDLevel::AVX2> {
|
|
246
|
+
using Base = QuantizerLloydMaxBase<1, SIMDLevel::AVX2>;
|
|
246
247
|
|
|
247
248
|
QuantizerLloydMax(size_t d, const std::vector<float>& trained)
|
|
248
249
|
: Base(d, trained) {
|
|
@@ -260,7 +261,7 @@ struct QuantizerLloydMax<1, SIMDLevel::AVX2>
|
|
|
260
261
|
for (size_t i = 0; i < this->d; i += 8) {
|
|
261
262
|
__m256 vals = _mm256_loadu_ps(x + i);
|
|
262
263
|
int mask = _mm256_movemask_ps(
|
|
263
|
-
_mm256_cmp_ps(vals, boundary,
|
|
264
|
+
_mm256_cmp_ps(vals, boundary, _CMP_NLT_UQ));
|
|
264
265
|
code[i / 8] = static_cast<uint8_t>(mask);
|
|
265
266
|
}
|
|
266
267
|
}
|
|
@@ -280,8 +281,8 @@ struct QuantizerLloydMax<1, SIMDLevel::AVX2>
|
|
|
280
281
|
// NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization,facebook-hte-ShadowingClass)
|
|
281
282
|
template <>
|
|
282
283
|
struct QuantizerLloydMax<2, SIMDLevel::AVX2>
|
|
283
|
-
:
|
|
284
|
-
using Base =
|
|
284
|
+
: QuantizerLloydMaxBase<2, SIMDLevel::AVX2> {
|
|
285
|
+
using Base = QuantizerLloydMaxBase<2, SIMDLevel::AVX2>;
|
|
285
286
|
|
|
286
287
|
QuantizerLloydMax(size_t d, const std::vector<float>& trained)
|
|
287
288
|
: Base(d, trained) {
|
|
@@ -295,7 +296,8 @@ struct QuantizerLloydMax<2, SIMDLevel::AVX2>
|
|
|
295
296
|
}
|
|
296
297
|
|
|
297
298
|
void encode_vector(const float* x, uint8_t* code) const final {
|
|
298
|
-
// 3 boundaries → branchless: idx = (x
|
|
299
|
+
// 3 boundaries → branchless: idx = !(x<b0) + !(x<b1) + !(x<b2),
|
|
300
|
+
// matching the scalar upper_bound tie-break.
|
|
299
301
|
// _mm256_cmp_ps returns all-ones (-1 as int32) for true,
|
|
300
302
|
// so we negate the sum to get positive indices.
|
|
301
303
|
__m256 b0 = _mm256_set1_ps(this->boundaries[0]);
|
|
@@ -303,16 +305,16 @@ struct QuantizerLloydMax<2, SIMDLevel::AVX2>
|
|
|
303
305
|
__m256 b2 = _mm256_set1_ps(this->boundaries[2]);
|
|
304
306
|
for (size_t i = 0; i < this->d; i += 8) {
|
|
305
307
|
__m256 vals = _mm256_loadu_ps(x + i);
|
|
306
|
-
__m256i
|
|
307
|
-
_mm256_castps_si256(_mm256_cmp_ps(vals, b0,
|
|
308
|
-
__m256i
|
|
309
|
-
_mm256_castps_si256(_mm256_cmp_ps(vals, b1,
|
|
310
|
-
__m256i
|
|
311
|
-
_mm256_castps_si256(_mm256_cmp_ps(vals, b2,
|
|
312
|
-
// Each
|
|
308
|
+
__m256i ge0 =
|
|
309
|
+
_mm256_castps_si256(_mm256_cmp_ps(vals, b0, _CMP_NLT_UQ));
|
|
310
|
+
__m256i ge1 =
|
|
311
|
+
_mm256_castps_si256(_mm256_cmp_ps(vals, b1, _CMP_NLT_UQ));
|
|
312
|
+
__m256i ge2 =
|
|
313
|
+
_mm256_castps_si256(_mm256_cmp_ps(vals, b2, _CMP_NLT_UQ));
|
|
314
|
+
// Each ge is 0 or -1 (0xFFFFFFFF). Sum = -(index).
|
|
313
315
|
__m256i idx = _mm256_sub_epi32(
|
|
314
316
|
_mm256_setzero_si256(),
|
|
315
|
-
_mm256_add_epi32(_mm256_add_epi32(
|
|
317
|
+
_mm256_add_epi32(_mm256_add_epi32(ge0, ge1), ge2));
|
|
316
318
|
// Pack 8 x 2-bit indices into 2 bytes.
|
|
317
319
|
// Store to temp array and pack scalarly - faster than
|
|
318
320
|
// extract+permute.
|
|
@@ -339,8 +341,8 @@ struct QuantizerLloydMax<2, SIMDLevel::AVX2>
|
|
|
339
341
|
#define DEFINE_LLOYD_MAX_AVX2_MULTIBIT(NBITS, UNPACK_EXPR) \
|
|
340
342
|
template <> \
|
|
341
343
|
struct QuantizerLloydMax<NBITS, SIMDLevel::AVX2> \
|
|
342
|
-
:
|
|
343
|
-
using Base =
|
|
344
|
+
: QuantizerLloydMaxBase<NBITS, SIMDLevel::AVX2> { \
|
|
345
|
+
using Base = QuantizerLloydMaxBase<NBITS, SIMDLevel::AVX2>; \
|
|
344
346
|
\
|
|
345
347
|
QuantizerLloydMax(size_t d, const std::vector<float>& trained) \
|
|
346
348
|
: Base(d, trained) { \
|
|
@@ -370,8 +372,8 @@ DEFINE_LLOYD_MAX_AVX2_MULTIBIT(4, unpack_8x4bit_to_u32(code, i));
|
|
|
370
372
|
// 8-bit Lloyd-Max: indices are raw bytes, no bit packing.
|
|
371
373
|
template <>
|
|
372
374
|
struct QuantizerLloydMax<8, SIMDLevel::AVX2>
|
|
373
|
-
:
|
|
374
|
-
using Base =
|
|
375
|
+
: QuantizerLloydMaxBase<8, SIMDLevel::AVX2> {
|
|
376
|
+
using Base = QuantizerLloydMaxBase<8, SIMDLevel::AVX2>;
|
|
375
377
|
|
|
376
378
|
QuantizerLloydMax(size_t d, const std::vector<float>& trained)
|
|
377
379
|
: Base(d, trained) {
|
|
@@ -401,9 +403,9 @@ struct QuantizerLloydMax<8, SIMDLevel::AVX2>
|
|
|
401
403
|
**********************************************************/
|
|
402
404
|
|
|
403
405
|
template <>
|
|
404
|
-
struct QuantizerFP16<SIMDLevel::AVX2> :
|
|
406
|
+
struct QuantizerFP16<SIMDLevel::AVX2> : QuantizerFP16Base<SIMDLevel::AVX2> {
|
|
405
407
|
QuantizerFP16(size_t d, const std::vector<float>& trained)
|
|
406
|
-
:
|
|
408
|
+
: QuantizerFP16Base<SIMDLevel::AVX2>(d, trained) {
|
|
407
409
|
assert(d % 8 == 0);
|
|
408
410
|
}
|
|
409
411
|
|
|
@@ -419,9 +421,9 @@ struct QuantizerFP16<SIMDLevel::AVX2> : QuantizerFP16<SIMDLevel::NONE> {
|
|
|
419
421
|
**********************************************************/
|
|
420
422
|
|
|
421
423
|
template <>
|
|
422
|
-
struct QuantizerBF16<SIMDLevel::AVX2> :
|
|
424
|
+
struct QuantizerBF16<SIMDLevel::AVX2> : QuantizerBF16Base<SIMDLevel::AVX2> {
|
|
423
425
|
QuantizerBF16(size_t d, const std::vector<float>& trained)
|
|
424
|
-
:
|
|
426
|
+
: QuantizerBF16Base<SIMDLevel::AVX2>(d, trained) {
|
|
425
427
|
assert(d % 8 == 0);
|
|
426
428
|
}
|
|
427
429
|
|
|
@@ -440,9 +442,9 @@ struct QuantizerBF16<SIMDLevel::AVX2> : QuantizerBF16<SIMDLevel::NONE> {
|
|
|
440
442
|
|
|
441
443
|
template <>
|
|
442
444
|
struct Quantizer8bitDirect<SIMDLevel::AVX2>
|
|
443
|
-
:
|
|
445
|
+
: Quantizer8bitDirectBase<SIMDLevel::AVX2> {
|
|
444
446
|
Quantizer8bitDirect(size_t d, const std::vector<float>& trained)
|
|
445
|
-
:
|
|
447
|
+
: Quantizer8bitDirectBase<SIMDLevel::AVX2>(d, trained) {
|
|
446
448
|
assert(d % 8 == 0);
|
|
447
449
|
}
|
|
448
450
|
|
|
@@ -460,9 +462,9 @@ struct Quantizer8bitDirect<SIMDLevel::AVX2>
|
|
|
460
462
|
|
|
461
463
|
template <>
|
|
462
464
|
struct Quantizer8bitDirectSigned<SIMDLevel::AVX2>
|
|
463
|
-
:
|
|
465
|
+
: Quantizer8bitDirectSignedBase<SIMDLevel::AVX2> {
|
|
464
466
|
Quantizer8bitDirectSigned(size_t d, const std::vector<float>& trained)
|
|
465
|
-
:
|
|
467
|
+
: Quantizer8bitDirectSignedBase<SIMDLevel::AVX2>(d, trained) {
|
|
466
468
|
assert(d % 8 == 0);
|
|
467
469
|
}
|
|
468
470
|
|
|
@@ -602,8 +604,18 @@ struct SimilarityIP<SIMDLevel::AVX2> {
|
|
|
602
604
|
* Distance computers
|
|
603
605
|
**********************************************************/
|
|
604
606
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
+
namespace {
|
|
608
|
+
|
|
609
|
+
/// 8 lanes to 4: lanes j and j + 4 summed into lane j.
|
|
610
|
+
FAISS_ALWAYS_INLINE __m128 reduce_8_to_4(__m256 a) {
|
|
611
|
+
return _mm_add_ps(_mm256_castps256_ps128(a), _mm256_extractf128_ps(a, 1));
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
} // namespace
|
|
615
|
+
|
|
616
|
+
template <class Quantizer, class Similarity, bool four_acc>
|
|
617
|
+
struct DCTemplate<Quantizer, Similarity, SIMDLevel::AVX2, four_acc>
|
|
618
|
+
: SQDistanceComputer {
|
|
607
619
|
using Sim = Similarity;
|
|
608
620
|
|
|
609
621
|
Quantizer quant;
|
|
@@ -626,7 +638,40 @@ struct DCTemplate<Quantizer, Similarity, SIMDLevel::AVX2> : SQDistanceComputer {
|
|
|
626
638
|
}
|
|
627
639
|
}
|
|
628
640
|
|
|
641
|
+
/// Similarity terms of one code with four accumulators.
|
|
642
|
+
FAISS_ALWAYS_INLINE __m256
|
|
643
|
+
accumulate_4(const float* x, const uint8_t* code) const {
|
|
644
|
+
struct Acc : Similarity {
|
|
645
|
+
Acc() : Similarity(nullptr) {}
|
|
646
|
+
};
|
|
647
|
+
Acc s[4];
|
|
648
|
+
for (int j = 0; j < 4; j++) {
|
|
649
|
+
s[j].begin_8();
|
|
650
|
+
}
|
|
651
|
+
const size_t d = quant.d;
|
|
652
|
+
size_t i = 0;
|
|
653
|
+
for (; i + 32 <= d; i += 32) {
|
|
654
|
+
for (int j = 0; j < 4; j++) {
|
|
655
|
+
s[j].add_8_components_2(
|
|
656
|
+
quant.reconstruct_8_components(
|
|
657
|
+
code, static_cast<int>(i + 8 * j)),
|
|
658
|
+
simd8float32(x + i + 8 * j));
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
for (; i < d; i += 8) {
|
|
662
|
+
s[0].add_8_components_2(
|
|
663
|
+
quant.reconstruct_8_components(code, static_cast<int>(i)),
|
|
664
|
+
simd8float32(x + i));
|
|
665
|
+
}
|
|
666
|
+
return _mm256_add_ps(
|
|
667
|
+
_mm256_add_ps(s[0].accu8.f, s[1].accu8.f),
|
|
668
|
+
_mm256_add_ps(s[2].accu8.f, s[3].accu8.f));
|
|
669
|
+
}
|
|
670
|
+
|
|
629
671
|
float compute_distance(const float* x, const uint8_t* code) const {
|
|
672
|
+
if constexpr (four_acc) {
|
|
673
|
+
return reduce_4(reduce_8_to_4(accumulate_4(x, code)));
|
|
674
|
+
}
|
|
630
675
|
Similarity sim(x);
|
|
631
676
|
sim.begin_8();
|
|
632
677
|
for (size_t i = 0; i < quant.d; i += 8) {
|
|
@@ -697,6 +742,21 @@ struct DCTemplate<Quantizer, Similarity, SIMDLevel::AVX2> : SQDistanceComputer {
|
|
|
697
742
|
float& dis1,
|
|
698
743
|
float& dis2,
|
|
699
744
|
float& dis3) const final {
|
|
745
|
+
if constexpr (four_acc) {
|
|
746
|
+
alignas(16) float dis[4];
|
|
747
|
+
_mm_store_ps(
|
|
748
|
+
dis,
|
|
749
|
+
reduce_4x4(
|
|
750
|
+
reduce_8_to_4(accumulate_4(q, code_0)),
|
|
751
|
+
reduce_8_to_4(accumulate_4(q, code_1)),
|
|
752
|
+
reduce_8_to_4(accumulate_4(q, code_2)),
|
|
753
|
+
reduce_8_to_4(accumulate_4(q, code_3))));
|
|
754
|
+
dis0 = dis[0];
|
|
755
|
+
dis1 = dis[1];
|
|
756
|
+
dis2 = dis[2];
|
|
757
|
+
dis3 = dis[3];
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
700
760
|
Similarity sim0(q);
|
|
701
761
|
Similarity sim1(q);
|
|
702
762
|
Similarity sim2(q);
|
|
@@ -726,6 +786,141 @@ struct DCTemplate<Quantizer, Similarity, SIMDLevel::AVX2> : SQDistanceComputer {
|
|
|
726
786
|
}
|
|
727
787
|
};
|
|
728
788
|
|
|
789
|
+
// QT_8bit + IP. With a, rmin from sq8_coefficients.h,
|
|
790
|
+
// <q, reconstruct(c)> = sum_i q_i * rmin_i + sum_i (q_i * a_i) * c_i.
|
|
791
|
+
// set_query folds the first sum into bias and the products into qa, so each
|
|
792
|
+
// 8 dims cost one convert and one FMA instead of the decode, vmin/vdiff and
|
|
793
|
+
// query FMAs.
|
|
794
|
+
template <bool four_acc>
|
|
795
|
+
struct DCTemplate<
|
|
796
|
+
QuantizerTemplate<
|
|
797
|
+
Codec8bit<SIMDLevel::AVX2>,
|
|
798
|
+
QuantizerTemplateScaling::NON_UNIFORM,
|
|
799
|
+
SIMDLevel::AVX2>,
|
|
800
|
+
SimilarityIP<SIMDLevel::AVX2>,
|
|
801
|
+
SIMDLevel::AVX2,
|
|
802
|
+
four_acc> : SQDistanceComputer {
|
|
803
|
+
using Quantizer = QuantizerTemplate<
|
|
804
|
+
Codec8bit<SIMDLevel::AVX2>,
|
|
805
|
+
QuantizerTemplateScaling::NON_UNIFORM,
|
|
806
|
+
SIMDLevel::AVX2>;
|
|
807
|
+
using Sim = SimilarityIP<SIMDLevel::AVX2>;
|
|
808
|
+
|
|
809
|
+
Quantizer quant;
|
|
810
|
+
std::vector<float> a, rmin, qa;
|
|
811
|
+
float bias = 0;
|
|
812
|
+
|
|
813
|
+
DCTemplate(size_t d, const std::vector<float>& trained)
|
|
814
|
+
: quant(d, trained), a(d), rmin(d), qa(d) {
|
|
815
|
+
sq8::make_coefficients(trained.data(), d, a.data(), rmin.data());
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
void set_query(const float* x) final {
|
|
819
|
+
q = x;
|
|
820
|
+
bias = 0;
|
|
821
|
+
for (size_t i = 0; i < quant.d; i++) {
|
|
822
|
+
qa[i] = x[i] * a[i];
|
|
823
|
+
bias += x[i] * rmin[i];
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
static FAISS_ALWAYS_INLINE __m256 codes_8(const uint8_t* code) {
|
|
828
|
+
return _mm256_cvtepi32_ps(
|
|
829
|
+
_mm256_cvtepu8_epi32(_mm_loadl_epi64((const __m128i*)code)));
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/// sum_i qa[i] * code[i] of N codes, in 4 lanes each. The N codes share
|
|
833
|
+
/// each qa load. With four_acc, dims i + 8 * j of each 32 go to
|
|
834
|
+
/// accumulator j of the code, so a code sums the same way for any N.
|
|
835
|
+
template <size_t N>
|
|
836
|
+
FAISS_ALWAYS_INLINE void accumulate(
|
|
837
|
+
const uint8_t* const* codes,
|
|
838
|
+
__m128* sums) const {
|
|
839
|
+
constexpr size_t n_acc = four_acc ? 4 : 1;
|
|
840
|
+
__m256 acc[N][n_acc];
|
|
841
|
+
for (size_t n = 0; n < N; n++) {
|
|
842
|
+
for (size_t j = 0; j < n_acc; j++) {
|
|
843
|
+
acc[n][j] = _mm256_setzero_ps();
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
const size_t d = quant.d;
|
|
847
|
+
size_t i = 0;
|
|
848
|
+
if constexpr (four_acc) {
|
|
849
|
+
for (; i + 32 <= d; i += 32) {
|
|
850
|
+
for (size_t j = 0; j < 4; j++) {
|
|
851
|
+
const __m256 qa8 = _mm256_loadu_ps(qa.data() + i + 8 * j);
|
|
852
|
+
for (size_t n = 0; n < N; n++) {
|
|
853
|
+
acc[n][j] = _mm256_fmadd_ps(
|
|
854
|
+
qa8, codes_8(codes[n] + i + 8 * j), acc[n][j]);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
for (; i < d; i += 8) {
|
|
860
|
+
const __m256 qa8 = _mm256_loadu_ps(qa.data() + i);
|
|
861
|
+
for (size_t n = 0; n < N; n++) {
|
|
862
|
+
acc[n][0] =
|
|
863
|
+
_mm256_fmadd_ps(qa8, codes_8(codes[n] + i), acc[n][0]);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
for (size_t n = 0; n < N; n++) {
|
|
867
|
+
__m256 sum = acc[n][0];
|
|
868
|
+
if constexpr (four_acc) {
|
|
869
|
+
sum = _mm256_add_ps(
|
|
870
|
+
_mm256_add_ps(acc[n][0], acc[n][1]),
|
|
871
|
+
_mm256_add_ps(acc[n][2], acc[n][3]));
|
|
872
|
+
}
|
|
873
|
+
sums[n] = reduce_8_to_4(sum);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
float query_to_code(const uint8_t* code) const final {
|
|
878
|
+
__m128 sum;
|
|
879
|
+
accumulate<1>(&code, &sum);
|
|
880
|
+
return bias + reduce_4(sum);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
void query_to_codes_batch_4(
|
|
884
|
+
const uint8_t* code_0,
|
|
885
|
+
const uint8_t* code_1,
|
|
886
|
+
const uint8_t* code_2,
|
|
887
|
+
const uint8_t* code_3,
|
|
888
|
+
float& dis0,
|
|
889
|
+
float& dis1,
|
|
890
|
+
float& dis2,
|
|
891
|
+
float& dis3) const final {
|
|
892
|
+
const uint8_t* codes[4] = {code_0, code_1, code_2, code_3};
|
|
893
|
+
__m128 sums[4];
|
|
894
|
+
if constexpr (four_acc) {
|
|
895
|
+
// 16 accumulators would take all 16 AVX2 registers.
|
|
896
|
+
accumulate<2>(codes, sums);
|
|
897
|
+
accumulate<2>(codes + 2, sums + 2);
|
|
898
|
+
} else {
|
|
899
|
+
accumulate<4>(codes, sums);
|
|
900
|
+
}
|
|
901
|
+
alignas(16) float dis[4];
|
|
902
|
+
_mm_store_ps(dis, reduce_4x4(sums[0], sums[1], sums[2], sums[3]));
|
|
903
|
+
dis0 = bias + dis[0];
|
|
904
|
+
dis1 = bias + dis[1];
|
|
905
|
+
dis2 = bias + dis[2];
|
|
906
|
+
dis3 = bias + dis[3];
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
float symmetric_dis(idx_t i, idx_t j) override {
|
|
910
|
+
const uint8_t* c1 = codes + i * code_size;
|
|
911
|
+
const uint8_t* c2 = codes + j * code_size;
|
|
912
|
+
Sim sim(nullptr);
|
|
913
|
+
sim.begin_8();
|
|
914
|
+
for (size_t k = 0; k < quant.d; k += 8) {
|
|
915
|
+
const int kk = static_cast<int>(k);
|
|
916
|
+
sim.add_8_components_2(
|
|
917
|
+
quant.reconstruct_8_components(c1, kk),
|
|
918
|
+
quant.reconstruct_8_components(c2, kk));
|
|
919
|
+
}
|
|
920
|
+
return sim.result_8();
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
|
|
729
924
|
template <class Similarity>
|
|
730
925
|
struct DistanceComputerByte<Similarity, SIMDLevel::AVX2> : SQDistanceComputer {
|
|
731
926
|
using Sim = Similarity;
|
|
@@ -853,54 +1048,8 @@ struct DistanceComputerByteSigned<Similarity, SIMDLevel::AVX2>
|
|
|
853
1048
|
}
|
|
854
1049
|
};
|
|
855
1050
|
|
|
856
|
-
/**********************************************************
|
|
857
|
-
* TurboQuant masked_sum AVX2 specialization
|
|
858
|
-
**********************************************************/
|
|
859
|
-
|
|
860
|
-
template <SIMDLevel SL0>
|
|
861
|
-
float turboq_masked_sum(const float* arr, const uint8_t* bits, size_t d);
|
|
862
|
-
|
|
863
|
-
template <>
|
|
864
|
-
float turboq_masked_sum<SIMDLevel::AVX2>(
|
|
865
|
-
const float* arr,
|
|
866
|
-
const uint8_t* bits,
|
|
867
|
-
size_t d) {
|
|
868
|
-
const __m256i bit_masks = _mm256_set_epi32(128, 64, 32, 16, 8, 4, 2, 1);
|
|
869
|
-
__m256 acc = _mm256_setzero_ps();
|
|
870
|
-
size_t full_bytes = d / 8;
|
|
871
|
-
for (size_t byte_idx = 0; byte_idx < full_bytes; byte_idx++) {
|
|
872
|
-
__m256i byte_broadcast =
|
|
873
|
-
_mm256_set1_epi32(static_cast<int>(bits[byte_idx]));
|
|
874
|
-
__m256i masked = _mm256_and_si256(byte_broadcast, bit_masks);
|
|
875
|
-
__m256i cmp = _mm256_cmpeq_epi32(masked, bit_masks);
|
|
876
|
-
__m256 mask = _mm256_castsi256_ps(cmp);
|
|
877
|
-
__m256 vals = _mm256_loadu_ps(arr + byte_idx * 8);
|
|
878
|
-
acc = _mm256_add_ps(acc, _mm256_and_ps(mask, vals));
|
|
879
|
-
}
|
|
880
|
-
__m128 hi = _mm256_extractf128_ps(acc, 1);
|
|
881
|
-
__m128 lo = _mm256_castps256_ps128(acc);
|
|
882
|
-
__m128 sum128 = _mm_add_ps(lo, hi);
|
|
883
|
-
__m128 shuf = _mm_movehdup_ps(sum128);
|
|
884
|
-
__m128 sums = _mm_add_ps(sum128, shuf);
|
|
885
|
-
shuf = _mm_movehl_ps(shuf, sums);
|
|
886
|
-
sums = _mm_add_ss(sums, shuf);
|
|
887
|
-
float result = _mm_cvtss_f32(sums);
|
|
888
|
-
size_t tail_start = full_bytes * 8;
|
|
889
|
-
if (tail_start < d) {
|
|
890
|
-
uint8_t last_byte = bits[full_bytes];
|
|
891
|
-
for (size_t j = tail_start; j < d; j++) {
|
|
892
|
-
if (last_byte & (1 << (j - tail_start))) {
|
|
893
|
-
result += arr[j];
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
return result;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
1051
|
} // namespace scalar_quantizer
|
|
901
1052
|
} // namespace faiss
|
|
902
1053
|
|
|
903
1054
|
#define THE_LEVEL_TO_DISPATCH SIMDLevel::AVX2
|
|
904
1055
|
#include <faiss/impl/scalar_quantizer/sq-dispatch.h>
|
|
905
|
-
|
|
906
|
-
#endif // COMPILE_SIMD_AVX2
|