/root/doris/contrib/faiss/faiss/IndexBinaryIVF.cpp
Line | Count | Source |
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 | | #include <faiss/IndexBinaryIVF.h> |
11 | | |
12 | | #include <omp.h> |
13 | | #include <cinttypes> |
14 | | #include <cstdio> |
15 | | |
16 | | #include <algorithm> |
17 | | #include <memory> |
18 | | |
19 | | #include <faiss/IndexFlat.h> |
20 | | #include <faiss/IndexLSH.h> |
21 | | #include <faiss/impl/AuxIndexStructures.h> |
22 | | #include <faiss/impl/FaissAssert.h> |
23 | | #include <faiss/utils/hamming.h> |
24 | | #include <faiss/utils/sorting.h> |
25 | | #include <faiss/utils/utils.h> |
26 | | |
27 | | namespace faiss { |
28 | | |
29 | | IndexBinaryIVF::IndexBinaryIVF(IndexBinary* quantizer, size_t d, size_t nlist) |
30 | 0 | : IndexBinary(d), |
31 | 0 | invlists(new ArrayInvertedLists(nlist, code_size)), |
32 | 0 | quantizer(quantizer), |
33 | 0 | nlist(nlist) { |
34 | 0 | FAISS_THROW_IF_NOT(d == quantizer->d); |
35 | 0 | is_trained = quantizer->is_trained && (quantizer->ntotal == nlist); |
36 | 0 | cp.niter = 10; |
37 | 0 | } |
38 | | |
39 | 0 | IndexBinaryIVF::IndexBinaryIVF() = default; |
40 | | |
41 | 0 | void IndexBinaryIVF::add(idx_t n, const uint8_t* x) { |
42 | 0 | add_with_ids(n, x, nullptr); |
43 | 0 | } |
44 | | |
45 | | void IndexBinaryIVF::add_with_ids( |
46 | | idx_t n, |
47 | | const uint8_t* x, |
48 | 0 | const idx_t* xids) { |
49 | 0 | add_core(n, x, xids, nullptr); |
50 | 0 | } |
51 | | |
52 | | void IndexBinaryIVF::add_core( |
53 | | idx_t n, |
54 | | const uint8_t* x, |
55 | | const idx_t* xids, |
56 | 0 | const idx_t* precomputed_idx) { |
57 | 0 | FAISS_THROW_IF_NOT(is_trained); |
58 | 0 | assert(invlists); |
59 | 0 | direct_map.check_can_add(xids); |
60 | |
|
61 | 0 | const idx_t* idx; |
62 | |
|
63 | 0 | std::unique_ptr<idx_t[]> scoped_idx; |
64 | |
|
65 | 0 | if (precomputed_idx) { |
66 | 0 | idx = precomputed_idx; |
67 | 0 | } else { |
68 | 0 | scoped_idx.reset(new idx_t[n]); |
69 | 0 | quantizer->assign(n, x, scoped_idx.get()); |
70 | 0 | idx = scoped_idx.get(); |
71 | 0 | } |
72 | |
|
73 | 0 | idx_t n_add = 0; |
74 | 0 | for (size_t i = 0; i < n; i++) { |
75 | 0 | idx_t id = xids ? xids[i] : ntotal + i; |
76 | 0 | idx_t list_no = idx[i]; |
77 | |
|
78 | 0 | if (list_no < 0) { |
79 | 0 | direct_map.add_single_id(id, -1, 0); |
80 | 0 | } else { |
81 | 0 | const uint8_t* xi = x + i * code_size; |
82 | 0 | size_t offset = invlists->add_entry(list_no, id, xi); |
83 | |
|
84 | 0 | direct_map.add_single_id(id, list_no, offset); |
85 | 0 | } |
86 | |
|
87 | 0 | n_add++; |
88 | 0 | } |
89 | 0 | if (verbose) { |
90 | 0 | printf("IndexBinaryIVF::add_with_ids: added " |
91 | 0 | "%" PRId64 " / %" PRId64 " vectors\n", |
92 | 0 | n_add, |
93 | 0 | n); |
94 | 0 | } |
95 | 0 | ntotal += n_add; |
96 | 0 | } |
97 | | |
98 | 0 | void IndexBinaryIVF::make_direct_map(bool b) { |
99 | 0 | if (b) { |
100 | 0 | direct_map.set_type(DirectMap::Array, invlists, ntotal); |
101 | 0 | } else { |
102 | 0 | direct_map.set_type(DirectMap::NoMap, invlists, ntotal); |
103 | 0 | } |
104 | 0 | } |
105 | | |
106 | 0 | void IndexBinaryIVF::set_direct_map_type(DirectMap::Type type) { |
107 | 0 | direct_map.set_type(type, invlists, ntotal); |
108 | 0 | } |
109 | | |
110 | | void IndexBinaryIVF::search( |
111 | | idx_t n, |
112 | | const uint8_t* x, |
113 | | idx_t k, |
114 | | int32_t* distances, |
115 | | idx_t* labels, |
116 | 0 | const SearchParameters* params) const { |
117 | 0 | FAISS_THROW_IF_NOT_MSG( |
118 | 0 | !params, "search params not supported for this index"); |
119 | 0 | FAISS_THROW_IF_NOT(k > 0); |
120 | 0 | FAISS_THROW_IF_NOT(nprobe > 0); |
121 | | |
122 | 0 | const size_t nprobe_2 = std::min(nlist, this->nprobe); |
123 | 0 | std::unique_ptr<idx_t[]> idx(new idx_t[n * nprobe_2]); |
124 | 0 | std::unique_ptr<int32_t[]> coarse_dis(new int32_t[n * nprobe_2]); |
125 | |
|
126 | 0 | double t0 = getmillisecs(); |
127 | 0 | quantizer->search(n, x, nprobe_2, coarse_dis.get(), idx.get()); |
128 | 0 | indexIVF_stats.quantization_time += getmillisecs() - t0; |
129 | |
|
130 | 0 | t0 = getmillisecs(); |
131 | 0 | invlists->prefetch_lists(idx.get(), n * nprobe_2); |
132 | |
|
133 | 0 | search_preassigned( |
134 | 0 | n, x, k, idx.get(), coarse_dis.get(), distances, labels, false); |
135 | 0 | indexIVF_stats.search_time += getmillisecs() - t0; |
136 | 0 | } |
137 | | |
138 | 0 | void IndexBinaryIVF::reconstruct(idx_t key, uint8_t* recons) const { |
139 | 0 | idx_t lo = direct_map.get(key); |
140 | 0 | reconstruct_from_offset(lo_listno(lo), lo_offset(lo), recons); |
141 | 0 | } |
142 | | |
143 | 0 | void IndexBinaryIVF::reconstruct_n(idx_t i0, idx_t ni, uint8_t* recons) const { |
144 | 0 | FAISS_THROW_IF_NOT(ni == 0 || (i0 >= 0 && i0 + ni <= ntotal)); |
145 | | |
146 | 0 | for (idx_t list_no = 0; list_no < nlist; list_no++) { |
147 | 0 | size_t list_size = invlists->list_size(list_no); |
148 | 0 | const idx_t* idlist = invlists->get_ids(list_no); |
149 | |
|
150 | 0 | for (idx_t offset = 0; offset < list_size; offset++) { |
151 | 0 | idx_t id = idlist[offset]; |
152 | 0 | if (!(id >= i0 && id < i0 + ni)) { |
153 | 0 | continue; |
154 | 0 | } |
155 | | |
156 | 0 | uint8_t* reconstructed = recons + (id - i0) * d; |
157 | 0 | reconstruct_from_offset(list_no, offset, reconstructed); |
158 | 0 | } |
159 | 0 | } |
160 | 0 | } |
161 | | |
162 | | void IndexBinaryIVF::search_and_reconstruct( |
163 | | idx_t n, |
164 | | const uint8_t* __restrict x, |
165 | | idx_t k, |
166 | | int32_t* __restrict distances, |
167 | | idx_t* __restrict labels, |
168 | | uint8_t* __restrict recons, |
169 | 0 | const SearchParameters* params) const { |
170 | 0 | FAISS_THROW_IF_NOT_MSG( |
171 | 0 | !params, "search params not supported for this index"); |
172 | 0 | const size_t nprobe_2 = std::min(nlist, this->nprobe); |
173 | 0 | FAISS_THROW_IF_NOT(k > 0); |
174 | 0 | FAISS_THROW_IF_NOT(nprobe_2 > 0); |
175 | | |
176 | 0 | std::unique_ptr<idx_t[]> idx(new idx_t[n * nprobe_2]); |
177 | 0 | std::unique_ptr<int32_t[]> coarse_dis(new int32_t[n * nprobe_2]); |
178 | |
|
179 | 0 | quantizer->search(n, x, nprobe_2, coarse_dis.get(), idx.get()); |
180 | |
|
181 | 0 | invlists->prefetch_lists(idx.get(), n * nprobe_2); |
182 | | |
183 | | // search_preassigned() with `store_pairs` enabled to obtain the list_no |
184 | | // and offset into `codes` for reconstruction |
185 | 0 | search_preassigned( |
186 | 0 | n, |
187 | 0 | x, |
188 | 0 | k, |
189 | 0 | idx.get(), |
190 | 0 | coarse_dis.get(), |
191 | 0 | distances, |
192 | 0 | labels, |
193 | 0 | /* store_pairs */ true); |
194 | 0 | for (idx_t i = 0; i < n; ++i) { |
195 | 0 | for (idx_t j = 0; j < k; ++j) { |
196 | 0 | idx_t ij = i * k + j; |
197 | 0 | idx_t key = labels[ij]; |
198 | 0 | uint8_t* reconstructed = recons + ij * d; |
199 | 0 | if (key < 0) { |
200 | | // Fill with NaNs |
201 | 0 | memset(reconstructed, -1, sizeof(*reconstructed) * d); |
202 | 0 | } else { |
203 | 0 | int list_no = key >> 32; |
204 | 0 | int offset = key & 0xffffffff; |
205 | | |
206 | | // Update label to the actual id |
207 | 0 | labels[ij] = invlists->get_single_id(list_no, offset); |
208 | |
|
209 | 0 | reconstruct_from_offset(list_no, offset, reconstructed); |
210 | 0 | } |
211 | 0 | } |
212 | 0 | } |
213 | 0 | } |
214 | | |
215 | | void IndexBinaryIVF::reconstruct_from_offset( |
216 | | idx_t list_no, |
217 | | idx_t offset, |
218 | 0 | uint8_t* recons) const { |
219 | 0 | memcpy(recons, invlists->get_single_code(list_no, offset), code_size); |
220 | 0 | } |
221 | | |
222 | 0 | void IndexBinaryIVF::reset() { |
223 | 0 | direct_map.clear(); |
224 | 0 | invlists->reset(); |
225 | 0 | ntotal = 0; |
226 | 0 | } |
227 | | |
228 | 0 | size_t IndexBinaryIVF::remove_ids(const IDSelector& sel) { |
229 | 0 | size_t nremove = direct_map.remove_ids(sel, invlists); |
230 | 0 | ntotal -= nremove; |
231 | 0 | return nremove; |
232 | 0 | } |
233 | | |
234 | 0 | void IndexBinaryIVF::train(idx_t n, const uint8_t* x) { |
235 | 0 | if (verbose) { |
236 | 0 | printf("Training quantizer\n"); |
237 | 0 | } |
238 | |
|
239 | 0 | if (quantizer->is_trained && (quantizer->ntotal == nlist)) { |
240 | 0 | if (verbose) { |
241 | 0 | printf("IVF quantizer does not need training.\n"); |
242 | 0 | } |
243 | 0 | } else { |
244 | 0 | if (verbose) { |
245 | 0 | printf("Training quantizer on %" PRId64 " vectors in %dD\n", n, d); |
246 | 0 | } |
247 | |
|
248 | 0 | Clustering clus(d, nlist, cp); |
249 | 0 | quantizer->reset(); |
250 | |
|
251 | 0 | IndexFlatL2 index_tmp(d); |
252 | |
|
253 | 0 | if (clustering_index && verbose) { |
254 | 0 | printf("using clustering_index of dimension %d to do the clustering\n", |
255 | 0 | clustering_index->d); |
256 | 0 | } |
257 | | |
258 | | // LSH codec that is able to convert the binary vectors to floats. |
259 | 0 | IndexLSH codec(d, d, false, false); |
260 | |
|
261 | 0 | clus.train_encoded( |
262 | 0 | n, x, &codec, clustering_index ? *clustering_index : index_tmp); |
263 | | |
264 | | // convert clusters to binary |
265 | 0 | std::unique_ptr<uint8_t[]> x_b(new uint8_t[clus.k * code_size]); |
266 | 0 | real_to_binary(d * clus.k, clus.centroids.data(), x_b.get()); |
267 | |
|
268 | 0 | quantizer->add(clus.k, x_b.get()); |
269 | 0 | quantizer->is_trained = true; |
270 | 0 | } |
271 | |
|
272 | 0 | is_trained = true; |
273 | 0 | } |
274 | | |
275 | | void IndexBinaryIVF::check_compatible_for_merge( |
276 | 0 | const IndexBinary& otherIndex) const { |
277 | 0 | auto other = dynamic_cast<const IndexBinaryIVF*>(&otherIndex); |
278 | 0 | FAISS_THROW_IF_NOT(other); |
279 | 0 | FAISS_THROW_IF_NOT(other->d == d); |
280 | 0 | FAISS_THROW_IF_NOT(other->nlist == nlist); |
281 | 0 | FAISS_THROW_IF_NOT(other->code_size == code_size); |
282 | 0 | FAISS_THROW_IF_NOT_MSG( |
283 | 0 | direct_map.no() && other->direct_map.no(), |
284 | 0 | "direct map copy not implemented"); |
285 | 0 | FAISS_THROW_IF_NOT_MSG( |
286 | 0 | typeid(*this) == typeid(other), |
287 | 0 | "can only merge indexes of the same type"); |
288 | 0 | } |
289 | | |
290 | 0 | void IndexBinaryIVF::merge_from(IndexBinary& otherIndex, idx_t add_id) { |
291 | | // minimal sanity checks |
292 | 0 | check_compatible_for_merge(otherIndex); |
293 | 0 | auto other = static_cast<IndexBinaryIVF*>(&otherIndex); |
294 | 0 | invlists->merge_from(other->invlists, add_id); |
295 | 0 | ntotal += other->ntotal; |
296 | 0 | other->ntotal = 0; |
297 | 0 | } |
298 | | |
299 | 0 | void IndexBinaryIVF::replace_invlists(InvertedLists* il, bool own) { |
300 | 0 | FAISS_THROW_IF_NOT(il->nlist == nlist && il->code_size == code_size); |
301 | 0 | if (own_invlists) { |
302 | 0 | delete invlists; |
303 | 0 | } |
304 | 0 | invlists = il; |
305 | 0 | own_invlists = own; |
306 | 0 | } |
307 | | |
308 | | namespace { |
309 | | |
310 | | template <class HammingComputer> |
311 | | struct IVFBinaryScannerL2 : BinaryInvertedListScanner { |
312 | | HammingComputer hc; |
313 | | size_t code_size; |
314 | | bool store_pairs; |
315 | | |
316 | | IVFBinaryScannerL2(size_t code_size, bool store_pairs) |
317 | 0 | : code_size(code_size), store_pairs(store_pairs) {} Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer4EEC2Emb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer8EEC2Emb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer16EEC2Emb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer20EEC2Emb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer32EEC2Emb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer64EEC2Emb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_22HammingComputerDefaultEEC2Emb |
318 | | |
319 | 0 | void set_query(const uint8_t* query_vector) override { |
320 | 0 | hc.set(query_vector, code_size); |
321 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer4EE9set_queryEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer8EE9set_queryEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer16EE9set_queryEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer20EE9set_queryEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer32EE9set_queryEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer64EE9set_queryEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_22HammingComputerDefaultEE9set_queryEPKh |
322 | | |
323 | | idx_t list_no; |
324 | 0 | void set_list(idx_t list_no_2, uint8_t /* coarse_dis */) override { |
325 | 0 | this->list_no = list_no_2; |
326 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer4EE8set_listElh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer8EE8set_listElh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer16EE8set_listElh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer20EE8set_listElh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer32EE8set_listElh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer64EE8set_listElh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_22HammingComputerDefaultEE8set_listElh |
327 | | |
328 | 0 | uint32_t distance_to_code(const uint8_t* code) const override { |
329 | 0 | return hc.hamming(code); |
330 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer4EE16distance_to_codeEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer8EE16distance_to_codeEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer16EE16distance_to_codeEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer20EE16distance_to_codeEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer32EE16distance_to_codeEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer64EE16distance_to_codeEPKh Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_22HammingComputerDefaultEE16distance_to_codeEPKh |
331 | | |
332 | | size_t scan_codes( |
333 | | size_t n, |
334 | | const uint8_t* __restrict codes, |
335 | | const idx_t* __restrict ids, |
336 | | int32_t* __restrict simi, |
337 | | idx_t* __restrict idxi, |
338 | 0 | size_t k) const override { |
339 | 0 | using C = CMax<int32_t, idx_t>; |
340 | |
|
341 | 0 | size_t nup = 0; |
342 | 0 | for (size_t j = 0; j < n; j++) { |
343 | 0 | uint32_t dis = hc.hamming(codes); |
344 | 0 | if (dis < simi[0]) { |
345 | 0 | idx_t id = store_pairs ? lo_build(list_no, j) : ids[j]; |
346 | 0 | heap_replace_top<C>(k, simi, idxi, dis, id); |
347 | 0 | nup++; |
348 | 0 | } |
349 | 0 | codes += code_size; |
350 | 0 | } |
351 | 0 | return nup; |
352 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer4EE10scan_codesEmPKhPKlPiPlm Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer8EE10scan_codesEmPKhPKlPiPlm Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer16EE10scan_codesEmPKhPKlPiPlm Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer20EE10scan_codesEmPKhPKlPiPlm Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer32EE10scan_codesEmPKhPKlPiPlm Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer64EE10scan_codesEmPKhPKlPiPlm Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_22HammingComputerDefaultEE10scan_codesEmPKhPKlPiPlm |
353 | | |
354 | | void scan_codes_range( |
355 | | size_t n, |
356 | | const uint8_t* __restrict codes, |
357 | | const idx_t* __restrict ids, |
358 | | int radius, |
359 | 0 | RangeQueryResult& result) const override { |
360 | 0 | for (size_t j = 0; j < n; j++) { |
361 | 0 | uint32_t dis = hc.hamming(codes); |
362 | 0 | if (dis < radius) { |
363 | 0 | int64_t id = store_pairs ? lo_build(list_no, j) : ids[j]; |
364 | 0 | result.add(dis, id); |
365 | 0 | } |
366 | 0 | codes += code_size; |
367 | 0 | } |
368 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer4EE16scan_codes_rangeEmPKhPKliRNS_16RangeQueryResultE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_16HammingComputer8EE16scan_codes_rangeEmPKhPKliRNS_16RangeQueryResultE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer16EE16scan_codes_rangeEmPKhPKliRNS_16RangeQueryResultE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer20EE16scan_codes_rangeEmPKhPKliRNS_16RangeQueryResultE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer32EE16scan_codes_rangeEmPKhPKliRNS_16RangeQueryResultE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_17HammingComputer64EE16scan_codes_rangeEmPKhPKliRNS_16RangeQueryResultE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZNK5faiss12_GLOBAL__N_118IVFBinaryScannerL2INS_22HammingComputerDefaultEE16scan_codes_rangeEmPKhPKliRNS_16RangeQueryResultE |
369 | | }; |
370 | | |
371 | | void search_knn_hamming_heap( |
372 | | const IndexBinaryIVF* ivf, |
373 | | size_t n, |
374 | | const uint8_t* __restrict x, |
375 | | idx_t k, |
376 | | const idx_t* __restrict keys, |
377 | | const int32_t* __restrict coarse_dis, |
378 | | int32_t* __restrict distances, |
379 | | idx_t* __restrict labels, |
380 | | bool store_pairs, |
381 | 0 | const IVFSearchParameters* params) { |
382 | 0 | idx_t nprobe = params ? params->nprobe : ivf->nprobe; |
383 | 0 | nprobe = std::min((idx_t)ivf->nlist, nprobe); |
384 | 0 | idx_t max_codes = params ? params->max_codes : ivf->max_codes; |
385 | 0 | MetricType metric_type = ivf->metric_type; |
386 | | |
387 | | // almost verbatim copy from IndexIVF::search_preassigned |
388 | |
|
389 | 0 | size_t nlistv = 0, ndis = 0, nheap = 0; |
390 | 0 | using HeapForIP = CMin<int32_t, idx_t>; |
391 | 0 | using HeapForL2 = CMax<int32_t, idx_t>; |
392 | |
|
393 | 0 | #pragma omp parallel if (n > 1) reduction(+ : nlistv, ndis, nheap) |
394 | 0 | { |
395 | 0 | std::unique_ptr<BinaryInvertedListScanner> scanner( |
396 | 0 | ivf->get_InvertedListScanner(store_pairs)); |
397 | |
|
398 | 0 | #pragma omp for |
399 | 0 | for (idx_t i = 0; i < n; i++) { |
400 | 0 | const uint8_t* xi = x + i * ivf->code_size; |
401 | 0 | scanner->set_query(xi); |
402 | |
|
403 | 0 | const idx_t* keysi = keys + i * nprobe; |
404 | 0 | int32_t* simi = distances + k * i; |
405 | 0 | idx_t* idxi = labels + k * i; |
406 | |
|
407 | 0 | if (metric_type == METRIC_INNER_PRODUCT) { |
408 | 0 | heap_heapify<HeapForIP>(k, simi, idxi); |
409 | 0 | } else { |
410 | 0 | heap_heapify<HeapForL2>(k, simi, idxi); |
411 | 0 | } |
412 | |
|
413 | 0 | size_t nscan = 0; |
414 | |
|
415 | 0 | for (size_t ik = 0; ik < nprobe; ik++) { |
416 | 0 | idx_t key = keysi[ik]; /* select the list */ |
417 | 0 | if (key < 0) { |
418 | | // not enough centroids for multiprobe |
419 | 0 | continue; |
420 | 0 | } |
421 | 0 | FAISS_THROW_IF_NOT_FMT( |
422 | 0 | key < (idx_t)ivf->nlist, |
423 | 0 | "Invalid key=%" PRId64 " at ik=%zd nlist=%zd\n", |
424 | 0 | key, |
425 | 0 | ik, |
426 | 0 | ivf->nlist); |
427 | |
|
428 | 0 | scanner->set_list(key, coarse_dis[i * nprobe + ik]); |
429 | |
|
430 | 0 | nlistv++; |
431 | |
|
432 | 0 | size_t list_size = ivf->invlists->list_size(key); |
433 | 0 | InvertedLists::ScopedCodes scodes(ivf->invlists, key); |
434 | 0 | std::unique_ptr<InvertedLists::ScopedIds> sids; |
435 | 0 | const idx_t* ids = nullptr; |
436 | |
|
437 | 0 | if (!store_pairs) { |
438 | 0 | sids = std::make_unique<InvertedLists::ScopedIds>( |
439 | 0 | ivf->invlists, key); |
440 | 0 | ids = sids->get(); |
441 | 0 | } |
442 | |
|
443 | 0 | nheap += scanner->scan_codes( |
444 | 0 | list_size, scodes.get(), ids, simi, idxi, k); |
445 | |
|
446 | 0 | nscan += list_size; |
447 | 0 | if (max_codes && nscan >= max_codes) |
448 | 0 | break; |
449 | 0 | } |
450 | |
|
451 | 0 | ndis += nscan; |
452 | 0 | if (metric_type == METRIC_INNER_PRODUCT) { |
453 | 0 | heap_reorder<HeapForIP>(k, simi, idxi); |
454 | 0 | } else { |
455 | 0 | heap_reorder<HeapForL2>(k, simi, idxi); |
456 | 0 | } |
457 | |
|
458 | 0 | } // parallel for |
459 | 0 | } // parallel |
460 | |
|
461 | 0 | indexIVF_stats.nq += n; |
462 | 0 | indexIVF_stats.nlist += nlistv; |
463 | 0 | indexIVF_stats.ndis += ndis; |
464 | 0 | indexIVF_stats.nheap_updates += nheap; |
465 | 0 | } |
466 | | |
467 | | template <class HammingComputer, bool store_pairs> |
468 | | void search_knn_hamming_count( |
469 | | const IndexBinaryIVF* ivf, |
470 | | size_t nx, |
471 | | const uint8_t* __restrict x, |
472 | | const idx_t* __restrict keys, |
473 | | int k, |
474 | | int32_t* __restrict distances, |
475 | | idx_t* __restrict labels, |
476 | 0 | const IVFSearchParameters* params) { |
477 | 0 | const int nBuckets = ivf->d + 1; |
478 | 0 | std::vector<int> all_counters(nx * nBuckets, 0); |
479 | 0 | std::unique_ptr<idx_t[]> all_ids_per_dis(new idx_t[nx * nBuckets * k]); |
480 | |
|
481 | 0 | idx_t nprobe = params ? params->nprobe : ivf->nprobe; |
482 | 0 | nprobe = std::min((idx_t)ivf->nlist, nprobe); |
483 | 0 | idx_t max_codes = params ? params->max_codes : ivf->max_codes; |
484 | |
|
485 | 0 | std::vector<HCounterState<HammingComputer>> cs; |
486 | 0 | for (size_t i = 0; i < nx; ++i) { |
487 | 0 | cs.push_back(HCounterState<HammingComputer>( |
488 | 0 | all_counters.data() + i * nBuckets, |
489 | 0 | all_ids_per_dis.get() + i * nBuckets * k, |
490 | 0 | x + i * ivf->code_size, |
491 | 0 | ivf->d, |
492 | 0 | k)); |
493 | 0 | } |
494 | |
|
495 | 0 | size_t nlistv = 0, ndis = 0; |
496 | |
|
497 | 0 | #pragma omp parallel for reduction(+ : nlistv, ndis) |
498 | 0 | for (int64_t i = 0; i < nx; i++) { |
499 | 0 | const idx_t* keysi = keys + i * nprobe; |
500 | 0 | HCounterState<HammingComputer>& csi = cs[i]; |
501 | |
|
502 | 0 | size_t nscan = 0; |
503 | |
|
504 | 0 | for (size_t ik = 0; ik < nprobe; ik++) { |
505 | 0 | idx_t key = keysi[ik]; /* select the list */ |
506 | 0 | if (key < 0) { |
507 | | // not enough centroids for multiprobe |
508 | 0 | continue; |
509 | 0 | } |
510 | 0 | FAISS_THROW_IF_NOT_FMT( |
511 | 0 | key < (idx_t)ivf->nlist, |
512 | 0 | "Invalid key=%" PRId64 " at ik=%zd nlist=%zd\n", |
513 | 0 | key, |
514 | 0 | ik, |
515 | 0 | ivf->nlist); |
516 | | |
517 | 0 | nlistv++; |
518 | 0 | size_t list_size = ivf->invlists->list_size(key); |
519 | 0 | InvertedLists::ScopedCodes scodes(ivf->invlists, key); |
520 | 0 | const uint8_t* list_vecs = scodes.get(); |
521 | 0 | const idx_t* ids = |
522 | 0 | store_pairs ? nullptr : ivf->invlists->get_ids(key); |
523 | |
|
524 | 0 | for (size_t j = 0; j < list_size; j++) { |
525 | 0 | const uint8_t* yj = list_vecs + ivf->code_size * j; |
526 | |
|
527 | 0 | idx_t id = store_pairs ? (key << 32 | j) : ids[j]; |
528 | 0 | csi.update_counter(yj, id); |
529 | 0 | } |
530 | 0 | if (ids) { |
531 | 0 | ivf->invlists->release_ids(key, ids); |
532 | 0 | } |
533 | |
|
534 | 0 | nscan += list_size; |
535 | 0 | if (max_codes && nscan >= max_codes) |
536 | 0 | break; |
537 | 0 | } |
538 | 0 | ndis += nscan; |
539 | |
|
540 | 0 | int nres = 0; |
541 | 0 | for (int b = 0; b < nBuckets && nres < k; b++) { |
542 | 0 | for (int l = 0; l < csi.counters[b] && nres < k; l++) { |
543 | 0 | labels[i * k + nres] = csi.ids_per_dis[b * k + l]; |
544 | 0 | distances[i * k + nres] = b; |
545 | 0 | nres++; |
546 | 0 | } |
547 | 0 | } |
548 | 0 | while (nres < k) { |
549 | 0 | labels[i * k + nres] = -1; |
550 | 0 | distances[i * k + nres] = std::numeric_limits<int32_t>::max(); |
551 | 0 | ++nres; |
552 | 0 | } |
553 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_16HammingComputer4ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_16HammingComputer8ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer16ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer20ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer32ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer64ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_22HammingComputerDefaultELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_16HammingComputer4ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_16HammingComputer8ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer16ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer20ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer32ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer64ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_22HammingComputerDefaultELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE.omp_outlined_debug__ |
554 | |
|
555 | 0 | indexIVF_stats.nq += nx; |
556 | 0 | indexIVF_stats.nlist += nlistv; |
557 | 0 | indexIVF_stats.ndis += ndis; |
558 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_16HammingComputer4ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_16HammingComputer8ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer16ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer20ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer32ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer64ELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_22HammingComputerDefaultELb1EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_16HammingComputer4ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_16HammingComputer8ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer16ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer20ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer32ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_17HammingComputer64ELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_124search_knn_hamming_countINS_22HammingComputerDefaultELb0EEEvPKNS_14IndexBinaryIVFEmPKhPKliPiPlPKNS_19SearchParametersIVFE |
559 | | |
560 | | /* Manages NQ queries at a time, stores results */ |
561 | | template <class HammingComputer, int NQ, int K> |
562 | | struct BlockSearch { |
563 | | HammingComputer hcs[NQ]; |
564 | | // heaps to update for each query |
565 | | int32_t* distances[NQ]; |
566 | | idx_t* labels[NQ]; |
567 | | // curent top of heap |
568 | | int32_t heap_tops[NQ]; |
569 | | |
570 | | BlockSearch( |
571 | | size_t code_size, |
572 | | const uint8_t* __restrict x, |
573 | | const int32_t* __restrict keys, |
574 | | int32_t* __restrict all_distances, |
575 | 0 | idx_t* __restrict all_labels) { |
576 | 0 | for (idx_t q = 0; q < NQ; q++) { |
577 | 0 | idx_t qno = keys[q]; |
578 | 0 | hcs[q] = HammingComputer(x + qno * code_size, code_size); |
579 | 0 | distances[q] = all_distances + qno * K; |
580 | 0 | labels[q] = all_labels + qno * K; |
581 | 0 | heap_tops[q] = distances[q][0]; |
582 | 0 | } |
583 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer4ELi4ELi1EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer4ELi4ELi2EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer4ELi4ELi4EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer8ELi4ELi1EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer8ELi4ELi2EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer8ELi4ELi4EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer16ELi4ELi1EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer16ELi4ELi2EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer16ELi4ELi4EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer20ELi4ELi1EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer20ELi4ELi2EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer20ELi4ELi4EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer32ELi4ELi1EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer32ELi4ELi2EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer32ELi4ELi4EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer64ELi4ELi1EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer64ELi4ELi2EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer64ELi4ELi4EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_22HammingComputerDefaultELi4ELi1EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_22HammingComputerDefaultELi4ELi2EEC2EmPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_22HammingComputerDefaultELi4ELi4EEC2EmPKhPKiPiPl |
584 | | |
585 | 0 | void add_bcode(const uint8_t* bcode, idx_t id) { |
586 | 0 | using C = CMax<int32_t, idx_t>; |
587 | 0 | for (int q = 0; q < NQ; q++) { |
588 | 0 | int dis = hcs[q].hamming(bcode); |
589 | 0 | if (dis < heap_tops[q]) { |
590 | 0 | heap_replace_top<C>(K, distances[q], labels[q], dis, id); |
591 | 0 | heap_tops[q] = distances[q][0]; |
592 | 0 | } |
593 | 0 | } |
594 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer4ELi4ELi1EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer4ELi4ELi2EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer4ELi4ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer8ELi4ELi1EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer8ELi4ELi2EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_16HammingComputer8ELi4ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer16ELi4ELi1EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer16ELi4ELi2EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer16ELi4ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer20ELi4ELi1EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer20ELi4ELi2EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer20ELi4ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer32ELi4ELi1EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer32ELi4ELi2EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer32ELi4ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer64ELi4ELi1EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer64ELi4ELi2EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_17HammingComputer64ELi4ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_22HammingComputerDefaultELi4ELi1EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_22HammingComputerDefaultELi4ELi2EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_111BlockSearchINS_22HammingComputerDefaultELi4ELi4EE9add_bcodeEPKhl |
595 | | }; |
596 | | |
597 | | template <class HammingComputer, int NQ> |
598 | | struct BlockSearchVariableK { |
599 | | int k; |
600 | | HammingComputer hcs[NQ]; |
601 | | // heaps to update for each query |
602 | | int32_t* distances[NQ]; |
603 | | idx_t* labels[NQ]; |
604 | | // curent top of heap |
605 | | int32_t heap_tops[NQ]; |
606 | | |
607 | | BlockSearchVariableK( |
608 | | size_t code_size, |
609 | | int k, |
610 | | const uint8_t* __restrict x, |
611 | | const int32_t* __restrict keys, |
612 | | int32_t* __restrict all_distances, |
613 | | idx_t* __restrict all_labels) |
614 | 0 | : k(k) { |
615 | 0 | for (idx_t q = 0; q < NQ; q++) { |
616 | 0 | idx_t qno = keys[q]; |
617 | 0 | hcs[q] = HammingComputer(x + qno * code_size, code_size); |
618 | 0 | distances[q] = all_distances + qno * k; |
619 | 0 | labels[q] = all_labels + qno * k; |
620 | 0 | heap_tops[q] = distances[q][0]; |
621 | 0 | } |
622 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_16HammingComputer4ELi4EEC2EmiPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_16HammingComputer8ELi4EEC2EmiPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_17HammingComputer16ELi4EEC2EmiPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_17HammingComputer20ELi4EEC2EmiPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_17HammingComputer32ELi4EEC2EmiPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_17HammingComputer64ELi4EEC2EmiPKhPKiPiPl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_22HammingComputerDefaultELi4EEC2EmiPKhPKiPiPl |
623 | | |
624 | 0 | void add_bcode(const uint8_t* bcode, idx_t id) { |
625 | 0 | using C = CMax<int32_t, idx_t>; |
626 | 0 | for (int q = 0; q < NQ; q++) { |
627 | 0 | int dis = hcs[q].hamming(bcode); |
628 | 0 | if (dis < heap_tops[q]) { |
629 | 0 | heap_replace_top<C>(k, distances[q], labels[q], dis, id); |
630 | 0 | heap_tops[q] = distances[q][0]; |
631 | 0 | } |
632 | 0 | } |
633 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_16HammingComputer4ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_16HammingComputer8ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_17HammingComputer16ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_17HammingComputer20ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_17HammingComputer32ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_17HammingComputer64ELi4EE9add_bcodeEPKhl Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_120BlockSearchVariableKINS_22HammingComputerDefaultELi4EE9add_bcodeEPKhl |
634 | | }; |
635 | | |
636 | | template <class HammingComputer> |
637 | | void search_knn_hamming_per_invlist( |
638 | | const IndexBinaryIVF* ivf, |
639 | | size_t n, |
640 | | const uint8_t* __restrict x, |
641 | | idx_t k, |
642 | | const idx_t* __restrict keys_in, |
643 | | const int32_t* __restrict coarse_dis, |
644 | | int32_t* __restrict distances, |
645 | | idx_t* __restrict labels, |
646 | | bool store_pairs, |
647 | 0 | const IVFSearchParameters* params) { |
648 | 0 | idx_t nprobe = params ? params->nprobe : ivf->nprobe; |
649 | 0 | nprobe = std::min((idx_t)ivf->nlist, nprobe); |
650 | 0 | idx_t max_codes = params ? params->max_codes : ivf->max_codes; |
651 | 0 | FAISS_THROW_IF_NOT(max_codes == 0); |
652 | 0 | FAISS_THROW_IF_NOT(!store_pairs); |
653 | | |
654 | | // reorder buckets |
655 | 0 | std::vector<int64_t> lims(n + 1); |
656 | 0 | int32_t* keys = new int32_t[n * nprobe]; |
657 | 0 | std::unique_ptr<int32_t[]> delete_keys(keys); |
658 | 0 | for (idx_t i = 0; i < n * nprobe; i++) { |
659 | 0 | keys[i] = keys_in[i]; |
660 | 0 | } |
661 | 0 | matrix_bucket_sort_inplace(n, nprobe, keys, ivf->nlist, lims.data(), 0); |
662 | |
|
663 | 0 | using C = CMax<int32_t, idx_t>; |
664 | 0 | heap_heapify<C>(n * k, distances, labels); |
665 | 0 | const size_t code_size = ivf->code_size; |
666 | |
|
667 | 0 | for (idx_t l = 0; l < ivf->nlist; l++) { |
668 | 0 | idx_t l0 = lims[l], nq = lims[l + 1] - l0; |
669 | |
|
670 | 0 | InvertedLists::ScopedCodes scodes(ivf->invlists, l); |
671 | 0 | InvertedLists::ScopedIds sidx(ivf->invlists, l); |
672 | 0 | idx_t nb = ivf->invlists->list_size(l); |
673 | 0 | const uint8_t* bcodes = scodes.get(); |
674 | 0 | const idx_t* ids = sidx.get(); |
675 | |
|
676 | 0 | idx_t i = 0; |
677 | | |
678 | | // process as much as possible by blocks |
679 | 0 | constexpr int BS = 4; |
680 | |
|
681 | 0 | if (k == 1) { |
682 | 0 | for (; i + BS <= nq; i += BS) { |
683 | 0 | BlockSearch<HammingComputer, BS, 1> bc( |
684 | 0 | code_size, x, keys + l0 + i, distances, labels); |
685 | 0 | for (idx_t j = 0; j < nb; j++) { |
686 | 0 | bc.add_bcode(bcodes + j * code_size, ids[j]); |
687 | 0 | } |
688 | 0 | } |
689 | 0 | } else if (k == 2) { |
690 | 0 | for (; i + BS <= nq; i += BS) { |
691 | 0 | BlockSearch<HammingComputer, BS, 2> bc( |
692 | 0 | code_size, x, keys + l0 + i, distances, labels); |
693 | 0 | for (idx_t j = 0; j < nb; j++) { |
694 | 0 | bc.add_bcode(bcodes + j * code_size, ids[j]); |
695 | 0 | } |
696 | 0 | } |
697 | 0 | } else if (k == 4) { |
698 | 0 | for (; i + BS <= nq; i += BS) { |
699 | 0 | BlockSearch<HammingComputer, BS, 4> bc( |
700 | 0 | code_size, x, keys + l0 + i, distances, labels); |
701 | 0 | for (idx_t j = 0; j < nb; j++) { |
702 | 0 | bc.add_bcode(bcodes + j * code_size, ids[j]); |
703 | 0 | } |
704 | 0 | } |
705 | 0 | } else { |
706 | 0 | for (; i + BS <= nq; i += BS) { |
707 | 0 | BlockSearchVariableK<HammingComputer, BS> bc( |
708 | 0 | code_size, k, x, keys + l0 + i, distances, labels); |
709 | 0 | for (idx_t j = 0; j < nb; j++) { |
710 | 0 | bc.add_bcode(bcodes + j * code_size, ids[j]); |
711 | 0 | } |
712 | 0 | } |
713 | 0 | } |
714 | | |
715 | | // leftovers |
716 | 0 | for (; i < nq; i++) { |
717 | 0 | idx_t qno = keys[l0 + i]; |
718 | 0 | HammingComputer hc(x + qno * code_size, code_size); |
719 | 0 | idx_t* __restrict idxi = labels + qno * k; |
720 | 0 | int32_t* __restrict simi = distances + qno * k; |
721 | 0 | int32_t simi0 = simi[0]; |
722 | 0 | for (idx_t j = 0; j < nb; j++) { |
723 | 0 | int dis = hc.hamming(bcodes + j * code_size); |
724 | |
|
725 | 0 | if (dis < simi0) { |
726 | 0 | idx_t id = store_pairs ? lo_build(l, j) : ids[j]; |
727 | 0 | heap_replace_top<C>(k, simi, idxi, dis, id); |
728 | 0 | simi0 = simi[0]; |
729 | 0 | } |
730 | 0 | } |
731 | 0 | } |
732 | 0 | } |
733 | 0 | for (idx_t i = 0; i < n; i++) { |
734 | 0 | heap_reorder<C>(k, distances + i * k, labels + i * k); |
735 | 0 | } |
736 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_130search_knn_hamming_per_invlistINS_16HammingComputer4EEEvPKNS_14IndexBinaryIVFEmPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_130search_knn_hamming_per_invlistINS_16HammingComputer8EEEvPKNS_14IndexBinaryIVFEmPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_130search_knn_hamming_per_invlistINS_17HammingComputer16EEEvPKNS_14IndexBinaryIVFEmPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_130search_knn_hamming_per_invlistINS_17HammingComputer20EEEvPKNS_14IndexBinaryIVFEmPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_130search_knn_hamming_per_invlistINS_17HammingComputer32EEEvPKNS_14IndexBinaryIVFEmPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_130search_knn_hamming_per_invlistINS_17HammingComputer64EEEvPKNS_14IndexBinaryIVFEmPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFE Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_130search_knn_hamming_per_invlistINS_22HammingComputerDefaultEEEvPKNS_14IndexBinaryIVFEmPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFE |
737 | | |
738 | | struct Run_search_knn_hamming_per_invlist { |
739 | | using T = void; |
740 | | |
741 | | template <class HammingComputer, class... Types> |
742 | 0 | void f(Types... args) { |
743 | 0 | search_knn_hamming_per_invlist<HammingComputer>(args...); |
744 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_134Run_search_knn_hamming_per_invlist1fINS_16HammingComputer4EJPKNS_14IndexBinaryIVFElPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_134Run_search_knn_hamming_per_invlist1fINS_16HammingComputer8EJPKNS_14IndexBinaryIVFElPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_134Run_search_knn_hamming_per_invlist1fINS_17HammingComputer16EJPKNS_14IndexBinaryIVFElPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_134Run_search_knn_hamming_per_invlist1fINS_17HammingComputer20EJPKNS_14IndexBinaryIVFElPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_134Run_search_knn_hamming_per_invlist1fINS_17HammingComputer32EJPKNS_14IndexBinaryIVFElPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_134Run_search_knn_hamming_per_invlist1fINS_17HammingComputer64EJPKNS_14IndexBinaryIVFElPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_134Run_search_knn_hamming_per_invlist1fINS_22HammingComputerDefaultEJPKNS_14IndexBinaryIVFElPKhlPKlPKiPiPlbPKNS_19SearchParametersIVFEEEEvDpT0_ |
745 | | }; |
746 | | |
747 | | template <bool store_pairs> |
748 | | struct Run_search_knn_hamming_count { |
749 | | using T = void; |
750 | | |
751 | | template <class HammingComputer, class... Types> |
752 | 0 | void f(Types... args) { |
753 | 0 | search_knn_hamming_count<HammingComputer, store_pairs>(args...); |
754 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb1EE1fINS_16HammingComputer4EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb1EE1fINS_16HammingComputer8EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb1EE1fINS_17HammingComputer16EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb1EE1fINS_17HammingComputer20EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb1EE1fINS_17HammingComputer32EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb1EE1fINS_17HammingComputer64EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb1EE1fINS_22HammingComputerDefaultEJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb0EE1fINS_16HammingComputer4EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb0EE1fINS_16HammingComputer8EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb0EE1fINS_17HammingComputer16EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb0EE1fINS_17HammingComputer20EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb0EE1fINS_17HammingComputer32EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb0EE1fINS_17HammingComputer64EJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_128Run_search_knn_hamming_countILb0EE1fINS_22HammingComputerDefaultEJPKNS_14IndexBinaryIVFElPKhPKllPiPlPKNS_19SearchParametersIVFEEEEvDpT0_ |
755 | | }; |
756 | | |
757 | | struct BuildScanner { |
758 | | using T = BinaryInvertedListScanner*; |
759 | | |
760 | | template <class HammingComputer> |
761 | 0 | T f(size_t code_size, bool store_pairs) { |
762 | 0 | return new IVFBinaryScannerL2<HammingComputer>(code_size, store_pairs); |
763 | 0 | } Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_112BuildScanner1fINS_16HammingComputer4EEEPNS_25BinaryInvertedListScannerEmb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_112BuildScanner1fINS_16HammingComputer8EEEPNS_25BinaryInvertedListScannerEmb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_112BuildScanner1fINS_17HammingComputer16EEEPNS_25BinaryInvertedListScannerEmb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_112BuildScanner1fINS_17HammingComputer20EEEPNS_25BinaryInvertedListScannerEmb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_112BuildScanner1fINS_17HammingComputer32EEEPNS_25BinaryInvertedListScannerEmb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_112BuildScanner1fINS_17HammingComputer64EEEPNS_25BinaryInvertedListScannerEmb Unexecuted instantiation: IndexBinaryIVF.cpp:_ZN5faiss12_GLOBAL__N_112BuildScanner1fINS_22HammingComputerDefaultEEEPNS_25BinaryInvertedListScannerEmb |
764 | | }; |
765 | | |
766 | | } // anonymous namespace |
767 | | |
768 | | BinaryInvertedListScanner* IndexBinaryIVF::get_InvertedListScanner( |
769 | 0 | bool store_pairs) const { |
770 | 0 | BuildScanner bs; |
771 | 0 | return dispatch_HammingComputer(code_size, bs, code_size, store_pairs); |
772 | 0 | } |
773 | | |
774 | | void IndexBinaryIVF::search_preassigned( |
775 | | idx_t n, |
776 | | const uint8_t* x, |
777 | | idx_t k, |
778 | | const idx_t* cidx, |
779 | | const int32_t* cdis, |
780 | | int32_t* dis, |
781 | | idx_t* idx, |
782 | | bool store_pairs, |
783 | 0 | const IVFSearchParameters* params) const { |
784 | 0 | if (per_invlist_search) { |
785 | 0 | Run_search_knn_hamming_per_invlist r; |
786 | | // clang-format off |
787 | 0 | dispatch_HammingComputer( |
788 | 0 | code_size, r, this, n, x, k, |
789 | 0 | cidx, cdis, dis, idx, store_pairs, params); |
790 | | // clang-format on |
791 | 0 | } else if (use_heap) { |
792 | 0 | search_knn_hamming_heap( |
793 | 0 | this, n, x, k, cidx, cdis, dis, idx, store_pairs, params); |
794 | 0 | } else if (store_pairs) { // !use_heap && store_pairs |
795 | 0 | Run_search_knn_hamming_count<true> r; |
796 | 0 | dispatch_HammingComputer( |
797 | 0 | code_size, r, this, n, x, cidx, k, dis, idx, params); |
798 | 0 | } else { // !use_heap && !store_pairs |
799 | 0 | Run_search_knn_hamming_count<false> r; |
800 | 0 | dispatch_HammingComputer( |
801 | 0 | code_size, r, this, n, x, cidx, k, dis, idx, params); |
802 | 0 | } |
803 | 0 | } |
804 | | |
805 | | void IndexBinaryIVF::range_search( |
806 | | idx_t n, |
807 | | const uint8_t* __restrict x, |
808 | | int radius, |
809 | | RangeSearchResult* __restrict res, |
810 | 0 | const SearchParameters* params) const { |
811 | 0 | FAISS_THROW_IF_NOT_MSG( |
812 | 0 | !params, "search params not supported for this index"); |
813 | 0 | const size_t nprobe_2 = std::min(nlist, this->nprobe); |
814 | 0 | std::unique_ptr<idx_t[]> idx(new idx_t[n * nprobe_2]); |
815 | 0 | std::unique_ptr<int32_t[]> coarse_dis(new int32_t[n * nprobe_2]); |
816 | |
|
817 | 0 | double t0 = getmillisecs(); |
818 | 0 | quantizer->search(n, x, nprobe_2, coarse_dis.get(), idx.get()); |
819 | 0 | indexIVF_stats.quantization_time += getmillisecs() - t0; |
820 | |
|
821 | 0 | t0 = getmillisecs(); |
822 | 0 | invlists->prefetch_lists(idx.get(), n * nprobe_2); |
823 | |
|
824 | 0 | range_search_preassigned(n, x, radius, idx.get(), coarse_dis.get(), res); |
825 | |
|
826 | 0 | indexIVF_stats.search_time += getmillisecs() - t0; |
827 | 0 | } |
828 | | |
829 | | void IndexBinaryIVF::range_search_preassigned( |
830 | | idx_t n, |
831 | | const uint8_t* __restrict x, |
832 | | int radius, |
833 | | const idx_t* __restrict assign, |
834 | | const int32_t* __restrict centroid_dis, |
835 | 0 | RangeSearchResult* __restrict res) const { |
836 | 0 | const size_t nprobe_2 = std::min(nlist, this->nprobe); |
837 | 0 | bool store_pairs = false; |
838 | 0 | size_t nlistv = 0, ndis = 0; |
839 | |
|
840 | 0 | std::vector<RangeSearchPartialResult*> all_pres(omp_get_max_threads()); |
841 | |
|
842 | 0 | #pragma omp parallel reduction(+ : nlistv, ndis) |
843 | 0 | { |
844 | 0 | RangeSearchPartialResult pres(res); |
845 | 0 | std::unique_ptr<BinaryInvertedListScanner> scanner( |
846 | 0 | get_InvertedListScanner(store_pairs)); |
847 | 0 | FAISS_THROW_IF_NOT(scanner.get()); |
848 | | |
849 | 0 | all_pres[omp_get_thread_num()] = &pres; |
850 | |
|
851 | 0 | auto scan_list_func = [&](size_t i, size_t ik, RangeQueryResult& qres) { |
852 | 0 | idx_t key = assign[i * nprobe_2 + ik]; /* select the list */ |
853 | 0 | if (key < 0) |
854 | 0 | return; |
855 | 0 | FAISS_THROW_IF_NOT_FMT( |
856 | 0 | key < (idx_t)nlist, |
857 | 0 | "Invalid key=%" PRId64 " at ik=%zd nlist=%zd\n", |
858 | 0 | key, |
859 | 0 | ik, |
860 | 0 | nlist); |
861 | 0 | const size_t list_size = invlists->list_size(key); |
862 | |
|
863 | 0 | if (list_size == 0) |
864 | 0 | return; |
865 | | |
866 | 0 | InvertedLists::ScopedCodes scodes(invlists, key); |
867 | 0 | InvertedLists::ScopedIds ids(invlists, key); |
868 | |
|
869 | 0 | scanner->set_list(key, assign[i * nprobe_2 + ik]); |
870 | 0 | nlistv++; |
871 | 0 | ndis += list_size; |
872 | 0 | scanner->scan_codes_range( |
873 | 0 | list_size, scodes.get(), ids.get(), radius, qres); |
874 | 0 | }; |
875 | |
|
876 | 0 | #pragma omp for |
877 | 0 | for (idx_t i = 0; i < n; i++) { |
878 | 0 | scanner->set_query(x + i * code_size); |
879 | |
|
880 | 0 | RangeQueryResult& qres = pres.new_result(i); |
881 | |
|
882 | 0 | for (size_t ik = 0; ik < nprobe_2; ik++) { |
883 | 0 | scan_list_func(i, ik, qres); |
884 | 0 | } |
885 | 0 | } |
886 | |
|
887 | 0 | pres.finalize(); |
888 | 0 | } |
889 | 0 | indexIVF_stats.nq += n; |
890 | 0 | indexIVF_stats.nlist += nlistv; |
891 | 0 | indexIVF_stats.ndis += ndis; |
892 | 0 | } |
893 | | |
894 | 0 | IndexBinaryIVF::~IndexBinaryIVF() { |
895 | 0 | if (own_invlists) { |
896 | 0 | delete invlists; |
897 | 0 | } |
898 | |
|
899 | 0 | if (own_fields) { |
900 | 0 | delete quantizer; |
901 | 0 | } |
902 | 0 | } |
903 | | |
904 | | } // namespace faiss |