faiss 0.6.2 → 0.6.4
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/Clustering.h +8 -0
- 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 +24 -4
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +16 -145
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +0 -6
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +8 -18
- data/vendor/faiss/faiss/IndexBinaryIVF.h +8 -1
- 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 +21 -54
- data/vendor/faiss/faiss/IndexFlat.h +2 -2
- data/vendor/faiss/faiss/IndexHNSW.cpp +311 -102
- data/vendor/faiss/faiss/IndexHNSW.h +31 -7
- data/vendor/faiss/faiss/IndexIDMap.cpp +26 -8
- data/vendor/faiss/faiss/IndexIDMap.h +2 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +36 -10
- 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 +49 -23
- data/vendor/faiss/faiss/IndexIVFPQ.h +11 -0
- 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 +5 -5
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +6 -5
- data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
- data/vendor/faiss/faiss/SuperKMeans.cpp +286 -247
- data/vendor/faiss/faiss/SuperKMeans.h +33 -2
- data/vendor/faiss/faiss/VectorTransform.cpp +71 -2
- data/vendor/faiss/faiss/VectorTransform.h +3 -0
- data/vendor/faiss/faiss/clone_index.cpp +8 -0
- data/vendor/faiss/faiss/factory_tools.cpp +47 -4
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +1 -5
- data/vendor/faiss/faiss/gpu/GpuDistance.h +2 -5
- data/vendor/faiss/faiss/gpu/GpuIndex.h +38 -16
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +71 -1
- 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/AdditiveQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +7 -4
- 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 +528 -267
- data/vendor/faiss/faiss/impl/HNSW.h +46 -7
- data/vendor/faiss/faiss/impl/IDSelector.h +44 -0
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/impl/NNDescent.cpp +10 -3
- data/vendor/faiss/faiss/impl/NSG.cpp +3 -1
- data/vendor/faiss/faiss/impl/Panorama.h +20 -9
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +38 -26
- 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 +239 -72
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +66 -4
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +4 -13
- data/vendor/faiss/faiss/impl/ResultHandler.h +34 -34
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +287 -84
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +26 -10
- 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 +90 -14
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/expanded_scanners.h +5 -1
- data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +1 -0
- 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 +491 -50
- data/vendor/faiss/faiss/impl/index_write.cpp +86 -30
- 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/IVFPQScanner_impl.h +73 -39
- 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/pq_code_distance/pq_code_distance-generic.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 +887 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +2 -2
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +9 -8
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +90 -24
- 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 +169 -13
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +125 -26
- data/vendor/faiss/faiss/impl/simd_dispatch.h +70 -31
- data/vendor/faiss/faiss/index_factory.cpp +40 -7
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +9 -6
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +29 -8
- 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 +47 -5
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +23 -3
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +4 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +10 -4
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +2 -1
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
- data/vendor/faiss/faiss/utils/distances.cpp +30 -11
- data/vendor/faiss/faiss/utils/distances_dispatch.h +30 -24
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +1 -1
- 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 +16 -10
- data/vendor/faiss/faiss/utils/hamming.h +10 -1
- data/vendor/faiss/faiss/utils/hamming_distance/common.h +14 -3
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_vpopcnt.cpp +24 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +1 -1
- data/vendor/faiss/faiss/utils/hamming_distance/{hamming_computer-avx512_spr.h → hamming_computer-avx512_vpopcnt.h} +85 -24
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +141 -0
- 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_arm_sve.cpp +194 -30
- 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 +198 -18
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +330 -40
- data/vendor/faiss/faiss/utils/simd_impl/{rabitq_avx512_spr.cpp → rabitq_avx512_vpopcnt.cpp} +112 -23
- 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_impl/super_kmeans_dispatch.h +2 -7
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +6 -1
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_sve.cpp +34 -0
- data/vendor/faiss/faiss/utils/simd_levels.cpp +196 -47
- data/vendor/faiss/faiss/utils/simd_levels.h +33 -8
- data/vendor/faiss/faiss/utils/utils.cpp +9 -27
- metadata +21 -5
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +0 -15
|
@@ -39,17 +39,50 @@ namespace faiss {
|
|
|
39
39
|
|
|
40
40
|
namespace {
|
|
41
41
|
|
|
42
|
+
// Whether the computer can measure a whole batch of codes in one call.
|
|
42
43
|
template <class HammingComputer>
|
|
43
|
-
|
|
44
|
+
constexpr bool has_hamming_batch =
|
|
45
|
+
requires(const uint8_t* tile, const uint8_t* codes, int32_t* dis) {
|
|
46
|
+
HammingComputer::batch_size;
|
|
47
|
+
HammingComputer::get_code_size();
|
|
48
|
+
HammingComputer::build_batch_query(tile, nullptr);
|
|
49
|
+
HammingComputer::hamming_batch(tile, codes, dis);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// The query repeated batch_size times, which is what hamming_batch() XORs
|
|
53
|
+
// against. Empty for a computer that does not batch, so those scanners carry
|
|
54
|
+
// neither the buffer nor its alignment.
|
|
55
|
+
template <class HammingComputer>
|
|
56
|
+
struct BatchQueryTile {};
|
|
57
|
+
|
|
58
|
+
template <class HammingComputer>
|
|
59
|
+
requires has_hamming_batch<HammingComputer>
|
|
60
|
+
struct BatchQueryTile<HammingComputer> {
|
|
61
|
+
alignas(64) uint8_t batch_query
|
|
62
|
+
[HammingComputer::batch_size * HammingComputer::get_code_size()];
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
template <class HammingComputer>
|
|
66
|
+
struct IVFBinaryScannerL2 : BinaryInvertedListScanner,
|
|
67
|
+
BatchQueryTile<HammingComputer> {
|
|
44
68
|
HammingComputer hc;
|
|
45
69
|
size_t code_size;
|
|
46
70
|
bool store_pairs;
|
|
47
71
|
|
|
48
72
|
IVFBinaryScannerL2(size_t code_size_, bool store_pairs_)
|
|
49
|
-
: code_size(code_size_), store_pairs(store_pairs_) {
|
|
73
|
+
: code_size(code_size_), store_pairs(store_pairs_) {
|
|
74
|
+
if constexpr (has_hamming_batch<HammingComputer>) {
|
|
75
|
+
// The batch kernel reads a fixed stride, so a caller that pairs
|
|
76
|
+
// this computer with another code size would read past the codes.
|
|
77
|
+
FAISS_THROW_IF_NOT(code_size == HammingComputer::get_code_size());
|
|
78
|
+
}
|
|
79
|
+
}
|
|
50
80
|
|
|
51
81
|
void set_query(const uint8_t* query_vector) override {
|
|
52
82
|
hc.set(query_vector, code_size);
|
|
83
|
+
if constexpr (has_hamming_batch<HammingComputer>) {
|
|
84
|
+
HammingComputer::build_batch_query(query_vector, this->batch_query);
|
|
85
|
+
}
|
|
53
86
|
}
|
|
54
87
|
|
|
55
88
|
idx_t list_no = 0;
|
|
@@ -61,6 +94,31 @@ struct IVFBinaryScannerL2 : BinaryInvertedListScanner {
|
|
|
61
94
|
return hc.hamming(code);
|
|
62
95
|
}
|
|
63
96
|
|
|
97
|
+
// Measures whole batches while at least batch_size codes remain, then
|
|
98
|
+
// leaves codes and j on the first code the caller must measure singly.
|
|
99
|
+
// bound is read per lane, so a caller that raises its heap top inside
|
|
100
|
+
// accept prunes the rest of the batch.
|
|
101
|
+
template <class Accept>
|
|
102
|
+
void scan_batch_prefix(
|
|
103
|
+
size_t n,
|
|
104
|
+
const uint8_t* __restrict& codes,
|
|
105
|
+
size_t& j,
|
|
106
|
+
const uint32_t& bound,
|
|
107
|
+
Accept&& accept) const {
|
|
108
|
+
if constexpr (has_hamming_batch<HammingComputer>) {
|
|
109
|
+
constexpr size_t B = HammingComputer::batch_size;
|
|
110
|
+
int32_t batch[B];
|
|
111
|
+
for (; j + B <= n; j += B, codes += B * code_size) {
|
|
112
|
+
HammingComputer::hamming_batch(this->batch_query, codes, batch);
|
|
113
|
+
for (size_t t = 0; t < B; t++) {
|
|
114
|
+
if (static_cast<uint32_t>(batch[t]) < bound) {
|
|
115
|
+
accept(batch[t], j + t);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
64
122
|
size_t scan_codes(
|
|
65
123
|
size_t n,
|
|
66
124
|
const uint8_t* __restrict codes,
|
|
@@ -70,15 +128,25 @@ struct IVFBinaryScannerL2 : BinaryInvertedListScanner {
|
|
|
70
128
|
size_t k) const override {
|
|
71
129
|
using C = CMax<int32_t, idx_t>;
|
|
72
130
|
|
|
131
|
+
uint32_t bound = static_cast<uint32_t>(simi[0]);
|
|
132
|
+
|
|
73
133
|
size_t nup = 0;
|
|
74
|
-
|
|
134
|
+
size_t j = 0;
|
|
135
|
+
|
|
136
|
+
auto accept = [&](int32_t dis, size_t at) {
|
|
137
|
+
idx_t id = store_pairs ? lo_build(list_no, at) : ids[at];
|
|
138
|
+
heap_replace_top<C>(k, simi, idxi, dis, id);
|
|
139
|
+
bound = static_cast<uint32_t>(simi[0]);
|
|
140
|
+
nup++;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
scan_batch_prefix(n, codes, j, bound, accept);
|
|
144
|
+
|
|
145
|
+
for (; j < n; j++, codes += code_size) {
|
|
75
146
|
uint32_t dis = hc.hamming(codes);
|
|
76
|
-
if (dis <
|
|
77
|
-
|
|
78
|
-
heap_replace_top<C>(k, simi, idxi, dis, id);
|
|
79
|
-
nup++;
|
|
147
|
+
if (dis < bound) {
|
|
148
|
+
accept(static_cast<int32_t>(dis), j);
|
|
80
149
|
}
|
|
81
|
-
codes += code_size;
|
|
82
150
|
}
|
|
83
151
|
return nup;
|
|
84
152
|
}
|
|
@@ -89,13 +157,21 @@ struct IVFBinaryScannerL2 : BinaryInvertedListScanner {
|
|
|
89
157
|
const idx_t* __restrict ids,
|
|
90
158
|
int radius,
|
|
91
159
|
RangeQueryResult& result) const override {
|
|
92
|
-
|
|
160
|
+
const uint32_t bound = static_cast<uint32_t>(radius);
|
|
161
|
+
size_t j = 0;
|
|
162
|
+
|
|
163
|
+
auto accept = [&](int32_t dis, size_t at) {
|
|
164
|
+
int64_t id = store_pairs ? lo_build(list_no, at) : ids[at];
|
|
165
|
+
result.add(static_cast<uint32_t>(dis), id);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
scan_batch_prefix(n, codes, j, bound, accept);
|
|
169
|
+
|
|
170
|
+
for (; j < n; j++, codes += code_size) {
|
|
93
171
|
uint32_t dis = hc.hamming(codes);
|
|
94
|
-
if (dis <
|
|
95
|
-
|
|
96
|
-
result.add(dis, id);
|
|
172
|
+
if (dis < bound) {
|
|
173
|
+
accept(static_cast<int32_t>(dis), j);
|
|
97
174
|
}
|
|
98
|
-
codes += code_size;
|
|
99
175
|
}
|
|
100
176
|
}
|
|
101
177
|
};
|
|
@@ -292,7 +368,7 @@ void search_knn_hamming_per_invlist(
|
|
|
292
368
|
nprobe = std::min((idx_t)ivf->nlist, nprobe);
|
|
293
369
|
idx_t max_codes = params ? params->max_codes : ivf->max_codes;
|
|
294
370
|
FAISS_THROW_IF_NOT(max_codes == 0);
|
|
295
|
-
|
|
371
|
+
FAISS_THROW_IF_MSG(store_pairs, "store_pairs is not supported here");
|
|
296
372
|
|
|
297
373
|
// reorder buckets
|
|
298
374
|
std::vector<int64_t> lims(n + 1);
|
|
@@ -9,17 +9,17 @@
|
|
|
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/utils/hamming_distance/hamming_computer-avx2.h>
|
|
14
14
|
|
|
15
15
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
16
|
-
#include <faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h>
|
|
16
|
+
#include <faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h> // IWYU pragma: keep
|
|
17
17
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
18
|
-
#include <faiss/impl/binary_hamming/IndexBinaryHash_impl.h>
|
|
18
|
+
#include <faiss/impl/binary_hamming/IndexBinaryHash_impl.h> // IWYU pragma: keep
|
|
19
19
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
20
20
|
#include <faiss/impl/binary_hamming/IndexBinaryIVF_impl.h>
|
|
21
21
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
22
|
-
#include <faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h>
|
|
22
|
+
#include <faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h> // IWYU pragma: keep
|
|
23
23
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
24
24
|
#include <faiss/impl/binary_hamming/IndexPQ_impl.h>
|
|
25
25
|
|
|
@@ -35,12 +35,16 @@ size_t run_scan_codes1(
|
|
|
35
35
|
size_t list_no = scanner.list_no;
|
|
36
36
|
size_t code_size = scanner.code_size;
|
|
37
37
|
const IDSelector* sel = scanner.sel;
|
|
38
|
+
// If the selector implements IDSelectorWithContext, hand it the scan
|
|
39
|
+
// context (ids, list_size, j) so it can exploit scan-order locality; the
|
|
40
|
+
// dispatch caches the once-per-list RTTI detection.
|
|
41
|
+
const IDSelectorContextDispatch sel_dispatch(sel, store_pairs);
|
|
38
42
|
float threshold = handler.threshold;
|
|
39
43
|
for (size_t j = 0; j < list_size; j++) {
|
|
40
44
|
if (use_sel) {
|
|
41
45
|
int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
|
|
42
46
|
// skip code without computing distance
|
|
43
|
-
if (!
|
|
47
|
+
if (!sel_dispatch.is_member(id, IDScanContext{ids, list_size, j})) {
|
|
44
48
|
codes += code_size;
|
|
45
49
|
continue;
|
|
46
50
|
}
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
#include <faiss/impl/fast_scan/accumulate_loops.h>
|
|
35
35
|
#include <faiss/impl/fast_scan/fast_scan.h>
|
|
36
|
+
#include <faiss/utils/simd_levels.h>
|
|
36
37
|
|
|
37
38
|
#if defined(COMPILE_SIMD_AVX512) && defined(__AVX512F__)
|
|
38
39
|
#include <faiss/impl/fast_scan/accumulate_loops_512.h>
|
|
@@ -114,8 +115,40 @@ struct ScannerMixIn : FastScanCodeScanner {
|
|
|
114
115
|
constexpr bool use_avx512_qbs = false;
|
|
115
116
|
#endif
|
|
116
117
|
if constexpr (use_avx512_qbs) {
|
|
117
|
-
//
|
|
118
|
-
|
|
118
|
+
// AMD Zen 4 / Zen 4c ("Bergamo", family 0x19) split 512-bit
|
|
119
|
+
// ops over a 256-bit datapath, so the 512-bit QBS kernel yields no
|
|
120
|
+
// throughput gain but pays extra per-block LUT-assembly and
|
|
121
|
+
// cross-lane reduction overhead (measured ~14% search regression
|
|
122
|
+
// for PQ8x4fs / PQ16x4fs). Route those CPUs to the 256-bit (AVX2)
|
|
123
|
+
// QBS kernel instead -- same output, no downside on Zen 4. This is
|
|
124
|
+
// a process-constant runtime branch, hoisted out of the inner
|
|
125
|
+
// accumulate loop. Intel AVX-512 keeps the 512-bit kernel.
|
|
126
|
+
if (SIMDConfig::avx512_split) {
|
|
127
|
+
if (pq2x4_scale) {
|
|
128
|
+
NormTableScaler<SIMDLevel::AVX2> scaler(pq2x4_scale);
|
|
129
|
+
pq4_accumulate_loop_qbs_fixed_scaler_256<SIMDLevel::AVX2>(
|
|
130
|
+
qbs,
|
|
131
|
+
nb,
|
|
132
|
+
nsq,
|
|
133
|
+
codes,
|
|
134
|
+
LUT,
|
|
135
|
+
handler_,
|
|
136
|
+
scaler,
|
|
137
|
+
block_stride);
|
|
138
|
+
} else {
|
|
139
|
+
DummyScaler<SIMDLevel::AVX2> dummy;
|
|
140
|
+
pq4_accumulate_loop_qbs_fixed_scaler_256<SIMDLevel::AVX2>(
|
|
141
|
+
qbs,
|
|
142
|
+
nb,
|
|
143
|
+
nsq,
|
|
144
|
+
codes,
|
|
145
|
+
LUT,
|
|
146
|
+
handler_,
|
|
147
|
+
dummy,
|
|
148
|
+
block_stride);
|
|
149
|
+
}
|
|
150
|
+
} else if (pq2x4_scale) {
|
|
151
|
+
// Use 512-bit QBS kernels with properly-leveled scalers.
|
|
119
152
|
NormTableScaler<THE_LEVEL_TO_DISPATCH> scaler(pq2x4_scale);
|
|
120
153
|
pq4_accumulate_loop_qbs_fixed_scaler_512(
|
|
121
154
|
qbs,
|
|
@@ -30,7 +30,7 @@ void LockVector::prepare(size_t new_size) {
|
|
|
30
30
|
// Just destroy old and init fresh; omp_lock_t is not copyable.
|
|
31
31
|
clear();
|
|
32
32
|
data_ = static_cast<omp_lock_t*>(malloc(new_cap * sizeof(omp_lock_t)));
|
|
33
|
-
FAISS_THROW_IF_NOT(data_
|
|
33
|
+
FAISS_THROW_IF_NOT(data_);
|
|
34
34
|
capacity_ = new_cap;
|
|
35
35
|
}
|
|
36
36
|
for (size_t i = size_; i < new_size; i++) {
|