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
|
@@ -223,18 +223,18 @@ struct QuantizerTemplate<
|
|
|
223
223
|
};
|
|
224
224
|
|
|
225
225
|
/**********************************************************
|
|
226
|
-
*
|
|
226
|
+
* Lloyd-Max scalar quantizer
|
|
227
227
|
**********************************************************/
|
|
228
228
|
|
|
229
|
-
// NEON
|
|
229
|
+
// NEON Lloyd-Max: decode via gather, encode stays scalar.
|
|
230
230
|
// NEON doesn't have movemask so 1-bit encode is also scalar.
|
|
231
|
-
#define
|
|
231
|
+
#define DEFINE_LLOYD_MAX_NEON_SPECIALIZATION(NBITS, UNPACK_FN) \
|
|
232
232
|
template <> \
|
|
233
|
-
struct
|
|
234
|
-
:
|
|
235
|
-
using Base =
|
|
233
|
+
struct QuantizerLloydMax<NBITS, SIMDLevel::ARM_NEON> \
|
|
234
|
+
: QuantizerLloydMax<NBITS, SIMDLevel::NONE> { \
|
|
235
|
+
using Base = QuantizerLloydMax<NBITS, SIMDLevel::NONE>; \
|
|
236
236
|
\
|
|
237
|
-
|
|
237
|
+
QuantizerLloydMax(size_t d, const std::vector<float>& trained) \
|
|
238
238
|
: Base(d, trained) { \
|
|
239
239
|
assert(d % 8 == 0); \
|
|
240
240
|
} \
|
|
@@ -256,19 +256,19 @@ struct QuantizerTemplate<
|
|
|
256
256
|
} \
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
259
|
+
DEFINE_LLOYD_MAX_NEON_SPECIALIZATION(1, unpack_8x1bit_to_u8);
|
|
260
|
+
DEFINE_LLOYD_MAX_NEON_SPECIALIZATION(2, unpack_8x2bit_to_u8);
|
|
261
|
+
DEFINE_LLOYD_MAX_NEON_SPECIALIZATION(3, unpack_8x3bit_to_u8);
|
|
262
|
+
DEFINE_LLOYD_MAX_NEON_SPECIALIZATION(4, unpack_8x4bit_to_u8);
|
|
263
263
|
|
|
264
|
-
#undef
|
|
264
|
+
#undef DEFINE_LLOYD_MAX_NEON_SPECIALIZATION
|
|
265
265
|
|
|
266
266
|
template <>
|
|
267
|
-
struct
|
|
268
|
-
:
|
|
269
|
-
using Base =
|
|
267
|
+
struct QuantizerLloydMax<8, SIMDLevel::ARM_NEON>
|
|
268
|
+
: QuantizerLloydMax<8, SIMDLevel::NONE> {
|
|
269
|
+
using Base = QuantizerLloydMax<8, SIMDLevel::NONE>;
|
|
270
270
|
|
|
271
|
-
|
|
271
|
+
QuantizerLloydMax(size_t d, const std::vector<float>& trained)
|
|
272
272
|
: Base(d, trained) {
|
|
273
273
|
assert(d % 8 == 0);
|
|
274
274
|
}
|
|
@@ -84,6 +84,24 @@ inline auto dispatch_with_fallback(LambdaType&& action) {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
/** Run action at current_level; on a null result, retry the next-lower level,
|
|
88
|
+
* down to NONE (terminal). action is called per level tried, so never moved. */
|
|
89
|
+
template <int available_levels, SIMDLevel current_level, typename LambdaType>
|
|
90
|
+
inline auto dispatch_simd_level_or_lower(LambdaType& action) {
|
|
91
|
+
if constexpr (current_level == SIMDLevel::NONE) {
|
|
92
|
+
return action.template operator()<SIMDLevel::NONE>();
|
|
93
|
+
} else {
|
|
94
|
+
if constexpr (available_levels & (1 << int(current_level))) {
|
|
95
|
+
if (auto result = action.template operator()<current_level>()) {
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return dispatch_simd_level_or_lower<
|
|
100
|
+
available_levels,
|
|
101
|
+
get_simd_fallback(current_level)>(action);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
87
105
|
/** The complete dispatching function. It takes into account:
|
|
88
106
|
* - the currently selected SIMD level
|
|
89
107
|
* - the compiled in SIMD levels (given by COMPILE_SIMD_XXX)
|
|
@@ -163,6 +181,18 @@ inline auto with_selected_simd_levels(LambdaType&& action) {
|
|
|
163
181
|
#endif
|
|
164
182
|
}
|
|
165
183
|
|
|
184
|
+
/** Like with_selected_simd_levels, but for factory actions that return null to
|
|
185
|
+
* decline a level (e.g. AVX-512 needing d % 16 == 0). Falls back to the next
|
|
186
|
+
* lower level, down to NONE. */
|
|
187
|
+
template <int available_levels, typename LambdaType>
|
|
188
|
+
inline auto with_simd_level_fallback(const LambdaType& action) {
|
|
189
|
+
return with_selected_simd_levels<available_levels>(
|
|
190
|
+
[&action]<SIMDLevel SL>() {
|
|
191
|
+
return dispatch_simd_level_or_lower<available_levels, SL>(
|
|
192
|
+
action);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
166
196
|
/**
|
|
167
197
|
* Dispatch to a lambda with SIMDLevel as a compile-time constant.
|
|
168
198
|
*
|
|
@@ -198,15 +228,6 @@ inline auto with_simd_level(LambdaType&& action) {
|
|
|
198
228
|
std::forward<LambdaType>(action));
|
|
199
229
|
}
|
|
200
230
|
|
|
201
|
-
/**
|
|
202
|
-
* Use for functions with AVX512_SPR-specific implementations.
|
|
203
|
-
*/
|
|
204
|
-
template <typename LambdaType>
|
|
205
|
-
inline auto with_simd_level_spr(LambdaType&& action) {
|
|
206
|
-
return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_A0_SPR>(
|
|
207
|
-
std::forward<LambdaType>(action));
|
|
208
|
-
}
|
|
209
|
-
|
|
210
231
|
/**
|
|
211
232
|
* Use for functions implemented with simdXintY (256-bit) operations
|
|
212
233
|
* that don't have dedicated AVX512 or SVE implementations.
|
|
@@ -21,11 +21,13 @@
|
|
|
21
21
|
#include <faiss/Index2Layer.h>
|
|
22
22
|
#include <faiss/IndexAdditiveQuantizer.h>
|
|
23
23
|
#include <faiss/IndexAdditiveQuantizerFastScan.h>
|
|
24
|
+
#include <faiss/IndexEDEN.h>
|
|
24
25
|
#include <faiss/IndexFlat.h>
|
|
25
26
|
#include <faiss/IndexHNSW.h>
|
|
26
27
|
#include <faiss/IndexIVF.h>
|
|
27
28
|
#include <faiss/IndexIVFAdditiveQuantizer.h>
|
|
28
29
|
#include <faiss/IndexIVFAdditiveQuantizerFastScan.h>
|
|
30
|
+
#include <faiss/IndexIVFEDEN.h>
|
|
29
31
|
#include <faiss/IndexIVFFlat.h>
|
|
30
32
|
#include <faiss/IndexIVFFlatPanorama.h>
|
|
31
33
|
#include <faiss/IndexIVFPQ.h>
|
|
@@ -315,8 +317,8 @@ Index* parse_coarse_quantizer(
|
|
|
315
317
|
SVSStorageKind storage = SVSStorageKind::SVS_FP32;
|
|
316
318
|
if (sm[3].matched) {
|
|
317
319
|
std::string s = sm[3].str().substr(1);
|
|
318
|
-
if (s == "
|
|
319
|
-
storage = SVSStorageKind::
|
|
320
|
+
if (s == "SQ8") {
|
|
321
|
+
storage = SVSStorageKind::SVS_SQ8;
|
|
320
322
|
} else if (s == "FP16") {
|
|
321
323
|
storage = SVSStorageKind::SVS_FP16;
|
|
322
324
|
} else if (s == "FP32") {
|
|
@@ -514,6 +516,18 @@ IndexIVF* parse_IndexIVF(
|
|
|
514
516
|
uint8_t nb_bits = sm[1].length() > 0 ? std::stoi(sm[1].str()) : 1;
|
|
515
517
|
return new IndexIVFRaBitQ(get_q(), d, nlist, mt, own_il, nb_bits);
|
|
516
518
|
}
|
|
519
|
+
// IndexIVFEDEN with optional nb_bits (1-8) and scale type.
|
|
520
|
+
// Accepts: "EDEN" (default 1-bit), "EDEN{nb_bits}" (e.g., "EDEN4"),
|
|
521
|
+
// or "EDEN{nb_bits}BIASED" for the MSE-minimizing scale.
|
|
522
|
+
if (match("EDEN([1-8])?(BIASED|BIAS)?")) {
|
|
523
|
+
uint8_t nb_bits = sm[1].length() > 0 ? std::stoi(sm[1].str()) : 1;
|
|
524
|
+
EDENScaleType scale_type =
|
|
525
|
+
sm[2].str() == "BIASED" || sm[2].str() == "BIAS"
|
|
526
|
+
? EDENScaleType_BIASED
|
|
527
|
+
: EDENScaleType_UNBIASED;
|
|
528
|
+
return new IndexIVFEDEN(
|
|
529
|
+
get_q(), d, nlist, mt, own_il, nb_bits, scale_type);
|
|
530
|
+
}
|
|
517
531
|
// Accepts: "RaBitQfs" (default 1-bit, batch size 32)
|
|
518
532
|
// "RaBitQfs{nb_bits}" (e.g., "RaBitQfs4")
|
|
519
533
|
// "RaBitQfs_64" (1-bit, batch size 64)
|
|
@@ -681,16 +695,16 @@ Index* parse_svs_datatype(
|
|
|
681
695
|
}
|
|
682
696
|
FAISS_ASSERT(false && "Unsupported SVS index type for Float16");
|
|
683
697
|
}
|
|
684
|
-
if (re_match(datatype_string, "
|
|
698
|
+
if (re_match(datatype_string, "SQ8", sm)) {
|
|
685
699
|
if (index_type == "Vamana") {
|
|
686
700
|
return new IndexSVSVamana(
|
|
687
|
-
d, std::stoul(arg_string), mt, SVSStorageKind::
|
|
701
|
+
d, std::stoul(arg_string), mt, SVSStorageKind::SVS_SQ8);
|
|
688
702
|
}
|
|
689
703
|
if (index_type == "IVF") {
|
|
690
704
|
return new IndexSVSIVF(
|
|
691
|
-
d, std::stoul(arg_string), mt, SVSStorageKind::
|
|
705
|
+
d, std::stoul(arg_string), mt, SVSStorageKind::SVS_SQ8);
|
|
692
706
|
}
|
|
693
|
-
FAISS_ASSERT(false && "Unsupported SVS index type for
|
|
707
|
+
FAISS_ASSERT(false && "Unsupported SVS index type for SQ8");
|
|
694
708
|
}
|
|
695
709
|
if (re_match(datatype_string, "(LVQ[0-9]+x[0-9]+)", sm)) {
|
|
696
710
|
if (index_type == "Vamana") {
|
|
@@ -917,6 +931,18 @@ Index* parse_other_indexes(
|
|
|
917
931
|
return new IndexRaBitQ(d, metric, nb_bits);
|
|
918
932
|
}
|
|
919
933
|
|
|
934
|
+
// IndexEDEN with optional nb_bits (1-8) and scale type.
|
|
935
|
+
// Accepts: "EDEN" (default 1-bit), "EDEN{nb_bits}" (e.g., "EDEN4"),
|
|
936
|
+
// or "EDEN{nb_bits}BIASED" for the MSE-minimizing scale.
|
|
937
|
+
if (match("EDEN([1-8])?(BIASED|BIAS)?")) {
|
|
938
|
+
uint8_t nb_bits = sm[1].length() > 0 ? std::stoi(sm[1].str()) : 1;
|
|
939
|
+
EDENScaleType scale_type =
|
|
940
|
+
sm[2].str() == "BIASED" || sm[2].str() == "BIAS"
|
|
941
|
+
? EDENScaleType_BIASED
|
|
942
|
+
: EDENScaleType_UNBIASED;
|
|
943
|
+
return new IndexEDEN(d, metric, nb_bits, scale_type);
|
|
944
|
+
}
|
|
945
|
+
|
|
920
946
|
if (match("RaBitQfs([1-9])?(_[0-9]+)?")) {
|
|
921
947
|
uint8_t nb_bits = sm[1].length() > 0 ? std::stoi(sm[1].str()) : 1;
|
|
922
948
|
int bbs = mres_to_int(sm[2], 32, 1);
|
|
@@ -80,7 +80,7 @@ idx_t DirectMap::get(idx_t key) const {
|
|
|
80
80
|
return lo;
|
|
81
81
|
} else if (type == Hashtable) {
|
|
82
82
|
auto res = hashtable.find(key);
|
|
83
|
-
|
|
83
|
+
FAISS_THROW_IF_MSG(res == hashtable.end(), "key not found");
|
|
84
84
|
return res->second;
|
|
85
85
|
} else {
|
|
86
86
|
FAISS_THROW_MSG("direct map not initialized");
|
|
@@ -371,8 +371,8 @@ ArrayInvertedListsPanorama::ArrayInvertedListsPanorama(
|
|
|
371
371
|
pano(code_size_in, n_levels_in, batch_size) {
|
|
372
372
|
FAISS_THROW_IF_NOT(n_levels_in > 0);
|
|
373
373
|
FAISS_THROW_IF_NOT(code_size_in % sizeof(float) == 0);
|
|
374
|
-
|
|
375
|
-
|
|
374
|
+
FAISS_THROW_IF_MSG(
|
|
375
|
+
use_iterator,
|
|
376
376
|
"IndexIVFFlatPanorama does not support iterators, use vanilla IndexIVFFlat instead");
|
|
377
377
|
FAISS_ASSERT(level_width % sizeof(float) == 0);
|
|
378
378
|
|
|
@@ -405,7 +405,8 @@ void OnDiskInvertedLists::update_entries(
|
|
|
405
405
|
size_t n_entry,
|
|
406
406
|
const idx_t* ids_in,
|
|
407
407
|
const uint8_t* codes_in) {
|
|
408
|
-
|
|
408
|
+
FAISS_THROW_IF_MSG(
|
|
409
|
+
read_only, "cannot modify a read-only OnDiskInvertedLists");
|
|
409
410
|
if (n_entry == 0) {
|
|
410
411
|
return;
|
|
411
412
|
}
|
|
@@ -422,7 +423,8 @@ size_t OnDiskInvertedLists::add_entries(
|
|
|
422
423
|
size_t n_entry,
|
|
423
424
|
const idx_t* ids,
|
|
424
425
|
const uint8_t* code) {
|
|
425
|
-
|
|
426
|
+
FAISS_THROW_IF_MSG(
|
|
427
|
+
read_only, "cannot modify a read-only OnDiskInvertedLists");
|
|
426
428
|
locks->lock_1(list_no);
|
|
427
429
|
size_t o = list_size(list_no);
|
|
428
430
|
resize_locked(list_no, n_entry + o);
|
|
@@ -432,7 +434,8 @@ size_t OnDiskInvertedLists::add_entries(
|
|
|
432
434
|
}
|
|
433
435
|
|
|
434
436
|
void OnDiskInvertedLists::resize(size_t list_no, size_t new_size) {
|
|
435
|
-
|
|
437
|
+
FAISS_THROW_IF_MSG(
|
|
438
|
+
read_only, "cannot modify a read-only OnDiskInvertedLists");
|
|
436
439
|
locks->lock_1(list_no);
|
|
437
440
|
resize_locked(list_no, new_size);
|
|
438
441
|
locks->unlock_1(list_no);
|
|
@@ -799,7 +802,19 @@ InvertedLists* OnDiskInvertedListsIOHook::read_ArrayInvertedLists(
|
|
|
799
802
|
OnDiskInvertedLists::List& l = ails->lists[i];
|
|
800
803
|
l.size = l.capacity = sizes[i];
|
|
801
804
|
l.offset = o;
|
|
802
|
-
|
|
805
|
+
size_t elem_size = add_no_overflow(
|
|
806
|
+
sizeof(idx_t), ails->code_size, "OnDisk inverted list element");
|
|
807
|
+
size_t list_bytes =
|
|
808
|
+
mul_no_overflow(l.size, elem_size, "OnDisk inverted list");
|
|
809
|
+
o = add_no_overflow(o, list_bytes, "OnDisk inverted list offset");
|
|
810
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
811
|
+
o <= ails->totsize,
|
|
812
|
+
"inverted list %zu at offset %zu with %zu bytes exceeds "
|
|
813
|
+
"mapped file size %zu",
|
|
814
|
+
i,
|
|
815
|
+
l.offset,
|
|
816
|
+
list_bytes,
|
|
817
|
+
ails->totsize);
|
|
803
818
|
}
|
|
804
819
|
// resume normal reading of file
|
|
805
820
|
fseek(fdesc, o, SEEK_SET);
|
|
@@ -151,7 +151,9 @@ int64_t PyCallbackShardingFunction::operator()(int64_t i, int64_t shard_count) {
|
|
|
151
151
|
if (shard_id == nullptr) {
|
|
152
152
|
FAISS_THROW_MSG("propagate py error");
|
|
153
153
|
}
|
|
154
|
-
|
|
154
|
+
int64_t rv = PyLong_AsLongLong(shard_id);
|
|
155
|
+
Py_DECREF(shard_id);
|
|
156
|
+
return rv;
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
PyCallbackShardingFunction::~PyCallbackShardingFunction() {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
#include <faiss/impl/AuxIndexStructures.h>
|
|
31
31
|
#include <faiss/impl/FaissAssert.h>
|
|
32
32
|
#include <faiss/impl/IDSelector.h>
|
|
33
|
+
#include <faiss/impl/mapped_io.h>
|
|
33
34
|
|
|
34
35
|
#include <algorithm>
|
|
35
36
|
#include <concepts>
|
|
@@ -248,4 +249,63 @@ struct FaissResultsAllocator : public svs_runtime::ResultsAllocator {
|
|
|
248
249
|
using LabelsConverter = OutputBufferConverter<size_t, faiss::idx_t>;
|
|
249
250
|
mutable LabelsConverter labels_converter;
|
|
250
251
|
};
|
|
252
|
+
|
|
253
|
+
// Helper for memory-mapped SVS index loading.
|
|
254
|
+
// Acquires a pointer to the remaining mapped region and returns the data
|
|
255
|
+
// pointer, size in bytes, and starting position. Validates that mmap returns
|
|
256
|
+
// expected byte count. MappedFileIOReader::mmap returns number of items (not
|
|
257
|
+
// bytes); we always request size=1 so items == bytes, but we name variables
|
|
258
|
+
// explicitly to avoid confusion.
|
|
259
|
+
struct MmapSpan {
|
|
260
|
+
void* data = nullptr;
|
|
261
|
+
size_t size_bytes = 0;
|
|
262
|
+
size_t start_pos = 0;
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
inline MmapSpan acquire_mmap_span(MappedFileIOReader* mf) {
|
|
266
|
+
FAISS_THROW_IF_NOT(mf);
|
|
267
|
+
FAISS_THROW_IF_NOT(mf->mmap_owner);
|
|
268
|
+
size_t pos = mf->pos;
|
|
269
|
+
size_t size_to_end = mf->mmap_owner->size() - pos;
|
|
270
|
+
// Reject an empty span: MappedFileIOReader::mmap() returns 0 without
|
|
271
|
+
// writing *ptr when no bytes remain, which would otherwise pass the
|
|
272
|
+
// size check below and hand a nullptr / zero size to the SVS runtime
|
|
273
|
+
// (e.g. for a truncated or corrupt file).
|
|
274
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
275
|
+
size_to_end > 0,
|
|
276
|
+
"acquire_mmap_span: no mapped bytes remain at reader position %zu",
|
|
277
|
+
pos);
|
|
278
|
+
void* data = nullptr;
|
|
279
|
+
// mmap returns actual_nitems; with size=1 this equals bytes
|
|
280
|
+
size_t actual_nitems = mf->mmap(&data, 1, size_to_end);
|
|
281
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
282
|
+
actual_nitems == size_to_end,
|
|
283
|
+
"mmap() returned unexpected size: %zu items (expected %zu bytes)",
|
|
284
|
+
actual_nitems,
|
|
285
|
+
size_to_end);
|
|
286
|
+
return {data, size_to_end, pos};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Adjusts MappedFileIOReader position after SVS consumes read_bytes,
|
|
290
|
+
// storing mmap_owner reference to keep mapping alive.
|
|
291
|
+
inline void finalize_mmap_span(
|
|
292
|
+
MappedFileIOReader* mf,
|
|
293
|
+
const MmapSpan& span,
|
|
294
|
+
size_t read_bytes,
|
|
295
|
+
std::shared_ptr<MmappedFileMappingOwner>& mmap_owner_out) {
|
|
296
|
+
// Take ownership of the mapping BEFORE validating read_bytes. By this point
|
|
297
|
+
// the caller's impl already holds pointers into the mapped region, so the
|
|
298
|
+
// index must keep the mapping alive even on the throw path. Otherwise the
|
|
299
|
+
// index would be left with a live impl but no mmap_owner, and once the
|
|
300
|
+
// reader's mapping reference is released the index destructor (which calls
|
|
301
|
+
// destroy(impl)) would touch unmapped memory.
|
|
302
|
+
mmap_owner_out = mf->mmap_owner;
|
|
303
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
304
|
+
read_bytes > 0 && read_bytes <= span.size_bytes,
|
|
305
|
+
"map_to_memory returned invalid read_bytes: %zu (span size %zu)",
|
|
306
|
+
read_bytes,
|
|
307
|
+
span.size_bytes);
|
|
308
|
+
mf->pos = span.start_pos + read_bytes;
|
|
309
|
+
}
|
|
310
|
+
|
|
251
311
|
} // namespace faiss
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
#include <faiss/Index.h>
|
|
25
|
+
#include <faiss/impl/mapped_io.h>
|
|
25
26
|
#include <faiss/svs/IndexSVSFaissUtils.h>
|
|
26
27
|
#include <faiss/svs/IndexSVSFlat.h>
|
|
27
28
|
|
|
@@ -55,11 +56,16 @@ void IndexSVSFlat::add(idx_t n, const float* x) {
|
|
|
55
56
|
|
|
56
57
|
void IndexSVSFlat::reset() {
|
|
57
58
|
if (impl) {
|
|
58
|
-
|
|
59
|
+
// Destroy impl to ensure no dangling pointers to mmap region remain.
|
|
60
|
+
// FlatIndex::reset may retain views; destroy guarantees clean state
|
|
61
|
+
// matching Vamana static behavior.
|
|
62
|
+
auto status = svs_runtime::FlatIndex::destroy(impl);
|
|
59
63
|
if (!status.ok()) {
|
|
60
64
|
FAISS_THROW_MSG(status.message());
|
|
61
65
|
}
|
|
66
|
+
impl = nullptr;
|
|
62
67
|
}
|
|
68
|
+
mmap_owner.reset(); // Release the memory mapping
|
|
63
69
|
ntotal = 0;
|
|
64
70
|
}
|
|
65
71
|
|
|
@@ -114,4 +120,23 @@ void IndexSVSFlat::deserialize_impl(std::istream& in) {
|
|
|
114
120
|
FAISS_THROW_IF_NOT_MSG(impl, "Failed to load SVS Flat index.");
|
|
115
121
|
}
|
|
116
122
|
|
|
123
|
+
void IndexSVSFlat::map_to(MappedFileIOReader* mf) {
|
|
124
|
+
FAISS_THROW_IF_MSG(impl, "Cannot map_to: SVS index already loaded.");
|
|
125
|
+
FAISS_THROW_IF_NOT(mf);
|
|
126
|
+
|
|
127
|
+
MmapSpan span = acquire_mmap_span(mf);
|
|
128
|
+
|
|
129
|
+
auto svs_metric = to_svs_metric(metric_type);
|
|
130
|
+
|
|
131
|
+
size_t read_bytes = 0;
|
|
132
|
+
auto status = svs_runtime::FlatIndex::map_to_memory(
|
|
133
|
+
&impl, span.data, span.size_bytes, svs_metric, &read_bytes);
|
|
134
|
+
|
|
135
|
+
if (!status.ok()) {
|
|
136
|
+
FAISS_THROW_MSG(status.message());
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
finalize_mmap_span(mf, span, read_bytes, mmap_owner);
|
|
140
|
+
}
|
|
141
|
+
|
|
117
142
|
} // namespace faiss
|
|
@@ -29,9 +29,14 @@
|
|
|
29
29
|
#include <svs/runtime/flat_index.h>
|
|
30
30
|
|
|
31
31
|
#include <iostream>
|
|
32
|
+
#include <memory>
|
|
32
33
|
|
|
33
34
|
namespace faiss {
|
|
34
35
|
|
|
36
|
+
// Forward declarations
|
|
37
|
+
struct MappedFileIOReader;
|
|
38
|
+
struct MmappedFileMappingOwner;
|
|
39
|
+
|
|
35
40
|
struct IndexSVSFlat : Index {
|
|
36
41
|
// sequential labels
|
|
37
42
|
size_t nlabels{0};
|
|
@@ -56,10 +61,18 @@ struct IndexSVSFlat : Index {
|
|
|
56
61
|
/* The actual SVS implementation */
|
|
57
62
|
svs_runtime::FlatIndex* impl{nullptr};
|
|
58
63
|
|
|
64
|
+
// Holds a reference to the memory-mapped file owner to keep the memory
|
|
65
|
+
// mapping alive for the lifetime of this index. Only used when index is
|
|
66
|
+
// loaded via map_to() with memory-mapped I/O.
|
|
67
|
+
std::shared_ptr<MmappedFileMappingOwner> mmap_owner{nullptr};
|
|
68
|
+
|
|
59
69
|
/* Serialization */
|
|
60
70
|
void serialize_impl(std::ostream& out) const;
|
|
61
71
|
void deserialize_impl(std::istream& in);
|
|
62
72
|
|
|
73
|
+
/* Memory-mapped deserialization */
|
|
74
|
+
void map_to(MappedFileIOReader* mf);
|
|
75
|
+
|
|
63
76
|
protected:
|
|
64
77
|
/* Initializes the implementation*/
|
|
65
78
|
virtual void create_impl();
|
|
@@ -222,7 +222,7 @@ size_t IndexSVSIVF::remove_ids(const IDSelector& sel) {
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
void IndexSVSIVF::create_impl(idx_t n, const float* x) {
|
|
225
|
-
|
|
225
|
+
FAISS_THROW_IF_MSG(impl, "impl already created");
|
|
226
226
|
ntotal = 0;
|
|
227
227
|
auto svs_metric = to_svs_metric(metric_type);
|
|
228
228
|
auto svs_storage_kind = to_svs_storage_kind(storage_kind);
|
|
@@ -119,7 +119,7 @@ void IndexSVSIVFLeanVec::deserialize_training_data(std::istream& in) {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
void IndexSVSIVFLeanVec::create_impl(idx_t n, const float* x) {
|
|
122
|
-
|
|
122
|
+
FAISS_THROW_IF_MSG(impl, "impl already created");
|
|
123
123
|
ntotal = 0;
|
|
124
124
|
auto svs_metric = to_svs_metric(metric_type);
|
|
125
125
|
auto svs_storage_kind = to_svs_storage_kind(storage_kind);
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
#include <faiss/svs/IndexSVSVamana.h>
|
|
26
26
|
|
|
27
27
|
#include <faiss/Index.h>
|
|
28
|
+
#include <faiss/impl/mapped_io.h>
|
|
28
29
|
|
|
29
30
|
#include <svs/runtime/api_defs.h>
|
|
30
31
|
#include <svs/runtime/dynamic_vamana_index.h>
|
|
@@ -187,6 +188,7 @@ void IndexSVSVamana::reset() {
|
|
|
187
188
|
}
|
|
188
189
|
stored_vectors.clear();
|
|
189
190
|
stored_vectors_valid = true;
|
|
191
|
+
mmap_owner.reset(); // Release the memory mapping
|
|
190
192
|
is_trained = false;
|
|
191
193
|
ntotal = 0;
|
|
192
194
|
}
|
|
@@ -266,7 +268,7 @@ size_t IndexSVSVamana::remove_ids(const IDSelector& sel) {
|
|
|
266
268
|
}
|
|
267
269
|
|
|
268
270
|
void IndexSVSVamana::create_impl(idx_t n, const float* x) {
|
|
269
|
-
|
|
271
|
+
FAISS_THROW_IF_MSG(impl, "impl already created");
|
|
270
272
|
ntotal = 0;
|
|
271
273
|
auto svs_metric = to_svs_metric(metric_type);
|
|
272
274
|
auto svs_storage_kind = to_svs_storage_kind(storage_kind);
|
|
@@ -363,4 +365,32 @@ svs_runtime::DynamicVamanaIndex* IndexSVSVamana::dynamic_impl() const {
|
|
|
363
365
|
return static_cast<svs_runtime::DynamicVamanaIndex*>(impl);
|
|
364
366
|
}
|
|
365
367
|
|
|
368
|
+
void IndexSVSVamana::map_to(MappedFileIOReader* mf) {
|
|
369
|
+
FAISS_THROW_IF_MSG(
|
|
370
|
+
!is_static,
|
|
371
|
+
"map_to() is only supported for static Vamana indices.");
|
|
372
|
+
FAISS_THROW_IF_MSG(impl, "Cannot map_to: SVS index already loaded.");
|
|
373
|
+
FAISS_THROW_IF_NOT(mf);
|
|
374
|
+
|
|
375
|
+
MmapSpan span = acquire_mmap_span(mf);
|
|
376
|
+
|
|
377
|
+
auto svs_metric = to_svs_metric(metric_type);
|
|
378
|
+
auto svs_storage_kind = to_svs_storage_kind(storage_kind);
|
|
379
|
+
|
|
380
|
+
size_t read_bytes = 0;
|
|
381
|
+
auto status = svs_runtime::VamanaIndex::map_to_memory(
|
|
382
|
+
&impl,
|
|
383
|
+
span.data,
|
|
384
|
+
span.size_bytes,
|
|
385
|
+
svs_metric,
|
|
386
|
+
svs_storage_kind,
|
|
387
|
+
&read_bytes);
|
|
388
|
+
|
|
389
|
+
if (!status.ok()) {
|
|
390
|
+
FAISS_THROW_MSG(status.message());
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
finalize_mmap_span(mf, span, read_bytes, mmap_owner);
|
|
394
|
+
}
|
|
395
|
+
|
|
366
396
|
} // namespace faiss
|
|
@@ -30,11 +30,16 @@
|
|
|
30
30
|
#include <svs/runtime/dynamic_vamana_index.h>
|
|
31
31
|
|
|
32
32
|
#include <iostream>
|
|
33
|
+
#include <memory>
|
|
33
34
|
#include <type_traits>
|
|
34
35
|
#include <vector>
|
|
35
36
|
|
|
36
37
|
namespace faiss {
|
|
37
38
|
|
|
39
|
+
// Forward declarations
|
|
40
|
+
struct MappedFileIOReader;
|
|
41
|
+
struct MmappedFileMappingOwner;
|
|
42
|
+
|
|
38
43
|
struct SearchParametersSVSVamana : public SearchParameters {
|
|
39
44
|
size_t search_window_size = 0;
|
|
40
45
|
size_t search_buffer_capacity = 0;
|
|
@@ -44,7 +49,7 @@ struct SearchParametersSVSVamana : public SearchParameters {
|
|
|
44
49
|
enum SVSStorageKind {
|
|
45
50
|
SVS_FP32,
|
|
46
51
|
SVS_FP16,
|
|
47
|
-
|
|
52
|
+
SVS_SQ8,
|
|
48
53
|
SVS_LVQ4x0,
|
|
49
54
|
SVS_LVQ4x4,
|
|
50
55
|
SVS_LVQ4x8,
|
|
@@ -61,7 +66,7 @@ inline svs_runtime::StorageKind to_svs_storage_kind(SVSStorageKind kind) {
|
|
|
61
66
|
return svs_runtime::StorageKind::FP32;
|
|
62
67
|
case SVS_FP16:
|
|
63
68
|
return svs_runtime::StorageKind::FP16;
|
|
64
|
-
case
|
|
69
|
+
case SVS_SQ8:
|
|
65
70
|
return svs_runtime::StorageKind::SQI8;
|
|
66
71
|
case SVS_LVQ4x0:
|
|
67
72
|
return svs_runtime::StorageKind::LVQ4x0;
|
|
@@ -141,10 +146,18 @@ struct IndexSVSVamana : Index {
|
|
|
141
146
|
void serialize_impl(std::ostream& out) const;
|
|
142
147
|
virtual void deserialize_impl(std::istream& in);
|
|
143
148
|
|
|
149
|
+
/* Memory-mapped deserialization for static indices */
|
|
150
|
+
virtual void map_to(MappedFileIOReader* mf);
|
|
151
|
+
|
|
144
152
|
/* The actual SVS implementation (VamanaIndex is the base for both
|
|
145
153
|
static and dynamic variants) */
|
|
146
154
|
svs_runtime::VamanaIndex* impl{nullptr};
|
|
147
155
|
|
|
156
|
+
// Holds a reference to the memory-mapped file owner to keep the memory
|
|
157
|
+
// mapping alive for the lifetime of this index. Only used when index is
|
|
158
|
+
// loaded via map_to() with memory-mapped I/O.
|
|
159
|
+
std::shared_ptr<MmappedFileMappingOwner> mmap_owner{nullptr};
|
|
160
|
+
|
|
148
161
|
// The SVS runtime API does not expose vector retrieval, so we keep a copy
|
|
149
162
|
// of added vectors to support reconstruct(). When used as a coarse
|
|
150
163
|
// quantizer this holds only nlist centroids.
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
#include <svs/runtime/vamana_index.h>
|
|
30
30
|
|
|
31
31
|
#include <memory>
|
|
32
|
-
#include <span>
|
|
33
32
|
#include "faiss/svs/IndexSVSVamana.h"
|
|
34
33
|
|
|
35
34
|
namespace faiss {
|
|
@@ -122,7 +121,7 @@ void IndexSVSVamanaLeanVec::deserialize_training_data(std::istream& in) {
|
|
|
122
121
|
}
|
|
123
122
|
|
|
124
123
|
void IndexSVSVamanaLeanVec::create_impl(idx_t n, const float* x) {
|
|
125
|
-
|
|
124
|
+
FAISS_THROW_IF_MSG(impl, "impl already created");
|
|
126
125
|
ntotal = 0;
|
|
127
126
|
auto svs_metric = to_svs_metric(metric_type);
|
|
128
127
|
auto svs_storage_kind = to_svs_storage_kind(storage_kind);
|
|
@@ -291,6 +291,11 @@ void exhaustive_inner_product_seq(
|
|
|
291
291
|
BlockResultHandler& res) {
|
|
292
292
|
using SingleResultHandler =
|
|
293
293
|
typename BlockResultHandler::SingleResultHandler;
|
|
294
|
+
|
|
295
|
+
if (nx == 0) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
|
|
294
299
|
[[maybe_unused]] int nt = std::min(int(nx), omp_get_max_threads());
|
|
295
300
|
|
|
296
301
|
#pragma omp parallel num_threads(nt)
|
|
@@ -327,6 +332,11 @@ void exhaustive_L2sqr_seq(
|
|
|
327
332
|
BlockResultHandler& res) {
|
|
328
333
|
using SingleResultHandler =
|
|
329
334
|
typename BlockResultHandler::SingleResultHandler;
|
|
335
|
+
|
|
336
|
+
if (nx == 0) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
330
340
|
[[maybe_unused]] int nt = std::min(int(nx), omp_get_max_threads());
|
|
331
341
|
|
|
332
342
|
#pragma omp parallel num_threads(nt)
|
|
@@ -531,8 +541,10 @@ void exhaustive_L2sqr_blas<Top1BlockResultHandler<CMax<float, int64_t>>>(
|
|
|
531
541
|
return;
|
|
532
542
|
}
|
|
533
543
|
|
|
534
|
-
with_selected_simd_levels<
|
|
535
|
-
if constexpr (
|
|
544
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_A1>([&]<SIMDLevel SL>() {
|
|
545
|
+
if constexpr (
|
|
546
|
+
SL == SIMDLevel::AVX2 || SL == SIMDLevel::AVX512 ||
|
|
547
|
+
SL == SIMDLevel::ARM_SVE) {
|
|
536
548
|
exhaustive_L2sqr_blas_cmax<SL>(x, y, d, nx, ny, res, y_norms);
|
|
537
549
|
} else {
|
|
538
550
|
exhaustive_L2sqr_blas_default_impl<
|
|
@@ -10,18 +10,19 @@
|
|
|
10
10
|
#include <faiss/utils/distances.h>
|
|
11
11
|
|
|
12
12
|
#include <cmath>
|
|
13
|
-
#include <cstdio>
|
|
14
13
|
#include <cstring>
|
|
15
14
|
|
|
16
|
-
#include <faiss/impl/FaissAssert.h>
|
|
17
15
|
#include <faiss/impl/simdlib/simdlib_dispatch.h>
|
|
18
16
|
|
|
19
17
|
#define THE_SIMD_LEVEL SIMDLevel::NONE
|
|
20
18
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
21
19
|
#include <faiss/utils/simd_impl/distances_autovec-inl.h>
|
|
22
20
|
|
|
21
|
+
// This TU is the SIMDLevel::NONE build of the specializations that
|
|
22
|
+
// distances_simdlib256.h emits, so the include is required despite no symbol
|
|
23
|
+
// being named directly here.
|
|
23
24
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
24
|
-
#include <faiss/utils/simd_impl/distances_simdlib256.h>
|
|
25
|
+
#include <faiss/utils/simd_impl/distances_simdlib256.h> // IWYU pragma: keep
|
|
25
26
|
|
|
26
27
|
namespace faiss {
|
|
27
28
|
|