/root/doris/contrib/faiss/faiss/impl/ResultHandler.h
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 | | /* |
9 | | * Structures that collect search results from distance computations |
10 | | */ |
11 | | |
12 | | #pragma once |
13 | | |
14 | | #include <faiss/impl/AuxIndexStructures.h> |
15 | | #include <faiss/impl/FaissException.h> |
16 | | #include <faiss/impl/IDSelector.h> |
17 | | #include <faiss/utils/Heap.h> |
18 | | #include <faiss/utils/partitioning.h> |
19 | | |
20 | | #include <algorithm> |
21 | | #include <iostream> |
22 | | |
23 | | namespace faiss { |
24 | | |
25 | | /***************************************************************** |
26 | | * The classes below are intended to be used as template arguments |
27 | | * they handle results for batches of queries (size nq). |
28 | | * They can be called in two ways: |
29 | | * - by instanciating a SingleResultHandler that tracks results for a single |
30 | | * query |
31 | | * - with begin_multiple/add_results/end_multiple calls where a whole block of |
32 | | * results is submitted |
33 | | * All classes are templated on C which to define wheter the min or the max of |
34 | | * results is to be kept, and on sel, so that the codepaths for with / without |
35 | | * selector can be separated at compile time. |
36 | | *****************************************************************/ |
37 | | |
38 | | template <class C, bool use_sel = false> |
39 | | struct BlockResultHandler { |
40 | | size_t nq; // number of queries for which we search |
41 | | const IDSelector* sel; |
42 | | |
43 | | explicit BlockResultHandler(size_t nq, const IDSelector* sel = nullptr) |
44 | 113 | : nq(nq), sel(sel) { |
45 | 113 | assert(!use_sel || sel); |
46 | 113 | } Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMinIflEELb1EEC2EmPKNS_10IDSelectorE _ZN5faiss18BlockResultHandlerINS_4CMinIflEELb0EEC2EmPKNS_10IDSelectorE Line | Count | Source | 44 | 3 | : nq(nq), sel(sel) { | 45 | | assert(!use_sel || sel); | 46 | 3 | } |
Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMaxIflEELb1EEC2EmPKNS_10IDSelectorE _ZN5faiss18BlockResultHandlerINS_4CMaxIflEELb0EEC2EmPKNS_10IDSelectorE Line | Count | Source | 44 | 110 | : nq(nq), sel(sel) { | 45 | | assert(!use_sel || sel); | 46 | 110 | } |
|
47 | | |
48 | | // currently handled query range |
49 | | size_t i0 = 0, i1 = 0; |
50 | | |
51 | | // start collecting results for queries [i0, i1) |
52 | 0 | virtual void begin_multiple(size_t i0_2, size_t i1_2) { |
53 | 0 | this->i0 = i0_2; |
54 | 0 | this->i1 = i1_2; |
55 | 0 | } Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMinIflEELb1EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMinIflEELb0EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMaxIflEELb1EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMaxIflEELb0EE14begin_multipleEmm |
56 | | |
57 | | // add results for queries [i0, i1) and database [j0, j1) |
58 | 0 | virtual void add_results(size_t, size_t, const typename C::T*) {} Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMinIflEELb1EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMaxIflEELb1EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf |
59 | | |
60 | | // series of results for queries i0..i1 is done |
61 | 0 | virtual void end_multiple() {} Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMinIflEELb1EE12end_multipleEv Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMinIflEELb0EE12end_multipleEv Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMaxIflEELb1EE12end_multipleEv Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMaxIflEELb0EE12end_multipleEv |
62 | | |
63 | 113 | virtual ~BlockResultHandler() {} Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMinIflEELb1EED2Ev _ZN5faiss18BlockResultHandlerINS_4CMinIflEELb0EED2Ev Line | Count | Source | 63 | 3 | virtual ~BlockResultHandler() {} |
Unexecuted instantiation: _ZN5faiss18BlockResultHandlerINS_4CMaxIflEELb1EED2Ev _ZN5faiss18BlockResultHandlerINS_4CMaxIflEELb0EED2Ev Line | Count | Source | 63 | 110 | virtual ~BlockResultHandler() {} |
|
64 | | |
65 | 1.50k | bool is_in_selection(idx_t i) const { |
66 | 1.50k | return !use_sel || sel->is_member(i); |
67 | 1.50k | } Unexecuted instantiation: _ZNK5faiss18BlockResultHandlerINS_4CMinIflEELb1EE15is_in_selectionEl _ZNK5faiss18BlockResultHandlerINS_4CMinIflEELb0EE15is_in_selectionEl Line | Count | Source | 65 | 1.50k | bool is_in_selection(idx_t i) const { | 66 | 1.50k | return !use_sel || sel->is_member(i); | 67 | 1.50k | } |
Unexecuted instantiation: _ZNK5faiss18BlockResultHandlerINS_4CMaxIflEELb1EE15is_in_selectionEl Unexecuted instantiation: _ZNK5faiss18BlockResultHandlerINS_4CMaxIflEELb0EE15is_in_selectionEl |
68 | | }; |
69 | | |
70 | | // handler for a single query |
71 | | template <class C> |
72 | | struct ResultHandler { |
73 | | // if not better than threshold, then not necessary to call add_result |
74 | | typename C::T threshold = C::neutral(); |
75 | | |
76 | | // return whether threshold was updated |
77 | | virtual bool add_result(typename C::T dis, typename C::TI idx) = 0; |
78 | | |
79 | 113 | virtual ~ResultHandler() {} _ZN5faiss13ResultHandlerINS_4CMinIflEEED2Ev Line | Count | Source | 79 | 3 | virtual ~ResultHandler() {} |
_ZN5faiss13ResultHandlerINS_4CMaxIflEEED2Ev Line | Count | Source | 79 | 110 | virtual ~ResultHandler() {} |
Unexecuted instantiation: _ZN5faiss13ResultHandlerINS_4CMaxItiEEED2Ev Unexecuted instantiation: _ZN5faiss13ResultHandlerINS_4CMinItiEEED2Ev Unexecuted instantiation: _ZN5faiss13ResultHandlerINS_4CMaxItlEEED2Ev Unexecuted instantiation: _ZN5faiss13ResultHandlerINS_4CMinItlEEED2Ev |
80 | | }; |
81 | | |
82 | | /***************************************************************** |
83 | | * Single best result handler. |
84 | | * Tracks the only best result, thus avoiding storing |
85 | | * some temporary data in memory. |
86 | | *****************************************************************/ |
87 | | |
88 | | template <class C, bool use_sel = false> |
89 | | struct Top1BlockResultHandler : BlockResultHandler<C, use_sel> { |
90 | | using T = typename C::T; |
91 | | using TI = typename C::TI; |
92 | | using BlockResultHandler<C, use_sel>::i0; |
93 | | using BlockResultHandler<C, use_sel>::i1; |
94 | | |
95 | | // contains exactly nq elements |
96 | | T* dis_tab; |
97 | | // contains exactly nq elements |
98 | | TI* ids_tab; |
99 | | |
100 | | Top1BlockResultHandler( |
101 | | size_t nq, |
102 | | T* dis_tab, |
103 | | TI* ids_tab, |
104 | | const IDSelector* sel = nullptr) |
105 | 0 | : BlockResultHandler<C, use_sel>(nq, sel), |
106 | 0 | dis_tab(dis_tab), |
107 | 0 | ids_tab(ids_tab) {} Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb1EEC2EmPfPlPKNS_10IDSelectorE Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb0EEC2EmPfPlPKNS_10IDSelectorE Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb1EEC2EmPfPlPKNS_10IDSelectorE Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb0EEC2EmPfPlPKNS_10IDSelectorE |
108 | | |
109 | | struct SingleResultHandler : ResultHandler<C> { |
110 | | Top1BlockResultHandler& hr; |
111 | | using ResultHandler<C>::threshold; |
112 | | |
113 | | TI min_idx; |
114 | | size_t current_idx = 0; |
115 | | |
116 | 0 | explicit SingleResultHandler(Top1BlockResultHandler& hr) : hr(hr) {} Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandlerC2ERS3_ Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandlerC2ERS3_ Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandlerC2ERS3_ Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandlerC2ERS3_ |
117 | | |
118 | | /// begin results for query # i |
119 | 0 | void begin(const size_t current_idx_2) { |
120 | 0 | this->current_idx = current_idx_2; |
121 | 0 | threshold = C::neutral(); |
122 | 0 | min_idx = -1; |
123 | 0 | } Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandler5beginEm Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandler5beginEm Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandler5beginEm Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandler5beginEm |
124 | | |
125 | | /// add one result for query i |
126 | 0 | bool add_result(T dis, TI idx) final { |
127 | 0 | if (C::cmp(this->threshold, dis)) { |
128 | 0 | threshold = dis; |
129 | 0 | min_idx = idx; |
130 | 0 | return true; |
131 | 0 | } |
132 | 0 | return false; |
133 | 0 | } Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandler10add_resultEfl Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandler10add_resultEfl Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandler10add_resultEfl Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandler10add_resultEfl |
134 | | |
135 | | /// series of results for query i is done |
136 | 0 | void end() { |
137 | 0 | hr.dis_tab[current_idx] = threshold; |
138 | 0 | hr.ids_tab[current_idx] = min_idx; |
139 | 0 | } Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandler3endEv Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandler3endEv Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandler3endEv Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandler3endEv |
140 | | }; |
141 | | |
142 | | /// begin |
143 | 0 | void begin_multiple(size_t i0, size_t i1) final { |
144 | 0 | this->i0 = i0; |
145 | 0 | this->i1 = i1; |
146 | |
|
147 | 0 | for (size_t i = i0; i < i1; i++) { |
148 | 0 | this->dis_tab[i] = C::neutral(); |
149 | 0 | } |
150 | 0 | } Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb1EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb0EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb1EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb0EE14begin_multipleEmm |
151 | | |
152 | | /// add results for query i0..i1 and j0..j1 |
153 | 0 | void add_results(size_t j0, size_t j1, const T* dis_tab_2) final { |
154 | 0 | for (int64_t i = i0; i < i1; i++) { |
155 | 0 | const T* dis_tab_i = dis_tab_2 + (j1 - j0) * (i - i0) - j0; |
156 | |
|
157 | 0 | auto& min_distance = this->dis_tab[i]; |
158 | 0 | auto& min_index = this->ids_tab[i]; |
159 | |
|
160 | 0 | for (size_t j = j0; j < j1; j++) { |
161 | 0 | const T distance = dis_tab_i[j]; |
162 | |
|
163 | 0 | if (C::cmp(min_distance, distance)) { |
164 | 0 | min_distance = distance; |
165 | 0 | min_index = j; |
166 | 0 | } |
167 | 0 | } |
168 | 0 | } |
169 | 0 | } Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb1EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb1EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss22Top1BlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf |
170 | | |
171 | 0 | void add_result(const size_t i, const T dis, const TI idx) { |
172 | 0 | auto& min_distance = this->dis_tab[i]; |
173 | 0 | auto& min_index = this->ids_tab[i]; |
174 | |
|
175 | 0 | if (C::cmp(min_distance, dis)) { |
176 | 0 | min_distance = dis; |
177 | 0 | min_index = idx; |
178 | 0 | } |
179 | 0 | } |
180 | | }; |
181 | | |
182 | | /***************************************************************** |
183 | | * Heap based result handler |
184 | | *****************************************************************/ |
185 | | |
186 | | template <class C, bool use_sel = false> |
187 | | struct HeapBlockResultHandler : BlockResultHandler<C, use_sel> { |
188 | | using T = typename C::T; |
189 | | using TI = typename C::TI; |
190 | | using BlockResultHandler<C, use_sel>::i0; |
191 | | using BlockResultHandler<C, use_sel>::i1; |
192 | | |
193 | | T* heap_dis_tab; |
194 | | TI* heap_ids_tab; |
195 | | |
196 | | int64_t k; // number of results to keep |
197 | | |
198 | | HeapBlockResultHandler( |
199 | | size_t nq, |
200 | | T* heap_dis_tab, |
201 | | TI* heap_ids_tab, |
202 | | size_t k, |
203 | | const IDSelector* sel = nullptr) |
204 | 37 | : BlockResultHandler<C, use_sel>(nq, sel), |
205 | 37 | heap_dis_tab(heap_dis_tab), |
206 | 37 | heap_ids_tab(heap_ids_tab), |
207 | 37 | k(k) {} Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb1EEC2EmPfPlmPKNS_10IDSelectorE Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EEC2EmPfPlmPKNS_10IDSelectorE Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb1EEC2EmPfPlmPKNS_10IDSelectorE _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EEC2EmPfPlmPKNS_10IDSelectorE Line | Count | Source | 204 | 37 | : BlockResultHandler<C, use_sel>(nq, sel), | 205 | 37 | heap_dis_tab(heap_dis_tab), | 206 | 37 | heap_ids_tab(heap_ids_tab), | 207 | 37 | k(k) {} |
|
208 | | |
209 | | /****************************************************** |
210 | | * API for 1 result at a time (each SingleResultHandler is |
211 | | * called from 1 thread) |
212 | | */ |
213 | | |
214 | | struct SingleResultHandler : ResultHandler<C> { |
215 | | HeapBlockResultHandler& hr; |
216 | | using ResultHandler<C>::threshold; |
217 | | size_t k; |
218 | | |
219 | | T* heap_dis; |
220 | | TI* heap_ids; |
221 | | |
222 | | explicit SingleResultHandler(HeapBlockResultHandler& hr) |
223 | 37 | : hr(hr), k(hr.k) {} Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandlerC2ERS3_ Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandlerC2ERS3_ Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandlerC2ERS3_ _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandlerC2ERS3_ Line | Count | Source | 223 | 37 | : hr(hr), k(hr.k) {} |
|
224 | | |
225 | | /// begin results for query # i |
226 | 37 | void begin(size_t i) { |
227 | 37 | heap_dis = hr.heap_dis_tab + i * k; |
228 | 37 | heap_ids = hr.heap_ids_tab + i * k; |
229 | 37 | heap_heapify<C>(k, heap_dis, heap_ids); |
230 | 37 | threshold = heap_dis[0]; |
231 | 37 | } Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandler5beginEm Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandler5beginEm Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandler5beginEm _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandler5beginEm Line | Count | Source | 226 | 37 | void begin(size_t i) { | 227 | 37 | heap_dis = hr.heap_dis_tab + i * k; | 228 | 37 | heap_ids = hr.heap_ids_tab + i * k; | 229 | 37 | heap_heapify<C>(k, heap_dis, heap_ids); | 230 | 37 | threshold = heap_dis[0]; | 231 | 37 | } |
|
232 | | |
233 | | /// add one result for query i |
234 | 3.71k | bool add_result(T dis, TI idx) final { |
235 | 3.71k | if (C::cmp(threshold, dis)) { |
236 | 3.71k | heap_replace_top<C>(k, heap_dis, heap_ids, dis, idx); |
237 | 3.71k | threshold = heap_dis[0]; |
238 | 3.71k | return true; |
239 | 3.71k | } |
240 | 0 | return false; |
241 | 3.71k | } Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandler10add_resultEfl Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandler10add_resultEfl Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandler10add_resultEfl _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandler10add_resultEfl Line | Count | Source | 234 | 3.71k | bool add_result(T dis, TI idx) final { | 235 | 3.71k | if (C::cmp(threshold, dis)) { | 236 | 3.71k | heap_replace_top<C>(k, heap_dis, heap_ids, dis, idx); | 237 | 3.71k | threshold = heap_dis[0]; | 238 | 3.71k | return true; | 239 | 3.71k | } | 240 | 0 | return false; | 241 | 3.71k | } |
|
242 | | |
243 | | /// series of results for query i is done |
244 | 37 | void end() { |
245 | 37 | heap_reorder<C>(k, heap_dis, heap_ids); |
246 | 37 | } Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandler3endEv Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandler3endEv Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandler3endEv _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandler3endEv Line | Count | Source | 244 | 37 | void end() { | 245 | 37 | heap_reorder<C>(k, heap_dis, heap_ids); | 246 | 37 | } |
|
247 | | }; |
248 | | |
249 | | /****************************************************** |
250 | | * API for multiple results (called from 1 thread) |
251 | | */ |
252 | | |
253 | | /// begin |
254 | 0 | void begin_multiple(size_t i0_2, size_t i1_2) final { |
255 | 0 | this->i0 = i0_2; |
256 | 0 | this->i1 = i1_2; |
257 | 0 | for (size_t i = i0; i < i1; i++) { |
258 | 0 | heap_heapify<C>(k, heap_dis_tab + i * k, heap_ids_tab + i * k); |
259 | 0 | } |
260 | 0 | } Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb1EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb1EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE14begin_multipleEmm |
261 | | |
262 | | /// add results for query i0..i1 and j0..j1 |
263 | 0 | void add_results(size_t j0, size_t j1, const T* dis_tab) final { |
264 | 0 | #pragma omp parallel for |
265 | 0 | for (int64_t i = i0; i < i1; i++) { |
266 | 0 | T* heap_dis = heap_dis_tab + i * k; |
267 | 0 | TI* heap_ids = heap_ids_tab + i * k; |
268 | 0 | const T* dis_tab_i = dis_tab + (j1 - j0) * (i - i0) - j0; |
269 | 0 | T thresh = heap_dis[0]; |
270 | 0 | for (size_t j = j0; j < j1; j++) { |
271 | 0 | T dis = dis_tab_i[j]; |
272 | 0 | if (C::cmp(thresh, dis)) { |
273 | 0 | heap_replace_top<C>(k, heap_dis, heap_ids, dis, j); |
274 | 0 | thresh = heap_dis[0]; |
275 | 0 | } |
276 | 0 | } |
277 | 0 | } Unexecuted instantiation: IndexFlatCodes.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexFlatCodes.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexFlatCodes.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexFlatCodes.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexHNSW.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexAdditiveQuantizer.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexAdditiveQuantizer.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexBinaryHNSW.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexRaBitQ.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexRaBitQ.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexRaBitQ.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexRaBitQ.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: distances.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: distances.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: distances.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: distances.cpp:_ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ |
278 | 0 | } Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb1EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb1EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf |
279 | | |
280 | | /// series of results for queries i0..i1 is done |
281 | 0 | void end_multiple() final { |
282 | | // maybe parallel for |
283 | 0 | for (size_t i = i0; i < i1; i++) { |
284 | 0 | heap_reorder<C>(k, heap_dis_tab + i * k, heap_ids_tab + i * k); |
285 | 0 | } |
286 | 0 | } Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb1EE12end_multipleEv Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMinIflEELb0EE12end_multipleEv Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb1EE12end_multipleEv Unexecuted instantiation: _ZN5faiss22HeapBlockResultHandlerINS_4CMaxIflEELb0EE12end_multipleEv |
287 | | }; |
288 | | |
289 | | /***************************************************************** |
290 | | * Reservoir result handler |
291 | | * |
292 | | * A reservoir is a result array of size capacity > n (number of requested |
293 | | * results) all results below a threshold are stored in an arbitrary order. When |
294 | | * the capacity is reached, a new threshold is chosen by partitionning the |
295 | | * distance array. |
296 | | *****************************************************************/ |
297 | | |
298 | | /// Reservoir for a single query |
299 | | template <class C> |
300 | | struct ReservoirTopN : ResultHandler<C> { |
301 | | using T = typename C::T; |
302 | | using TI = typename C::TI; |
303 | | using ResultHandler<C>::threshold; |
304 | | |
305 | | T* vals; |
306 | | TI* ids; |
307 | | |
308 | | size_t i; // number of stored elements |
309 | | size_t n; // number of requested elements |
310 | | size_t capacity; // size of storage |
311 | | |
312 | | ReservoirTopN() {} |
313 | | |
314 | | ReservoirTopN(size_t n, size_t capacity, T* vals, TI* ids) |
315 | 0 | : vals(vals), ids(ids), i(0), n(n), capacity(capacity) { |
316 | 0 | assert(n < capacity); |
317 | 0 | threshold = C::neutral(); |
318 | 0 | } Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinIflEEEC2EmmPfPl Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxIflEEEC2EmmPfPl Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxItiEEEC2EmmPtPi Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinItiEEEC2EmmPtPi Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxItlEEEC2EmmPtPl Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinItlEEEC2EmmPtPl |
319 | | |
320 | 0 | bool add_result(T val, TI id) final { |
321 | 0 | bool updated_threshold = false; |
322 | 0 | if (C::cmp(threshold, val)) { |
323 | 0 | if (i == capacity) { |
324 | 0 | shrink_fuzzy(); |
325 | 0 | updated_threshold = true; |
326 | 0 | } |
327 | 0 | vals[i] = val; |
328 | 0 | ids[i] = id; |
329 | 0 | i++; |
330 | 0 | } |
331 | 0 | return updated_threshold; |
332 | 0 | } Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinIflEEE10add_resultEfl Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxIflEEE10add_resultEfl Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxItiEEE10add_resultEti Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinItiEEE10add_resultEti Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxItlEEE10add_resultEtl Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinItlEEE10add_resultEtl |
333 | | |
334 | 0 | void add(T val, TI id) { |
335 | 0 | add_result(val, id); |
336 | 0 | } Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxItiEEE3addEti Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinItiEEE3addEti Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxItlEEE3addEtl Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinItlEEE3addEtl |
337 | | |
338 | | // reduce storage from capacity to anything |
339 | | // between n and (capacity + n) / 2 |
340 | 0 | void shrink_fuzzy() { |
341 | 0 | assert(i == capacity); |
342 | | |
343 | 0 | threshold = partition_fuzzy<C>( |
344 | 0 | vals, ids, capacity, n, (capacity + n) / 2, &i); |
345 | 0 | } Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinIflEEE12shrink_fuzzyEv Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxIflEEE12shrink_fuzzyEv Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxItiEEE12shrink_fuzzyEv Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinItiEEE12shrink_fuzzyEv Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxItlEEE12shrink_fuzzyEv Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinItlEEE12shrink_fuzzyEv |
346 | | |
347 | 0 | void shrink() { |
348 | 0 | threshold = partition<C>(vals, ids, i, n); |
349 | 0 | i = n; |
350 | 0 | } Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxItiEEE6shrinkEv Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinItiEEE6shrinkEv Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMaxItlEEE6shrinkEv Unexecuted instantiation: _ZN5faiss13ReservoirTopNINS_4CMinItlEEE6shrinkEv |
351 | | |
352 | 0 | void to_result(T* heap_dis, TI* heap_ids) const { |
353 | 0 | for (int j = 0; j < std::min(i, n); j++) { |
354 | 0 | heap_push<C>(j + 1, heap_dis, heap_ids, vals[j], ids[j]); |
355 | 0 | } |
356 | |
|
357 | 0 | if (i < n) { |
358 | 0 | heap_reorder<C>(i, heap_dis, heap_ids); |
359 | | // add empty results |
360 | 0 | heap_heapify<C>(n - i, heap_dis + i, heap_ids + i); |
361 | 0 | } else { |
362 | | // add remaining elements |
363 | 0 | heap_addn<C>(n, heap_dis, heap_ids, vals + n, ids + n, i - n); |
364 | 0 | heap_reorder<C>(n, heap_dis, heap_ids); |
365 | 0 | } |
366 | 0 | } Unexecuted instantiation: _ZNK5faiss13ReservoirTopNINS_4CMinIflEEE9to_resultEPfPl Unexecuted instantiation: _ZNK5faiss13ReservoirTopNINS_4CMaxIflEEE9to_resultEPfPl |
367 | | }; |
368 | | |
369 | | template <class C, bool use_sel = false> |
370 | | struct ReservoirBlockResultHandler : BlockResultHandler<C, use_sel> { |
371 | | using T = typename C::T; |
372 | | using TI = typename C::TI; |
373 | | using BlockResultHandler<C, use_sel>::i0; |
374 | | using BlockResultHandler<C, use_sel>::i1; |
375 | | |
376 | | T* heap_dis_tab; |
377 | | TI* heap_ids_tab; |
378 | | |
379 | | int64_t k; // number of results to keep |
380 | | size_t capacity; // capacity of the reservoirs |
381 | | |
382 | | ReservoirBlockResultHandler( |
383 | | size_t nq, |
384 | | T* heap_dis_tab, |
385 | | TI* heap_ids_tab, |
386 | | size_t k, |
387 | | const IDSelector* sel = nullptr) |
388 | 0 | : BlockResultHandler<C, use_sel>(nq, sel), |
389 | 0 | heap_dis_tab(heap_dis_tab), |
390 | 0 | heap_ids_tab(heap_ids_tab), |
391 | 0 | k(k) { |
392 | | // double then round up to multiple of 16 (for SIMD alignment) |
393 | 0 | capacity = (2 * k + 15) & ~15; |
394 | 0 | } Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb1EEC2EmPfPlmPKNS_10IDSelectorE Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb0EEC2EmPfPlmPKNS_10IDSelectorE Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb1EEC2EmPfPlmPKNS_10IDSelectorE Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb0EEC2EmPfPlmPKNS_10IDSelectorE |
395 | | |
396 | | /****************************************************** |
397 | | * API for 1 result at a time (each SingleResultHandler is |
398 | | * called from 1 thread) |
399 | | */ |
400 | | |
401 | | struct SingleResultHandler : ReservoirTopN<C> { |
402 | | ReservoirBlockResultHandler& hr; |
403 | | |
404 | | std::vector<T> reservoir_dis; |
405 | | std::vector<TI> reservoir_ids; |
406 | | |
407 | | explicit SingleResultHandler(ReservoirBlockResultHandler& hr) |
408 | 0 | : ReservoirTopN<C>(hr.k, hr.capacity, nullptr, nullptr), |
409 | 0 | hr(hr) {} Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandlerC2ERS3_ Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandlerC2ERS3_ Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandlerC2ERS3_ Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandlerC2ERS3_ |
410 | | |
411 | | size_t qno; |
412 | | |
413 | | /// begin results for query # i |
414 | 0 | void begin(size_t qno_2) { |
415 | 0 | reservoir_dis.resize(hr.capacity); |
416 | 0 | reservoir_ids.resize(hr.capacity); |
417 | 0 | this->vals = reservoir_dis.data(); |
418 | 0 | this->ids = reservoir_ids.data(); |
419 | 0 | this->i = 0; // size of reservoir |
420 | 0 | this->threshold = C::neutral(); |
421 | 0 | this->qno = qno_2; |
422 | 0 | } Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandler5beginEm Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandler5beginEm Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandler5beginEm Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandler5beginEm |
423 | | |
424 | | /// series of results for query qno is done |
425 | 0 | void end() { |
426 | 0 | T* heap_dis = hr.heap_dis_tab + qno * hr.k; |
427 | 0 | TI* heap_ids = hr.heap_ids_tab + qno * hr.k; |
428 | 0 | this->to_result(heap_dis, heap_ids); |
429 | 0 | } Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandler3endEv Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandler3endEv Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandler3endEv Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandler3endEv |
430 | | }; |
431 | | |
432 | | /****************************************************** |
433 | | * API for multiple results (called from 1 thread) |
434 | | */ |
435 | | |
436 | | std::vector<T> reservoir_dis; |
437 | | std::vector<TI> reservoir_ids; |
438 | | std::vector<ReservoirTopN<C>> reservoirs; |
439 | | |
440 | | /// begin |
441 | 0 | void begin_multiple(size_t i0_2, size_t i1_2) { |
442 | 0 | this->i0 = i0_2; |
443 | 0 | this->i1 = i1_2; |
444 | 0 | reservoir_dis.resize((i1 - i0) * capacity); |
445 | 0 | reservoir_ids.resize((i1 - i0) * capacity); |
446 | 0 | reservoirs.clear(); |
447 | 0 | for (size_t i = i0_2; i < i1_2; i++) { |
448 | 0 | reservoirs.emplace_back( |
449 | 0 | k, |
450 | 0 | capacity, |
451 | 0 | reservoir_dis.data() + (i - i0_2) * capacity, |
452 | 0 | reservoir_ids.data() + (i - i0_2) * capacity); |
453 | 0 | } |
454 | 0 | } Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb1EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb0EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb1EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb0EE14begin_multipleEmm |
455 | | |
456 | | /// add results for query i0..i1 and j0..j1 |
457 | 0 | void add_results(size_t j0, size_t j1, const T* dis_tab) { |
458 | 0 | #pragma omp parallel for |
459 | 0 | for (int64_t i = i0; i < i1; i++) { |
460 | 0 | ReservoirTopN<C>& reservoir = reservoirs[i - i0]; |
461 | 0 | const T* dis_tab_i = dis_tab + (j1 - j0) * (i - i0) - j0; |
462 | 0 | for (size_t j = j0; j < j1; j++) { |
463 | 0 | T dis = dis_tab_i[j]; |
464 | 0 | reservoir.add_result(dis, j); |
465 | 0 | } |
466 | 0 | } Unexecuted instantiation: IndexFlatCodes.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexFlatCodes.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexFlatCodes.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexFlatCodes.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexRaBitQ.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexRaBitQ.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexRaBitQ.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: IndexRaBitQ.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: distances.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: distances.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: distances.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb1EE11add_resultsEmmPKf.omp_outlined_debug__ Unexecuted instantiation: distances.cpp:_ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf.omp_outlined_debug__ |
467 | 0 | } Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb1EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb1EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf |
468 | | |
469 | | /// series of results for queries i0..i1 is done |
470 | 0 | void end_multiple() final { |
471 | | // maybe parallel for |
472 | 0 | for (size_t i = i0; i < i1; i++) { |
473 | 0 | reservoirs[i - i0].to_result( |
474 | 0 | heap_dis_tab + i * k, heap_ids_tab + i * k); |
475 | 0 | } |
476 | 0 | } Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb1EE12end_multipleEv Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMinIflEELb0EE12end_multipleEv Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb1EE12end_multipleEv Unexecuted instantiation: _ZN5faiss27ReservoirBlockResultHandlerINS_4CMaxIflEELb0EE12end_multipleEv |
477 | | }; |
478 | | |
479 | | /***************************************************************** |
480 | | * Result handler for range searches |
481 | | *****************************************************************/ |
482 | | |
483 | | template <class C, bool use_sel = false> |
484 | | struct RangeSearchBlockResultHandler : BlockResultHandler<C, use_sel> { |
485 | | using T = typename C::T; |
486 | | using TI = typename C::TI; |
487 | | using BlockResultHandler<C, use_sel>::i0; |
488 | | using BlockResultHandler<C, use_sel>::i1; |
489 | | |
490 | | RangeSearchResult* res; |
491 | | T radius; |
492 | | |
493 | | RangeSearchBlockResultHandler( |
494 | | RangeSearchResult* res, |
495 | | float radius, |
496 | | const IDSelector* sel = nullptr) |
497 | 76 | : BlockResultHandler<C, use_sel>(res->nq, sel), |
498 | 76 | res(res), |
499 | 76 | radius(radius) {} Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb1EEC2EPNS_17RangeSearchResultEfPKNS_10IDSelectorE _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb0EEC2EPNS_17RangeSearchResultEfPKNS_10IDSelectorE Line | Count | Source | 497 | 3 | : BlockResultHandler<C, use_sel>(res->nq, sel), | 498 | 3 | res(res), | 499 | 3 | radius(radius) {} |
Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb1EEC2EPNS_17RangeSearchResultEfPKNS_10IDSelectorE _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb0EEC2EPNS_17RangeSearchResultEfPKNS_10IDSelectorE Line | Count | Source | 497 | 73 | : BlockResultHandler<C, use_sel>(res->nq, sel), | 498 | 73 | res(res), | 499 | 73 | radius(radius) {} |
|
500 | | |
501 | | /****************************************************** |
502 | | * API for 1 result at a time (each SingleResultHandler is |
503 | | * called from 1 thread) |
504 | | ******************************************************/ |
505 | | |
506 | | struct SingleResultHandler : ResultHandler<C> { |
507 | | // almost the same interface as RangeSearchResultHandler |
508 | | using ResultHandler<C>::threshold; |
509 | | RangeSearchPartialResult pres; |
510 | | RangeQueryResult* qr = nullptr; |
511 | | |
512 | | explicit SingleResultHandler(RangeSearchBlockResultHandler& rh) |
513 | 76 | : pres(rh.res) { |
514 | 76 | threshold = rh.radius; |
515 | 76 | } Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandlerC2ERS3_ _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandlerC2ERS3_ Line | Count | Source | 513 | 3 | : pres(rh.res) { | 514 | 3 | threshold = rh.radius; | 515 | 3 | } |
Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandlerC2ERS3_ _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandlerC2ERS3_ Line | Count | Source | 513 | 73 | : pres(rh.res) { | 514 | 73 | threshold = rh.radius; | 515 | 73 | } |
|
516 | | |
517 | | /// begin results for query # i |
518 | 76 | void begin(size_t i) { |
519 | 76 | qr = &pres.new_result(i); |
520 | 76 | } Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandler5beginEm _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandler5beginEm Line | Count | Source | 518 | 3 | void begin(size_t i) { | 519 | 3 | qr = &pres.new_result(i); | 520 | 3 | } |
Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandler5beginEm _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandler5beginEm Line | Count | Source | 518 | 73 | void begin(size_t i) { | 519 | 73 | qr = &pres.new_result(i); | 520 | 73 | } |
|
521 | | |
522 | | /// add one result for query i |
523 | 5.62k | bool add_result(T dis, TI idx) final { |
524 | 5.62k | if (C::cmp(threshold, dis)) { |
525 | 4.88k | qr->add(dis, idx); |
526 | 4.88k | } |
527 | 5.62k | return false; |
528 | 5.62k | } Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandler10add_resultEfl _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandler10add_resultEfl Line | Count | Source | 523 | 1.50k | bool add_result(T dis, TI idx) final { | 524 | 1.50k | if (C::cmp(threshold, dis)) { | 525 | 753 | qr->add(dis, idx); | 526 | 753 | } | 527 | 1.50k | return false; | 528 | 1.50k | } |
Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandler10add_resultEfl _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandler10add_resultEfl Line | Count | Source | 523 | 4.12k | bool add_result(T dis, TI idx) final { | 524 | 4.12k | if (C::cmp(threshold, dis)) { | 525 | 4.12k | qr->add(dis, idx); | 526 | 4.12k | } | 527 | 4.12k | return false; | 528 | 4.12k | } |
|
529 | | |
530 | | /// series of results for query i is done |
531 | 76 | void end() {} Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandler3endEv _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandler3endEv Line | Count | Source | 531 | 3 | void end() {} |
Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandler3endEv _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandler3endEv Line | Count | Source | 531 | 73 | void end() {} |
|
532 | | |
533 | 76 | ~SingleResultHandler() { |
534 | 76 | try { |
535 | | // finalize the partial result |
536 | 76 | pres.finalize(); |
537 | 76 | } catch ([[maybe_unused]] const faiss::FaissException& e) { |
538 | | // Do nothing if allocation fails in finalizing partial results. |
539 | 0 | #ifndef NDEBUG |
540 | 0 | std::cerr << e.what() << std::endl; |
541 | 0 | #endif |
542 | 0 | } |
543 | 76 | } Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb1EE19SingleResultHandlerD2Ev _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb0EE19SingleResultHandlerD2Ev Line | Count | Source | 533 | 3 | ~SingleResultHandler() { | 534 | 3 | try { | 535 | | // finalize the partial result | 536 | 3 | pres.finalize(); | 537 | 3 | } catch ([[maybe_unused]] const faiss::FaissException& e) { | 538 | | // Do nothing if allocation fails in finalizing partial results. | 539 | 0 | #ifndef NDEBUG | 540 | 0 | std::cerr << e.what() << std::endl; | 541 | 0 | #endif | 542 | 0 | } | 543 | 3 | } |
Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb1EE19SingleResultHandlerD2Ev _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb0EE19SingleResultHandlerD2Ev Line | Count | Source | 533 | 73 | ~SingleResultHandler() { | 534 | 73 | try { | 535 | | // finalize the partial result | 536 | 73 | pres.finalize(); | 537 | 73 | } catch ([[maybe_unused]] const faiss::FaissException& e) { | 538 | | // Do nothing if allocation fails in finalizing partial results. | 539 | 0 | #ifndef NDEBUG | 540 | 0 | std::cerr << e.what() << std::endl; | 541 | 0 | #endif | 542 | 0 | } | 543 | 73 | } |
|
544 | | }; |
545 | | |
546 | | /****************************************************** |
547 | | * API for multiple results (called from 1 thread) |
548 | | ******************************************************/ |
549 | | |
550 | | std::vector<RangeSearchPartialResult*> partial_results; |
551 | | std::vector<size_t> j0s; |
552 | | int pr = 0; |
553 | | |
554 | | /// begin |
555 | 0 | void begin_multiple(size_t i0_2, size_t i1_2) { |
556 | 0 | this->i0 = i0_2; |
557 | 0 | this->i1 = i1_2; |
558 | 0 | } Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb1EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb0EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb1EE14begin_multipleEmm Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb0EE14begin_multipleEmm |
559 | | |
560 | | /// add results for query i0..i1 and j0..j1 |
561 | | |
562 | 0 | void add_results(size_t j0, size_t j1, const T* dis_tab) { |
563 | 0 | RangeSearchPartialResult* pres; |
564 | | // there is one RangeSearchPartialResult structure per j0 |
565 | | // (= block of columns of the large distance matrix) |
566 | | // it is a bit tricky to find the poper PartialResult structure |
567 | | // because the inner loop is on db not on queries. |
568 | |
|
569 | 0 | if (pr < j0s.size() && j0 == j0s[pr]) { |
570 | 0 | pres = partial_results[pr]; |
571 | 0 | pr++; |
572 | 0 | } else if (j0 == 0 && j0s.size() > 0) { |
573 | 0 | pr = 0; |
574 | 0 | pres = partial_results[pr]; |
575 | 0 | pr++; |
576 | 0 | } else { // did not find this j0 |
577 | 0 | pres = new RangeSearchPartialResult(res); |
578 | 0 | partial_results.push_back(pres); |
579 | 0 | j0s.push_back(j0); |
580 | 0 | pr = partial_results.size(); |
581 | 0 | } |
582 | |
|
583 | 0 | for (size_t i = i0; i < i1; i++) { |
584 | 0 | const float* ip_line = dis_tab + (i - i0) * (j1 - j0); |
585 | 0 | RangeQueryResult& qres = pres->new_result(i); |
586 | |
|
587 | 0 | for (size_t j = j0; j < j1; j++) { |
588 | 0 | float dis = *ip_line++; |
589 | 0 | if (C::cmp(radius, dis)) { |
590 | 0 | qres.add(dis, j); |
591 | 0 | } |
592 | 0 | } |
593 | 0 | } |
594 | 0 | } Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb1EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb0EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb1EE11add_resultsEmmPKf Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb0EE11add_resultsEmmPKf |
595 | | |
596 | 76 | ~RangeSearchBlockResultHandler() { |
597 | 76 | try { |
598 | 76 | if (partial_results.size() > 0) { |
599 | 0 | RangeSearchPartialResult::merge(partial_results); |
600 | 0 | } |
601 | 76 | } catch ([[maybe_unused]] const faiss::FaissException& e) { |
602 | | // Do nothing if allocation fails in merge. |
603 | 0 | #ifndef NDEBUG |
604 | 0 | std::cerr << e.what() << std::endl; |
605 | 0 | #endif |
606 | 0 | } |
607 | 76 | } Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb1EED2Ev _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMinIflEELb0EED2Ev Line | Count | Source | 596 | 3 | ~RangeSearchBlockResultHandler() { | 597 | 3 | try { | 598 | 3 | if (partial_results.size() > 0) { | 599 | 0 | RangeSearchPartialResult::merge(partial_results); | 600 | 0 | } | 601 | 3 | } catch ([[maybe_unused]] const faiss::FaissException& e) { | 602 | | // Do nothing if allocation fails in merge. | 603 | 0 | #ifndef NDEBUG | 604 | 0 | std::cerr << e.what() << std::endl; | 605 | 0 | #endif | 606 | 0 | } | 607 | 3 | } |
Unexecuted instantiation: _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb1EED2Ev _ZN5faiss29RangeSearchBlockResultHandlerINS_4CMaxIflEELb0EED2Ev Line | Count | Source | 596 | 73 | ~RangeSearchBlockResultHandler() { | 597 | 73 | try { | 598 | 73 | if (partial_results.size() > 0) { | 599 | 0 | RangeSearchPartialResult::merge(partial_results); | 600 | 0 | } | 601 | 73 | } catch ([[maybe_unused]] const faiss::FaissException& e) { | 602 | | // Do nothing if allocation fails in merge. | 603 | 0 | #ifndef NDEBUG | 604 | 0 | std::cerr << e.what() << std::endl; | 605 | 0 | #endif | 606 | 0 | } | 607 | 73 | } |
|
608 | | }; |
609 | | |
610 | | /***************************************************************** |
611 | | * Dispatcher function to choose the right knn result handler depending on k |
612 | | *****************************************************************/ |
613 | | |
614 | | // declared in distances.cpp |
615 | | FAISS_API extern int distance_compute_min_k_reservoir; |
616 | | |
617 | | template <class Consumer, class... Types> |
618 | | typename Consumer::T dispatch_knn_ResultHandler( |
619 | | size_t nx, |
620 | | float* vals, |
621 | | int64_t* ids, |
622 | | size_t k, |
623 | | MetricType metric, |
624 | | const IDSelector* sel, |
625 | | Consumer& consumer, |
626 | 0 | Types... args) { |
627 | 0 | #define DISPATCH_C_SEL(C, use_sel) \ |
628 | 0 | if (k == 1) { \ |
629 | 0 | Top1BlockResultHandler<C, use_sel> res(nx, vals, ids, sel); \ |
630 | 0 | return consumer.template f<>(res, args...); \ |
631 | 0 | } else if (k < distance_compute_min_k_reservoir) { \ |
632 | 0 | HeapBlockResultHandler<C, use_sel> res(nx, vals, ids, k, sel); \ |
633 | 0 | return consumer.template f<>(res, args...); \ |
634 | 0 | } else { \ |
635 | 0 | ReservoirBlockResultHandler<C, use_sel> res(nx, vals, ids, k, sel); \ |
636 | 0 | return consumer.template f<>(res, args...); \ |
637 | 0 | } |
638 | |
|
639 | 0 | if (is_similarity_metric(metric)) { |
640 | 0 | using C = CMin<float, int64_t>; |
641 | 0 | if (sel) { |
642 | 0 | DISPATCH_C_SEL(C, true); |
643 | 0 | } else { |
644 | 0 | DISPATCH_C_SEL(C, false); |
645 | 0 | } |
646 | 0 | } else { |
647 | 0 | using C = CMax<float, int64_t>; |
648 | 0 | if (sel) { |
649 | 0 | DISPATCH_C_SEL(C, true); |
650 | 0 | } else { |
651 | 0 | DISPATCH_C_SEL(C, false); |
652 | 0 | } |
653 | 0 | } |
654 | 0 | #undef DISPATCH_C_SEL |
655 | 0 | } Unexecuted instantiation: IndexFlatCodes.cpp:_ZN5faiss26dispatch_knn_ResultHandlerINS_12_GLOBAL__N_130Run_search_with_decompress_resEJPKNS_14IndexFlatCodesEPKfEEENT_1TEmPfPlmNS_10MetricTypeEPKNS_10IDSelectorERS8_DpT0_ Unexecuted instantiation: IndexRaBitQ.cpp:_ZN5faiss26dispatch_knn_ResultHandlerINS_12_GLOBAL__N_122Run_search_with_dc_resEJPKNS_11IndexRaBitQEPKfEEENT_1TEmPfPlmNS_10MetricTypeEPKNS_10IDSelectorERS8_DpT0_ Unexecuted instantiation: distances.cpp:_ZN5faiss26dispatch_knn_ResultHandlerINS_12_GLOBAL__N_124Run_search_inner_productEJPKfS4_mmmEEENT_1TEmPfPlmNS_10MetricTypeEPKNS_10IDSelectorERS5_DpT0_ Unexecuted instantiation: distances.cpp:_ZN5faiss26dispatch_knn_ResultHandlerINS_12_GLOBAL__N_116Run_search_L2sqrEJPKfS4_mmmS4_EEENT_1TEmPfPlmNS_10MetricTypeEPKNS_10IDSelectorERS5_DpT0_ |
656 | | |
657 | | template <class Consumer, class... Types> |
658 | | typename Consumer::T dispatch_range_ResultHandler( |
659 | | RangeSearchResult* res, |
660 | | float radius, |
661 | | MetricType metric, |
662 | | const IDSelector* sel, |
663 | | Consumer& consumer, |
664 | 3 | Types... args) { |
665 | 3 | #define DISPATCH_C_SEL(C, use_sel) \ |
666 | 3 | RangeSearchBlockResultHandler<C, use_sel> resb(res, radius, sel); \ |
667 | 3 | return consumer.template f<>(resb, args...); |
668 | | |
669 | 3 | if (is_similarity_metric(metric)) { |
670 | 3 | using C = CMin<float, int64_t>; |
671 | 3 | if (sel) { |
672 | 0 | DISPATCH_C_SEL(C, true); |
673 | 3 | } else { |
674 | 3 | DISPATCH_C_SEL(C, false); |
675 | 0 | } |
676 | 3 | } else { |
677 | 0 | using C = CMax<float, int64_t>; |
678 | 0 | if (sel) { |
679 | 0 | DISPATCH_C_SEL(C, true); |
680 | 0 | } else { |
681 | 0 | DISPATCH_C_SEL(C, false); |
682 | 0 | } |
683 | 0 | } |
684 | 3 | #undef DISPATCH_C_SEL |
685 | 3 | } Unexecuted instantiation: IndexFlatCodes.cpp:_ZN5faiss28dispatch_range_ResultHandlerINS_12_GLOBAL__N_130Run_search_with_decompress_resEJPKNS_14IndexFlatCodesEPKfEEENT_1TEPNS_17RangeSearchResultEfNS_10MetricTypeEPKNS_10IDSelectorERS8_DpT0_ Unexecuted instantiation: IndexRaBitQ.cpp:_ZN5faiss28dispatch_range_ResultHandlerINS_12_GLOBAL__N_122Run_search_with_dc_resEJPKNS_11IndexRaBitQEPKfEEENT_1TEPNS_17RangeSearchResultEfNS_10MetricTypeEPKNS_10IDSelectorERS8_DpT0_ Unexecuted instantiation: distances.cpp:_ZN5faiss28dispatch_range_ResultHandlerINS_12_GLOBAL__N_116Run_search_L2sqrEJPKfS4_mmmDnEEENT_1TEPNS_17RangeSearchResultEfNS_10MetricTypeEPKNS_10IDSelectorERS5_DpT0_ distances.cpp:_ZN5faiss28dispatch_range_ResultHandlerINS_12_GLOBAL__N_124Run_search_inner_productEJPKfS4_mmmEEENT_1TEPNS_17RangeSearchResultEfNS_10MetricTypeEPKNS_10IDSelectorERS5_DpT0_ Line | Count | Source | 664 | 3 | Types... args) { | 665 | 3 | #define DISPATCH_C_SEL(C, use_sel) \ | 666 | 3 | RangeSearchBlockResultHandler<C, use_sel> resb(res, radius, sel); \ | 667 | 3 | return consumer.template f<>(resb, args...); | 668 | | | 669 | 3 | if (is_similarity_metric(metric)) { | 670 | 3 | using C = CMin<float, int64_t>; | 671 | 3 | if (sel) { | 672 | 0 | DISPATCH_C_SEL(C, true); | 673 | 3 | } else { | 674 | 3 | DISPATCH_C_SEL(C, false); | 675 | 0 | } | 676 | 3 | } else { | 677 | 0 | using C = CMax<float, int64_t>; | 678 | 0 | if (sel) { | 679 | 0 | DISPATCH_C_SEL(C, true); | 680 | 0 | } else { | 681 | 0 | DISPATCH_C_SEL(C, false); | 682 | 0 | } | 683 | 0 | } | 684 | 3 | #undef DISPATCH_C_SEL | 685 | 3 | } |
|
686 | | |
687 | | } // namespace faiss |