faiss 0.6.2 → 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 +4 -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 +4 -5
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +2 -4
- 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 +10 -11
- data/vendor/faiss/faiss/IndexIDMap.cpp +16 -3
- data/vendor/faiss/faiss/IndexIDMap.h +2 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +17 -6
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +1 -1
- 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 +3 -4
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +40 -22
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +19 -49
- 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 +9 -2
- data/vendor/faiss/faiss/IndexNSG.cpp +7 -2
- 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/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/factory_tools.cpp +47 -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/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/MetalIndexIVFFlat.h +1 -5
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -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 +109 -152
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/impl/NSG.cpp +3 -1
- data/vendor/faiss/faiss/impl/Panorama.h +9 -7
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +34 -22
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +44 -36
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +168 -67
- 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 +25 -31
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +258 -57
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +20 -0
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
- data/vendor/faiss/faiss/impl/VisitedTable.cpp +22 -2
- data/vendor/faiss/faiss/impl/VisitedTable.h +20 -0
- 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 +35 -2
- data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
- data/vendor/faiss/faiss/impl/index_read.cpp +376 -36
- data/vendor/faiss/faiss/impl/index_write.cpp +55 -4
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
- data/vendor/faiss/faiss/impl/platform_macros.h +3 -1
- 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 +4 -4
- 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/quantizers.h +9 -8
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +85 -23
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +30 -30
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +4 -5
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +101 -34
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +136 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +16 -16
- data/vendor/faiss/faiss/impl/simd_dispatch.h +30 -9
- data/vendor/faiss/faiss/index_factory.cpp +32 -6
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +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 +31 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +15 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +1 -2
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
- data/vendor/faiss/faiss/utils/distances.cpp +14 -2
- data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -3
- 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 +1 -1
- 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/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 +92 -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 +44 -0
- data/vendor/faiss/faiss/utils/simd_levels.h +14 -0
- data/vendor/faiss/faiss/utils/utils.cpp +9 -27
- metadata +16 -1
|
@@ -25,11 +25,13 @@
|
|
|
25
25
|
#include <faiss/Index2Layer.h>
|
|
26
26
|
#include <faiss/IndexAdditiveQuantizer.h>
|
|
27
27
|
#include <faiss/IndexAdditiveQuantizerFastScan.h>
|
|
28
|
+
#include <faiss/IndexEDEN.h>
|
|
28
29
|
#include <faiss/IndexFlat.h>
|
|
29
30
|
#include <faiss/IndexHNSW.h>
|
|
30
31
|
#include <faiss/IndexIVF.h>
|
|
31
32
|
#include <faiss/IndexIVFAdditiveQuantizer.h>
|
|
32
33
|
#include <faiss/IndexIVFAdditiveQuantizerFastScan.h>
|
|
34
|
+
#include <faiss/IndexIVFEDEN.h>
|
|
33
35
|
#include <faiss/IndexIVFFlat.h>
|
|
34
36
|
#include <faiss/IndexIVFFlatPanorama.h>
|
|
35
37
|
#include <faiss/IndexIVFIndependentQuantizer.h>
|
|
@@ -63,6 +65,7 @@
|
|
|
63
65
|
#include <faiss/IndexScalarQuantizer.h>
|
|
64
66
|
#include <faiss/MetaIndexes.h>
|
|
65
67
|
#include <faiss/VectorTransform.h>
|
|
68
|
+
#include <faiss/impl/EDENQuantizer.h>
|
|
66
69
|
|
|
67
70
|
#include <faiss/IndexBinaryFlat.h>
|
|
68
71
|
#include <faiss/IndexBinaryFromFloat.h>
|
|
@@ -439,6 +442,20 @@ static void write_RaBitQuantizer(
|
|
|
439
442
|
}
|
|
440
443
|
}
|
|
441
444
|
|
|
445
|
+
static void write_EDENScalarQuantizer(
|
|
446
|
+
const ScalarQuantizer* sq,
|
|
447
|
+
MetricType metric_type,
|
|
448
|
+
EDENScaleType scale_type,
|
|
449
|
+
size_t full_code_size,
|
|
450
|
+
IOWriter* f) {
|
|
451
|
+
WRITE1(sq->d);
|
|
452
|
+
WRITE1(full_code_size);
|
|
453
|
+
WRITE1(metric_type);
|
|
454
|
+
WRITE1(sq->bits);
|
|
455
|
+
int scale_type_int = static_cast<int>(scale_type);
|
|
456
|
+
WRITE1(scale_type_int);
|
|
457
|
+
}
|
|
458
|
+
|
|
442
459
|
static void write_direct_map(const DirectMap* dm, IOWriter* f) {
|
|
443
460
|
char maintain_direct_map =
|
|
444
461
|
(char)dm->type; // for backwards compatibility with bool
|
|
@@ -871,8 +888,12 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
|
871
888
|
: dynamic_cast<const IndexHNSWSQ*>(idx) ? fourcc("IHNs")
|
|
872
889
|
: dynamic_cast<const IndexHNSW2Level*>(idx) ? fourcc("IHN2")
|
|
873
890
|
: dynamic_cast<const IndexHNSWCagra*>(idx) ? fourcc("IHc2")
|
|
891
|
+
: typeid(*idx) == typeid(IndexHNSW) ? fourcc("IH00")
|
|
874
892
|
: 0;
|
|
875
|
-
|
|
893
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
894
|
+
h != 0,
|
|
895
|
+
"don't know how to serialize this IndexHNSW subtype: %s",
|
|
896
|
+
typeid(*idx).name());
|
|
876
897
|
WRITE1(h);
|
|
877
898
|
write_index_header(idxhnsw, f);
|
|
878
899
|
if (h == fourcc("IHfP")) {
|
|
@@ -900,7 +921,8 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
|
900
921
|
: dynamic_cast<const IndexNSGPQ*>(idx) ? fourcc("INSp")
|
|
901
922
|
: dynamic_cast<const IndexNSGSQ*>(idx) ? fourcc("INSs")
|
|
902
923
|
: 0;
|
|
903
|
-
|
|
924
|
+
FAISS_THROW_IF_MSG(
|
|
925
|
+
h == 0, "don't know how to serialize this IndexNSG subtype");
|
|
904
926
|
WRITE1(h);
|
|
905
927
|
write_index_header(idxnsg, f);
|
|
906
928
|
WRITE1(idxnsg->GK);
|
|
@@ -915,9 +937,11 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
|
915
937
|
const IndexNNDescent* idxnnd =
|
|
916
938
|
dynamic_cast<const IndexNNDescent*>(idx)) {
|
|
917
939
|
auto idxnndflat = dynamic_cast<const IndexNNDescentFlat*>(idx);
|
|
918
|
-
FAISS_THROW_IF_NOT(idxnndflat
|
|
940
|
+
FAISS_THROW_IF_NOT(idxnndflat);
|
|
919
941
|
uint32_t h = fourcc("INNf");
|
|
920
|
-
|
|
942
|
+
FAISS_THROW_IF_MSG(
|
|
943
|
+
h == 0,
|
|
944
|
+
"don't know how to serialize this IndexNNDescent subtype");
|
|
921
945
|
WRITE1(h);
|
|
922
946
|
write_index_header(idxnnd, f);
|
|
923
947
|
write_NNDescent(&idxnnd->nndescent, f);
|
|
@@ -965,6 +989,33 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
|
965
989
|
WRITE1(h);
|
|
966
990
|
write_index_header(imm_2, f);
|
|
967
991
|
write_index(imm_2->index, f);
|
|
992
|
+
} else if (const IndexEDEN* idxe = dynamic_cast<const IndexEDEN*>(idx)) {
|
|
993
|
+
uint32_t h = fourcc("IxEe");
|
|
994
|
+
WRITE1(h);
|
|
995
|
+
write_index_header(idx, f);
|
|
996
|
+
write_EDENScalarQuantizer(
|
|
997
|
+
&idxe->sq,
|
|
998
|
+
idxe->metric_type,
|
|
999
|
+
idxe->scale_type,
|
|
1000
|
+
idxe->code_size,
|
|
1001
|
+
f);
|
|
1002
|
+
WRITEVECTOR(idxe->codes);
|
|
1003
|
+
WRITEVECTOR(idxe->center);
|
|
1004
|
+
} else if (
|
|
1005
|
+
const IndexIVFEDEN* iveden =
|
|
1006
|
+
dynamic_cast<const IndexIVFEDEN*>(idx)) {
|
|
1007
|
+
uint32_t h = fourcc("IwEe");
|
|
1008
|
+
WRITE1(h);
|
|
1009
|
+
write_ivf_header(iveden, f);
|
|
1010
|
+
write_EDENScalarQuantizer(
|
|
1011
|
+
&iveden->sq,
|
|
1012
|
+
iveden->metric_type,
|
|
1013
|
+
iveden->scale_type,
|
|
1014
|
+
iveden->code_size,
|
|
1015
|
+
f);
|
|
1016
|
+
WRITE1(iveden->code_size);
|
|
1017
|
+
WRITE1(iveden->by_residual);
|
|
1018
|
+
write_InvertedLists(iveden->invlists, f);
|
|
968
1019
|
} else if (
|
|
969
1020
|
const IndexRaBitQFastScan* idxqfs =
|
|
970
1021
|
dynamic_cast<const IndexRaBitQFastScan*>(idx)) {
|
|
@@ -557,12 +557,11 @@ ZnSphereCodecRec::ZnSphereCodecRec(int dim_in, int r2_in)
|
|
|
557
557
|
|
|
558
558
|
decode_cache.resize((r2 + 1));
|
|
559
559
|
|
|
560
|
-
// The decode cache stores total_cache_entries * dimsub floats
|
|
561
|
-
//
|
|
562
|
-
//
|
|
563
|
-
//
|
|
564
|
-
//
|
|
565
|
-
// O(r2^2) growth of nv_cum.
|
|
560
|
+
// The decode cache stores total_cache_entries * dimsub floats and is
|
|
561
|
+
// built with one decode() call per entry. The entry count grows as the
|
|
562
|
+
// number of lattice points in dimension 2^cache_level, which is
|
|
563
|
+
// O(r2^(dim/2)) -- much faster than the O(r2^2) growth of nv_cum, so it
|
|
564
|
+
// is bounded per-r2sub in the loop below.
|
|
566
565
|
size_t total_cache_entries = 0;
|
|
567
566
|
int dimsub = (1 << cache_level);
|
|
568
567
|
|
|
@@ -571,9 +570,9 @@ ZnSphereCodecRec::ZnSphereCodecRec(int dim_in, int r2_in)
|
|
|
571
570
|
uint64_t nvi = get_nv(ld, r2sub);
|
|
572
571
|
total_cache_entries += nvi;
|
|
573
572
|
FAISS_THROW_IF_NOT_MSG(
|
|
574
|
-
total_cache_entries <= (size_t(1) << 27) /
|
|
575
|
-
"ZnSphereCodecRec: r2 too large, decode cache "
|
|
576
|
-
"would require excessive memory");
|
|
573
|
+
total_cache_entries <= (size_t(1) << 27) / (size_t)dim,
|
|
574
|
+
"ZnSphereCodecRec: r2/dim too large, decode cache "
|
|
575
|
+
"would require excessive memory and computation");
|
|
577
576
|
std::vector<float>& cache = decode_cache[r2sub];
|
|
578
577
|
cache.resize(nvi * dimsub);
|
|
579
578
|
std::vector<float> c(dim);
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
|
|
26
26
|
#define strtok_r strtok_s
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
// clang-cl defines _MSC_VER but provides __PRETTY_FUNCTION__ itself, in
|
|
29
|
+
// clang's format. Redefining it there breaks code that parses it.
|
|
30
|
+
#if defined(_MSC_VER) && !defined(__clang__)
|
|
29
31
|
#define __PRETTY_FUNCTION__ __FUNCSIG__
|
|
30
32
|
#endif // _MSC_VER
|
|
31
33
|
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and 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
|
+
#ifdef COMPILE_SIMD_AVX512
|
|
11
|
+
|
|
12
|
+
#include <faiss/impl/PolysemousTraining.h>
|
|
13
|
+
#include <faiss/impl/polysemous_training/dispatch.h>
|
|
14
|
+
#include <faiss/utils/popcount.h>
|
|
15
|
+
|
|
16
|
+
#include <immintrin.h>
|
|
17
|
+
#include <cstdint>
|
|
18
|
+
|
|
19
|
+
namespace faiss {
|
|
20
|
+
namespace {
|
|
21
|
+
|
|
22
|
+
inline int hamming_dis(uint64_t a, uint64_t b) {
|
|
23
|
+
return popcount64(a ^ b);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
inline double sqr(double x) {
|
|
27
|
+
return x * x;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
inline __m512i popcnt_512(__m512i v) {
|
|
31
|
+
#ifdef __AVX512VPOPCNTDQ__
|
|
32
|
+
return _mm512_popcnt_epi64(v);
|
|
33
|
+
#else
|
|
34
|
+
const __m128i nibble_popcount =
|
|
35
|
+
_mm_setr_epi8(0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4);
|
|
36
|
+
const __m512i lookup = _mm512_broadcast_i32x4(nibble_popcount);
|
|
37
|
+
|
|
38
|
+
const __m512i low_mask = _mm512_set1_epi8(0x0f);
|
|
39
|
+
const __m512i lo = _mm512_and_si512(v, low_mask);
|
|
40
|
+
const __m512i hi = _mm512_and_si512(_mm512_srli_epi16(v, 4), low_mask);
|
|
41
|
+
|
|
42
|
+
const __m512i popcnt_lo = _mm512_shuffle_epi8(lookup, lo);
|
|
43
|
+
const __m512i popcnt_hi = _mm512_shuffle_epi8(lookup, hi);
|
|
44
|
+
const __m512i popcnt_bytes = _mm512_add_epi8(popcnt_lo, popcnt_hi);
|
|
45
|
+
|
|
46
|
+
return _mm512_sad_epu8(popcnt_bytes, _mm512_setzero_si512());
|
|
47
|
+
#endif
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
} // namespace
|
|
51
|
+
|
|
52
|
+
namespace polysemous_training {
|
|
53
|
+
|
|
54
|
+
template <>
|
|
55
|
+
double hamming_compute_cost<SIMDLevel::AVX512>(
|
|
56
|
+
int n,
|
|
57
|
+
const int* perm,
|
|
58
|
+
const double* target_dis,
|
|
59
|
+
const double* weights) {
|
|
60
|
+
double total_cost = 0.0;
|
|
61
|
+
for (int i = 0; i < n; i++) {
|
|
62
|
+
__m512d cost_vec = _mm512_setzero_pd();
|
|
63
|
+
const __m512i perm_i_vec = _mm512_set1_epi64(perm[i]);
|
|
64
|
+
const int bro = i * n;
|
|
65
|
+
int j = 0;
|
|
66
|
+
for (; j <= n - 8; j += 8) {
|
|
67
|
+
const __m512d wanted_vec = _mm512_loadu_pd(&target_dis[bro + j]);
|
|
68
|
+
const __m512d w_vec = _mm512_loadu_pd(&weights[bro + j]);
|
|
69
|
+
const __m256i pj32 = _mm256_loadu_si256((__m256i const*)&perm[j]);
|
|
70
|
+
const __m512i pj64 = _mm512_cvtepi32_epi64(pj32);
|
|
71
|
+
const __m512i xor_res = _mm512_xor_si512(perm_i_vec, pj64);
|
|
72
|
+
const __m512d actual_vec = _mm512_cvtepi64_pd(popcnt_512(xor_res));
|
|
73
|
+
const __m512d diff = _mm512_sub_pd(wanted_vec, actual_vec);
|
|
74
|
+
cost_vec =
|
|
75
|
+
_mm512_fmadd_pd(w_vec, _mm512_mul_pd(diff, diff), cost_vec);
|
|
76
|
+
}
|
|
77
|
+
total_cost += _mm512_reduce_add_pd(cost_vec);
|
|
78
|
+
for (; j < n; j++) {
|
|
79
|
+
double wanted = target_dis[bro + j];
|
|
80
|
+
double w = weights[bro + j];
|
|
81
|
+
double actual = hamming_dis(perm[i], perm[j]);
|
|
82
|
+
total_cost += w * sqr(wanted - actual);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return total_cost;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
template <>
|
|
89
|
+
double hamming_cost_update<SIMDLevel::AVX512>(
|
|
90
|
+
int n,
|
|
91
|
+
const int* perm,
|
|
92
|
+
int iw,
|
|
93
|
+
int jw,
|
|
94
|
+
const double* target_dis,
|
|
95
|
+
const double* weights) {
|
|
96
|
+
double delta_cost_scalar = 0;
|
|
97
|
+
const __m512i v_idx_base = _mm512_setr_epi64(0, 1, 2, 3, 4, 5, 6, 7);
|
|
98
|
+
// Loop-invariant across the j-loop and both process_row calls.
|
|
99
|
+
const __m512i v_iw = _mm512_set1_epi64(iw);
|
|
100
|
+
const __m512i v_jw = _mm512_set1_epi64(jw);
|
|
101
|
+
const __m512i v_perm_iw = _mm512_set1_epi64(perm[iw]);
|
|
102
|
+
const __m512i v_perm_jw = _mm512_set1_epi64(perm[jw]);
|
|
103
|
+
__m512d delta_cost_vec = _mm512_setzero_pd();
|
|
104
|
+
|
|
105
|
+
auto process_row = [&](int row, int old_pi, int new_pi) {
|
|
106
|
+
const int bro = row * n;
|
|
107
|
+
const __m512i v_old = _mm512_set1_epi64(old_pi);
|
|
108
|
+
const __m512i v_new = _mm512_set1_epi64(new_pi);
|
|
109
|
+
int j = 0;
|
|
110
|
+
for (; j <= n - 8; j += 8) {
|
|
111
|
+
__m512d wv = _mm512_loadu_pd(&target_dis[bro + j]);
|
|
112
|
+
__m512d ww = _mm512_loadu_pd(&weights[bro + j]);
|
|
113
|
+
__m256i pj32 = _mm256_loadu_si256((__m256i const*)&perm[j]);
|
|
114
|
+
__m512i pjv = _mm512_cvtepi32_epi64(pj32);
|
|
115
|
+
__m512d av = _mm512_cvtepi64_pd(
|
|
116
|
+
popcnt_512(_mm512_xor_si512(v_old, pjv)));
|
|
117
|
+
__m512d to = _mm512_sub_pd(wv, av);
|
|
118
|
+
to = _mm512_mul_pd(to, to);
|
|
119
|
+
delta_cost_vec = _mm512_fnmadd_pd(ww, to, delta_cost_vec);
|
|
120
|
+
|
|
121
|
+
__m512i ji = _mm512_add_epi64(_mm512_set1_epi64(j), v_idx_base);
|
|
122
|
+
__mmask8 miw = _mm512_cmpeq_epi64_mask(ji, v_iw);
|
|
123
|
+
__mmask8 mjw = _mm512_cmpeq_epi64_mask(ji, v_jw);
|
|
124
|
+
__m512i pnj = _mm512_mask_blend_epi64(mjw, pjv, v_perm_iw);
|
|
125
|
+
pnj = _mm512_mask_blend_epi64(miw, pnj, v_perm_jw);
|
|
126
|
+
__m512d nav = _mm512_cvtepi64_pd(
|
|
127
|
+
popcnt_512(_mm512_xor_si512(v_new, pnj)));
|
|
128
|
+
__m512d tn = _mm512_sub_pd(wv, nav);
|
|
129
|
+
tn = _mm512_mul_pd(tn, tn);
|
|
130
|
+
delta_cost_vec = _mm512_fmadd_pd(ww, tn, delta_cost_vec);
|
|
131
|
+
}
|
|
132
|
+
for (; j < n; j++) {
|
|
133
|
+
double wanted = target_dis[bro + j];
|
|
134
|
+
double w = weights[bro + j];
|
|
135
|
+
double actual = hamming_dis(old_pi, perm[j]);
|
|
136
|
+
delta_cost_scalar -= w * sqr(wanted - actual);
|
|
137
|
+
double new_actual = hamming_dis(
|
|
138
|
+
new_pi,
|
|
139
|
+
perm[j == iw ? jw
|
|
140
|
+
: j == jw ? iw
|
|
141
|
+
: j]);
|
|
142
|
+
delta_cost_scalar += w * sqr(wanted - new_actual);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
process_row(iw, perm[iw], perm[jw]);
|
|
146
|
+
process_row(jw, perm[jw], perm[iw]);
|
|
147
|
+
|
|
148
|
+
for (int i = 0; i < n; ++i) {
|
|
149
|
+
if (i == iw || i == jw)
|
|
150
|
+
continue;
|
|
151
|
+
int j = iw;
|
|
152
|
+
{
|
|
153
|
+
double wanted = target_dis[i * n + j];
|
|
154
|
+
double w = weights[i * n + j];
|
|
155
|
+
delta_cost_scalar -=
|
|
156
|
+
w * sqr(wanted - hamming_dis(perm[i], perm[j]));
|
|
157
|
+
delta_cost_scalar +=
|
|
158
|
+
w * sqr(wanted - hamming_dis(perm[i], perm[jw]));
|
|
159
|
+
}
|
|
160
|
+
j = jw;
|
|
161
|
+
{
|
|
162
|
+
double wanted = target_dis[i * n + j];
|
|
163
|
+
double w = weights[i * n + j];
|
|
164
|
+
delta_cost_scalar -=
|
|
165
|
+
w * sqr(wanted - hamming_dis(perm[i], perm[j]));
|
|
166
|
+
delta_cost_scalar +=
|
|
167
|
+
w * sqr(wanted - hamming_dis(perm[i], perm[iw]));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return _mm512_reduce_add_pd(delta_cost_vec) + delta_cost_scalar;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
template <>
|
|
174
|
+
double distances_compute_cost<SIMDLevel::AVX512>(
|
|
175
|
+
const ReproduceDistancesObjective& obj,
|
|
176
|
+
const int* perm) {
|
|
177
|
+
const int n = obj.n;
|
|
178
|
+
double total_cost = 0.0;
|
|
179
|
+
for (int i = 0; i < n; ++i) {
|
|
180
|
+
const int pi = perm[i];
|
|
181
|
+
const int bro_t = i * n;
|
|
182
|
+
const int bro_s = pi * n;
|
|
183
|
+
__m512d sum = _mm512_setzero_pd();
|
|
184
|
+
int j = 0;
|
|
185
|
+
for (; j <= n - 8; j += 8) {
|
|
186
|
+
__m512d wv = _mm512_loadu_pd(&obj.target_dis[bro_t + j]);
|
|
187
|
+
__m512d ww = _mm512_loadu_pd(&obj.weights[bro_t + j]);
|
|
188
|
+
__m256i pj = _mm256_loadu_si256(
|
|
189
|
+
reinterpret_cast<const __m256i*>(&perm[j]));
|
|
190
|
+
__m256i idx = _mm256_add_epi32(_mm256_set1_epi32(bro_s), pj);
|
|
191
|
+
__m512d av = _mm512_i32gather_pd(idx, obj.source_dis.data(), 8);
|
|
192
|
+
__m512d d = _mm512_sub_pd(wv, av);
|
|
193
|
+
sum = _mm512_fmadd_pd(_mm512_mul_pd(d, d), ww, sum);
|
|
194
|
+
}
|
|
195
|
+
total_cost += _mm512_reduce_add_pd(sum);
|
|
196
|
+
for (; j < n; ++j) {
|
|
197
|
+
double wanted = obj.target_dis[bro_t + j];
|
|
198
|
+
double w = obj.weights[bro_t + j];
|
|
199
|
+
double actual = obj.get_source_dis(pi, perm[j]);
|
|
200
|
+
total_cost += w * sqr(wanted - actual);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return total_cost;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
template <>
|
|
207
|
+
double distances_cost_update<SIMDLevel::AVX512>(
|
|
208
|
+
const ReproduceDistancesObjective& obj,
|
|
209
|
+
const int* perm,
|
|
210
|
+
int iw,
|
|
211
|
+
int jw) {
|
|
212
|
+
const int n = obj.n;
|
|
213
|
+
double delta_cost = 0.0;
|
|
214
|
+
const int p_iw = perm[iw], p_jw = perm[jw];
|
|
215
|
+
const __m256i v_joff = _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0);
|
|
216
|
+
const __m256i vi = _mm256_set1_epi32(iw);
|
|
217
|
+
const __m256i vj = _mm256_set1_epi32(jw);
|
|
218
|
+
const __m256i vpi = _mm256_set1_epi32(p_iw);
|
|
219
|
+
const __m256i vpj = _mm256_set1_epi32(p_jw);
|
|
220
|
+
const __m256i vpin = _mm256_set1_epi32(p_iw * n);
|
|
221
|
+
const __m256i vpjn = _mm256_set1_epi32(p_jw * n);
|
|
222
|
+
|
|
223
|
+
auto process_row =
|
|
224
|
+
[&](int row, int old_p, int new_p, __m256i old_pn, __m256i new_pn) {
|
|
225
|
+
const int bro = row * n;
|
|
226
|
+
__m512d dv = _mm512_setzero_pd();
|
|
227
|
+
int j = 0;
|
|
228
|
+
for (; j <= n - 8; j += 8) {
|
|
229
|
+
__m512d wv = _mm512_loadu_pd(&obj.target_dis[bro + j]);
|
|
230
|
+
__m512d ww = _mm512_loadu_pd(&obj.weights[bro + j]);
|
|
231
|
+
__m256i pjv = _mm256_loadu_si256(
|
|
232
|
+
reinterpret_cast<const __m256i*>(&perm[j]));
|
|
233
|
+
__m256i ia = _mm256_add_epi32(old_pn, pjv);
|
|
234
|
+
__m512d av =
|
|
235
|
+
_mm512_i32gather_pd(ia, obj.source_dis.data(), 8);
|
|
236
|
+
__m512d da = _mm512_sub_pd(wv, av);
|
|
237
|
+
dv = _mm512_fnmadd_pd(ww, _mm512_mul_pd(da, da), dv);
|
|
238
|
+
__m256i vk = _mm256_add_epi32(_mm256_set1_epi32(j), v_joff);
|
|
239
|
+
__mmask8 mi = _mm256_cmpeq_epi32_mask(vk, vi);
|
|
240
|
+
__mmask8 mj = _mm256_cmpeq_epi32_mask(vk, vj);
|
|
241
|
+
__m256i pnj = _mm256_mask_blend_epi32(mi, pjv, vpj);
|
|
242
|
+
pnj = _mm256_mask_blend_epi32(mj, pnj, vpi);
|
|
243
|
+
__m256i in2 = _mm256_add_epi32(new_pn, pnj);
|
|
244
|
+
__m512d nav =
|
|
245
|
+
_mm512_i32gather_pd(in2, obj.source_dis.data(), 8);
|
|
246
|
+
__m512d dn = _mm512_sub_pd(wv, nav);
|
|
247
|
+
dv = _mm512_fmadd_pd(ww, _mm512_mul_pd(dn, dn), dv);
|
|
248
|
+
}
|
|
249
|
+
delta_cost += _mm512_reduce_add_pd(dv);
|
|
250
|
+
for (; j < n; ++j) {
|
|
251
|
+
double wanted = obj.target_dis[bro + j];
|
|
252
|
+
double w = obj.weights[bro + j];
|
|
253
|
+
double actual = obj.get_source_dis(old_p, perm[j]);
|
|
254
|
+
delta_cost -= w * sqr(wanted - actual);
|
|
255
|
+
int pnj = (j == iw) ? p_jw : ((j == jw) ? p_iw : perm[j]);
|
|
256
|
+
double na = obj.get_source_dis(new_p, pnj);
|
|
257
|
+
delta_cost += w * sqr(wanted - na);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
process_row(iw, p_iw, p_jw, vpin, vpjn);
|
|
261
|
+
process_row(jw, p_jw, p_iw, vpjn, vpin);
|
|
262
|
+
|
|
263
|
+
for (int i = 0; i < n; ++i) {
|
|
264
|
+
if (i == iw || i == jw)
|
|
265
|
+
continue;
|
|
266
|
+
double wanted = obj.target_dis[i * n + iw], w = obj.weights[i * n + iw];
|
|
267
|
+
double actual = obj.get_source_dis(perm[i], p_iw);
|
|
268
|
+
delta_cost -= w * sqr(wanted - actual);
|
|
269
|
+
double na = obj.get_source_dis(perm[i], p_jw);
|
|
270
|
+
delta_cost += w * sqr(wanted - na);
|
|
271
|
+
wanted = obj.target_dis[i * n + jw];
|
|
272
|
+
w = obj.weights[i * n + jw];
|
|
273
|
+
actual = obj.get_source_dis(perm[i], p_jw);
|
|
274
|
+
delta_cost -= w * sqr(wanted - actual);
|
|
275
|
+
na = obj.get_source_dis(perm[i], p_iw);
|
|
276
|
+
delta_cost += w * sqr(wanted - na);
|
|
277
|
+
}
|
|
278
|
+
return delta_cost;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
} // namespace polysemous_training
|
|
282
|
+
} // namespace faiss
|
|
283
|
+
|
|
284
|
+
#endif // COMPILE_SIMD_AVX512
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and 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 <faiss/utils/simd_levels.h>
|
|
11
|
+
|
|
12
|
+
namespace faiss {
|
|
13
|
+
|
|
14
|
+
struct ReproduceDistancesObjective;
|
|
15
|
+
|
|
16
|
+
namespace polysemous_training {
|
|
17
|
+
|
|
18
|
+
// Levels with a dedicated kernel: scalar (NONE) plus AVX-512. Any other runtime
|
|
19
|
+
// level (AVX2, NEON, ...) falls back to NONE via with_selected_simd_levels /
|
|
20
|
+
// get_simd_fallback, and AVX512_SPR reuses the AVX-512 kernel.
|
|
21
|
+
constexpr int SIMD_LEVELS =
|
|
22
|
+
(1 << int(SIMDLevel::NONE)) | (1 << int(SIMDLevel::AVX512));
|
|
23
|
+
|
|
24
|
+
/// compute_cost for ReproduceWithHammingObjective.
|
|
25
|
+
/// Parameters mirror the objective's fields to avoid exposing the
|
|
26
|
+
/// anonymous-namespace struct.
|
|
27
|
+
template <SIMDLevel SL>
|
|
28
|
+
double hamming_compute_cost(
|
|
29
|
+
int n,
|
|
30
|
+
const int* perm,
|
|
31
|
+
const double* target_dis,
|
|
32
|
+
const double* weights);
|
|
33
|
+
|
|
34
|
+
/// cost_update for ReproduceWithHammingObjective.
|
|
35
|
+
template <SIMDLevel SL>
|
|
36
|
+
double hamming_cost_update(
|
|
37
|
+
int n,
|
|
38
|
+
const int* perm,
|
|
39
|
+
int iw,
|
|
40
|
+
int jw,
|
|
41
|
+
const double* target_dis,
|
|
42
|
+
const double* weights);
|
|
43
|
+
|
|
44
|
+
/// compute_cost for ReproduceDistancesObjective.
|
|
45
|
+
template <SIMDLevel SL>
|
|
46
|
+
double distances_compute_cost(
|
|
47
|
+
const ReproduceDistancesObjective& obj,
|
|
48
|
+
const int* perm);
|
|
49
|
+
|
|
50
|
+
/// cost_update for ReproduceDistancesObjective.
|
|
51
|
+
template <SIMDLevel SL>
|
|
52
|
+
double distances_cost_update(
|
|
53
|
+
const ReproduceDistancesObjective& obj,
|
|
54
|
+
const int* perm,
|
|
55
|
+
int iw,
|
|
56
|
+
int jw);
|
|
57
|
+
|
|
58
|
+
// The scalar (NONE) specializations are defined in PolysemousTraining.cpp; the
|
|
59
|
+
// AVX-512 specializations are defined in polysemous_training/avx512.cpp. Both
|
|
60
|
+
// are declared here so callers instantiate the out-of-line definition rather
|
|
61
|
+
// than implicitly instantiating the (undefined) primary template.
|
|
62
|
+
template <>
|
|
63
|
+
double hamming_compute_cost<SIMDLevel::NONE>(
|
|
64
|
+
int n,
|
|
65
|
+
const int* perm,
|
|
66
|
+
const double* target_dis,
|
|
67
|
+
const double* weights);
|
|
68
|
+
template <>
|
|
69
|
+
double hamming_compute_cost<SIMDLevel::AVX512>(
|
|
70
|
+
int n,
|
|
71
|
+
const int* perm,
|
|
72
|
+
const double* target_dis,
|
|
73
|
+
const double* weights);
|
|
74
|
+
|
|
75
|
+
template <>
|
|
76
|
+
double hamming_cost_update<SIMDLevel::NONE>(
|
|
77
|
+
int n,
|
|
78
|
+
const int* perm,
|
|
79
|
+
int iw,
|
|
80
|
+
int jw,
|
|
81
|
+
const double* target_dis,
|
|
82
|
+
const double* weights);
|
|
83
|
+
template <>
|
|
84
|
+
double hamming_cost_update<SIMDLevel::AVX512>(
|
|
85
|
+
int n,
|
|
86
|
+
const int* perm,
|
|
87
|
+
int iw,
|
|
88
|
+
int jw,
|
|
89
|
+
const double* target_dis,
|
|
90
|
+
const double* weights);
|
|
91
|
+
|
|
92
|
+
template <>
|
|
93
|
+
double distances_compute_cost<SIMDLevel::NONE>(
|
|
94
|
+
const ReproduceDistancesObjective& obj,
|
|
95
|
+
const int* perm);
|
|
96
|
+
template <>
|
|
97
|
+
double distances_compute_cost<SIMDLevel::AVX512>(
|
|
98
|
+
const ReproduceDistancesObjective& obj,
|
|
99
|
+
const int* perm);
|
|
100
|
+
|
|
101
|
+
template <>
|
|
102
|
+
double distances_cost_update<SIMDLevel::NONE>(
|
|
103
|
+
const ReproduceDistancesObjective& obj,
|
|
104
|
+
const int* perm,
|
|
105
|
+
int iw,
|
|
106
|
+
int jw);
|
|
107
|
+
template <>
|
|
108
|
+
double distances_cost_update<SIMDLevel::AVX512>(
|
|
109
|
+
const ReproduceDistancesObjective& obj,
|
|
110
|
+
const int* perm,
|
|
111
|
+
int iw,
|
|
112
|
+
int jw);
|
|
113
|
+
|
|
114
|
+
} // namespace polysemous_training
|
|
115
|
+
} // namespace faiss
|
|
@@ -20,23 +20,39 @@ namespace faiss {
|
|
|
20
20
|
namespace pq_code_distance {
|
|
21
21
|
|
|
22
22
|
template <class PQCodeDist>
|
|
23
|
-
struct PQDistanceComputer : FlatCodesDistanceComputer {
|
|
23
|
+
struct PQDistanceComputer final : FlatCodesDistanceComputer {
|
|
24
24
|
using PQDecoder = typename PQCodeDist::PQDecoder;
|
|
25
|
-
size_t d;
|
|
26
25
|
MetricType metric;
|
|
27
|
-
idx_t nb;
|
|
28
26
|
const ProductQuantizer& pq;
|
|
29
27
|
const float* sdc;
|
|
30
28
|
std::vector<float> precomputed_table;
|
|
31
|
-
size_t ndis;
|
|
32
|
-
const float* q;
|
|
33
29
|
|
|
34
30
|
float distance_to_code(const uint8_t* code) final {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
float dis = PQCodeDist::distance_single_code(
|
|
31
|
+
return PQCodeDist::distance_single_code(
|
|
38
32
|
pq.M, pq.nbits, precomputed_table.data(), code);
|
|
39
|
-
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
void distance_to_code_batch_4(
|
|
36
|
+
const uint8_t* c1,
|
|
37
|
+
const uint8_t* c2,
|
|
38
|
+
const uint8_t* c3,
|
|
39
|
+
const uint8_t* c4,
|
|
40
|
+
float& d1,
|
|
41
|
+
float& d2,
|
|
42
|
+
float& d3,
|
|
43
|
+
float& d4) override {
|
|
44
|
+
PQCodeDist::distance_four_codes(
|
|
45
|
+
pq.M,
|
|
46
|
+
pq.nbits,
|
|
47
|
+
precomputed_table.data(),
|
|
48
|
+
c1,
|
|
49
|
+
c2,
|
|
50
|
+
c3,
|
|
51
|
+
c4,
|
|
52
|
+
d1,
|
|
53
|
+
d2,
|
|
54
|
+
d3,
|
|
55
|
+
d4);
|
|
40
56
|
}
|
|
41
57
|
|
|
42
58
|
float symmetric_dis(idx_t i, idx_t j) override {
|
|
@@ -50,7 +66,6 @@ struct PQDistanceComputer : FlatCodesDistanceComputer {
|
|
|
50
66
|
accu += sdci[codei.decode() + (codej.decode() << codei.nbits)];
|
|
51
67
|
sdci += uint64_t(1) << (2 * codei.nbits);
|
|
52
68
|
}
|
|
53
|
-
ndis++;
|
|
54
69
|
return accu;
|
|
55
70
|
}
|
|
56
71
|
|
|
@@ -58,18 +73,14 @@ struct PQDistanceComputer : FlatCodesDistanceComputer {
|
|
|
58
73
|
: FlatCodesDistanceComputer(
|
|
59
74
|
storage.codes.data(),
|
|
60
75
|
storage.code_size),
|
|
61
|
-
pq(storage.pq)
|
|
62
|
-
q(nullptr) {
|
|
76
|
+
pq(storage.pq) {
|
|
63
77
|
precomputed_table.resize(pq.M * pq.ksub);
|
|
64
|
-
nb = storage.ntotal;
|
|
65
|
-
d = storage.d;
|
|
66
78
|
metric = storage.metric_type;
|
|
67
79
|
if (pq.sdc_table.size() == pq.ksub * pq.ksub * pq.M) {
|
|
68
80
|
sdc = pq.sdc_table.data();
|
|
69
81
|
} else {
|
|
70
82
|
sdc = nullptr;
|
|
71
83
|
}
|
|
72
|
-
ndis = 0;
|
|
73
84
|
}
|
|
74
85
|
|
|
75
86
|
void set_query(const float* x) override {
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
|
|
10
10
|
#define THE_SIMD_LEVEL SIMDLevel::AVX2
|
|
11
11
|
|
|
12
|
-
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
12
|
+
// NOLINTNEXTLINE(facebook-hte-InlineHeader,facebook-unused-include-check)
|
|
13
13
|
#include <faiss/impl/pq_code_distance/pq_code_distance-avx2.h>
|
|
14
|
-
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
14
|
+
// NOLINTNEXTLINE(facebook-hte-InlineHeader,facebook-unused-include-check)
|
|
15
15
|
#include <faiss/utils/hamming_distance/hamming_computer-avx2.h>
|
|
16
16
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader,facebook-unused-include-check)
|
|
17
17
|
#include <faiss/impl/pq_code_distance/pq_scan_impl.h>
|
|
18
|
-
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
18
|
+
// NOLINTNEXTLINE(facebook-hte-InlineHeader,facebook-unused-include-check)
|
|
19
19
|
#include <faiss/impl/pq_code_distance/PQDistanceComputer_impl.h>
|
|
20
|
-
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
20
|
+
// NOLINTNEXTLINE(facebook-hte-InlineHeader,facebook-unused-include-check)
|
|
21
21
|
#include <faiss/impl/pq_code_distance/IVFPQScanner_impl.h>
|
|
22
22
|
|
|
23
23
|
#endif // COMPILE_SIMD_AVX2
|