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
|
@@ -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)) {
|
|
@@ -1044,6 +1095,7 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
|
1044
1095
|
WRITE1(svs->prune_to);
|
|
1045
1096
|
WRITE1(svs->use_full_search_history);
|
|
1046
1097
|
WRITE1(svs->storage_kind);
|
|
1098
|
+
WRITE1(svs->is_static);
|
|
1047
1099
|
|
|
1048
1100
|
if (lean != nullptr) {
|
|
1049
1101
|
WRITE1(lean->leanvec_d);
|
|
@@ -35,6 +35,31 @@ size_t get_deserialization_vector_byte_limit();
|
|
|
35
35
|
|
|
36
36
|
#define READ1(x) READANDCHECK(&(x), 1)
|
|
37
37
|
|
|
38
|
+
// Reads a single byte into a bool, rejecting any byte that is not the
|
|
39
|
+
// canonical encoding for the platform's bool representation. Reading a
|
|
40
|
+
// non-canonical byte directly into a bool is undefined behavior and
|
|
41
|
+
// trips UBSan's invalid-bool-load check. To stay ABI-portable, we
|
|
42
|
+
// assign via the language-defined conversion (b != 0) and then compare
|
|
43
|
+
// the resulting bool's storage byte back against the byte we read - the
|
|
44
|
+
// roundtrip succeeds iff the input byte was already canonical on this
|
|
45
|
+
// platform. FAISS only ever writes the canonical encoding via
|
|
46
|
+
// WRITE1(bool), so well-formed indices roundtrip cleanly; corrupt or
|
|
47
|
+
// attacker-controlled input that places a non-canonical byte at a bool
|
|
48
|
+
// offset is rejected as a FaissException.
|
|
49
|
+
#define READ1_BOOL(x) \
|
|
50
|
+
{ \
|
|
51
|
+
static_assert( \
|
|
52
|
+
sizeof(x) == 1, "READ1_BOOL: destination must be 1 byte"); \
|
|
53
|
+
uint8_t b; \
|
|
54
|
+
READANDCHECK(&b, 1); \
|
|
55
|
+
(x) = (b != 0); \
|
|
56
|
+
FAISS_THROW_IF_NOT_FMT( \
|
|
57
|
+
*reinterpret_cast<const uint8_t*>(&(x)) == b, \
|
|
58
|
+
"invalid bool encoding 0x%02x for %s", \
|
|
59
|
+
b, \
|
|
60
|
+
#x); \
|
|
61
|
+
}
|
|
62
|
+
|
|
38
63
|
#define READ1_DUMMY(x_type) \
|
|
39
64
|
{ \
|
|
40
65
|
x_type x = {}; \
|
|
@@ -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
|
|
|
@@ -110,12 +112,6 @@ inline int __builtin_clzll(uint64_t x) {
|
|
|
110
112
|
#define FAISS_PACK_STRUCTS_BEGIN __pragma(pack(push, 1))
|
|
111
113
|
#define FAISS_PACK_STRUCTS_END __pragma(pack(pop))
|
|
112
114
|
|
|
113
|
-
#ifdef SWIG
|
|
114
|
-
#define FAISS_MAYBE_UNUSED
|
|
115
|
-
#else
|
|
116
|
-
#define FAISS_MAYBE_UNUSED [[maybe_unused]]
|
|
117
|
-
#endif
|
|
118
|
-
|
|
119
115
|
#else
|
|
120
116
|
/*******************************************************
|
|
121
117
|
* Linux and OSX
|
|
@@ -130,12 +126,10 @@ inline int __builtin_clzll(uint64_t x) {
|
|
|
130
126
|
#define ALIGNED(x)
|
|
131
127
|
#define FAISS_PACKED
|
|
132
128
|
#define FAISS_RESTRICT
|
|
133
|
-
#define FAISS_MAYBE_UNUSED
|
|
134
129
|
#else
|
|
135
130
|
#define ALIGNED(x) __attribute__((aligned(x)))
|
|
136
131
|
#define FAISS_PACKED __attribute__((packed))
|
|
137
132
|
#define FAISS_RESTRICT __restrict
|
|
138
|
-
#define FAISS_MAYBE_UNUSED [[maybe_unused]]
|
|
139
133
|
#endif
|
|
140
134
|
|
|
141
135
|
// On non-Windows, FAISS_PACKED handles packing, so these are no-ops
|
|
@@ -220,3 +214,15 @@ inline int __builtin_clzll(uint64_t x) {
|
|
|
220
214
|
#define Swap4Bytes(val) \
|
|
221
215
|
((((val) >> 24) & 0x000000FF) | (((val) >> 8) & 0x0000FF00) | \
|
|
222
216
|
(((val) << 8) & 0x00FF0000) | (((val) << 24) & 0xFF000000))
|
|
217
|
+
|
|
218
|
+
/*******************************************************
|
|
219
|
+
* A few things that SWIG has trouble parsing
|
|
220
|
+
*******************************************************/
|
|
221
|
+
|
|
222
|
+
#ifdef SWIG
|
|
223
|
+
#define FAISS_MAYBE_UNUSED
|
|
224
|
+
#define FAISS_FINAL
|
|
225
|
+
#else
|
|
226
|
+
#define FAISS_MAYBE_UNUSED [[maybe_unused]]
|
|
227
|
+
#define FAISS_FINAL final
|
|
228
|
+
#endif
|
|
@@ -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
|