Skip to content

Commit 6c0a67a

Browse files
algoriddlemeta-codesync[bot]
authored andcommitted
Switch all search paths to FastScanCodeScanner and remove make_knn_handler (#4904)
Summary: Pull Request resolved: #4904 Now that every make_knn_scanner() returns a real scanner (never nullptr), switch all callers to use scanners directly and remove make_knn_handler. Add impl param to make_knn_scanner and its factory so heap vs reservoir selection respects the implem setting. Switch IndexFastScan search_implem_12/14, IndexIVFFastScan search_dispatch_implem/range_search, and IndexIVFPQFastScan scan_codes to scanner-only paths. Add range scanner factories (make_range_scanner, make_partial_range_scanner). Remove make_knn_handler from all classes. Change search_implem_10/12 scanner param from pointer to reference. Reviewed By: mdouze Differential Revision: D96116555
1 parent 8091063 commit 6c0a67a

15 files changed

Lines changed: 316 additions & 411 deletions

faiss/IndexFastScan.cpp

Lines changed: 24 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424

2525
namespace faiss {
2626

27-
using namespace simd_result_handlers;
28-
2927
inline size_t roundup(size_t a, size_t b) {
3028
return (a + b - 1) / b * b;
3129
}
@@ -219,48 +217,10 @@ std::unique_ptr<FastScanCodeScanner> IndexFastScan::make_knn_scanner(
219217
float* distances,
220218
idx_t* labels,
221219
const IDSelector* sel,
222-
const FastScanDistancePostProcessing&) const {
223-
return make_fast_scan_knn_scanner(
224-
is_max, 0, n, ntotal, k, distances, labels, sel);
225-
}
226-
227-
// Default implementation of make_knn_handler with centralized fallback logic
228-
SIMDResultHandlerToFloat* IndexFastScan::make_knn_handler(
229-
bool is_max,
230220
int impl,
231-
idx_t n,
232-
idx_t k,
233-
size_t ntotal,
234-
float* distances,
235-
idx_t* labels,
236-
const IDSelector* sel,
237221
const FastScanDistancePostProcessing&) const {
238-
// Create default handlers based on k and impl
239-
if (is_max) {
240-
using HeapHC = HeapHandler<CMax<uint16_t, int>, false>;
241-
using ReservoirHC = ReservoirHandler<CMax<uint16_t, int>, false>;
242-
using SingleResultHC = SingleResultHandler<CMax<uint16_t, int>, false>;
243-
244-
if (k == 1) {
245-
return new SingleResultHC(n, ntotal, distances, labels, sel);
246-
} else if (impl % 2 == 0) {
247-
return new HeapHC(n, ntotal, k, distances, labels, sel);
248-
} else {
249-
return new ReservoirHC(n, ntotal, k, 2 * k, distances, labels, sel);
250-
}
251-
} else {
252-
using HeapHC = HeapHandler<CMin<uint16_t, int>, false>;
253-
using ReservoirHC = ReservoirHandler<CMin<uint16_t, int>, false>;
254-
using SingleResultHC = SingleResultHandler<CMin<uint16_t, int>, false>;
255-
256-
if (k == 1) {
257-
return new SingleResultHC(n, ntotal, distances, labels, sel);
258-
} else if (impl % 2 == 0) {
259-
return new HeapHC(n, ntotal, k, distances, labels, sel);
260-
} else {
261-
return new ReservoirHC(n, ntotal, k, 2 * k, distances, labels, sel);
262-
}
263-
}
222+
return make_fast_scan_knn_scanner(
223+
is_max, impl, n, ntotal, k, distances, labels, sel);
264224
}
265225

266226
using namespace quantize_lut;
@@ -481,7 +441,6 @@ void IndexFastScan::search_implem_12(
481441
idx_t* labels,
482442
int impl,
483443
const FastScanDistancePostProcessing& context) const {
484-
using RH = ResultHandlerCompare<C, false>;
485444
FAISS_THROW_IF_NOT(bbs == 32);
486445

487446
// handle qbs2 blocking by recursive call
@@ -532,36 +491,26 @@ void IndexFastScan::search_implem_12(
532491
pq4_pack_LUT_qbs(qbs, M2, quantized_dis_tables.get(), LUT.get());
533492
FAISS_THROW_IF_NOT(LUT_nq == n);
534493

535-
std::unique_ptr<RH> handler(
536-
static_cast<RH*>(make_knn_handler(
537-
C::is_max,
538-
impl,
539-
n,
540-
k,
541-
ntotal,
542-
distances,
543-
labels,
544-
nullptr,
545-
context)));
546-
547-
handler->disable = bool(skip & 2);
548-
handler->normalizers = normalizers.get();
549-
550-
if (skip & 4) {
551-
// pass
552-
} else {
553-
pq4_accumulate_loop_qbs(
494+
auto scanner = make_knn_scanner(
495+
C::is_max, n, k, ntotal, distances, labels, nullptr, impl, context);
496+
auto* rh = scanner->handler();
497+
rh->normalizers = normalizers.get();
498+
// Note: skip & 2 previously set handler->disable (run kernel,
499+
// discard results). Through the scanner path, skip & 2 now skips
500+
// the kernel entirely (same as skip & 4), since disable is not
501+
// accessible through the SIMDResultHandlerToFloat* interface.
502+
if (!(skip & (2 | 4))) {
503+
scanner->accumulate_loop_qbs(
554504
qbs,
555505
ntotal2,
556506
M2,
557507
codes.get(),
558508
LUT.get(),
559-
*handler.get(),
560509
context.pq2x4_scale,
561510
get_block_stride());
562511
}
563512
if (!(skip & 8)) {
564-
handler->end();
513+
rh->end();
565514
}
566515
}
567516

@@ -576,7 +525,6 @@ void IndexFastScan::search_implem_14(
576525
idx_t* labels,
577526
int impl,
578527
const FastScanDistancePostProcessing& context) const {
579-
using RH = ResultHandlerCompare<C, false>;
580528
FAISS_THROW_IF_NOT(bbs % 32 == 0);
581529

582530
int qbs2 = qbs == 0 ? 4 : qbs;
@@ -616,36 +564,27 @@ void IndexFastScan::search_implem_14(
616564
AlignedTable<uint8_t> LUT(n * dim12);
617565
pq4_pack_LUT(n, M2, quantized_dis_tables.get(), LUT.get());
618566

619-
std::unique_ptr<RH> handler(
620-
static_cast<RH*>(make_knn_handler(
621-
C::is_max,
622-
impl,
623-
n,
624-
k,
625-
ntotal,
626-
distances,
627-
labels,
628-
nullptr,
629-
context)));
630-
handler->disable = bool(skip & 2);
631-
handler->normalizers = normalizers.get();
632-
633-
if (skip & 4) {
634-
// pass
635-
} else {
636-
pq4_accumulate_loop(
567+
auto scanner = make_knn_scanner(
568+
C::is_max, n, k, ntotal, distances, labels, nullptr, impl, context);
569+
auto* rh = scanner->handler();
570+
rh->normalizers = normalizers.get();
571+
// Note: skip & 2 previously set handler->disable (run kernel,
572+
// discard results). Through the scanner path, skip & 2 now skips
573+
// the kernel entirely (same as skip & 4), since disable is not
574+
// accessible through the SIMDResultHandlerToFloat* interface.
575+
if (!(skip & (2 | 4))) {
576+
scanner->accumulate_loop(
637577
n,
638578
ntotal2,
639579
bbs,
640580
M2,
641581
codes.get(),
642582
LUT.get(),
643-
*handler.get(),
644583
context.pq2x4_scale,
645584
get_block_stride());
646585
}
647586
if (!(skip & 8)) {
648-
handler->end();
587+
rh->end();
649588
}
650589
}
651590

faiss/IndexFastScan.h

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ namespace faiss {
1818

1919
struct CodePacker;
2020
struct IDSelector;
21-
struct SIMDResultHandlerToFloat;
2221

2322
/** Fast scan version of IndexPQ and IndexAQ. Works for 4-bit PQ and AQ for now.
2423
*
@@ -138,36 +137,9 @@ struct IndexFastScan : Index {
138137
float* distances,
139138
idx_t* labels,
140139
const IDSelector* sel,
140+
int impl = 0,
141141
const FastScanDistancePostProcessing& context = {}) const;
142142

143-
/** Create a KNN handler for this index type
144-
*
145-
* This method can be overridden by derived classes to provide
146-
* specialized handlers (e.g., RaBitQHeapHandler for RaBitQ indexes).
147-
* Base implementation creates standard handlers based on k and impl.
148-
*
149-
* @param is_max whether to use CMax comparator (true) or CMin (false)
150-
* @param impl implementation number
151-
* @param n number of queries
152-
* @param k number of neighbors to find
153-
* @param ntotal total number of vectors in database
154-
* @param distances output distances array
155-
* @param labels output labels array
156-
* @param sel optional ID selector
157-
* @param context processing context for distance post-processing
158-
* @return pointer to created handler (never returns nullptr)
159-
*/
160-
virtual SIMDResultHandlerToFloat* make_knn_handler(
161-
bool is_max,
162-
int impl,
163-
idx_t n,
164-
idx_t k,
165-
size_t ntotal,
166-
float* distances,
167-
idx_t* labels,
168-
const IDSelector* sel,
169-
const FastScanDistancePostProcessing& context) const;
170-
171143
// called by search function
172144
void compute_quantized_LUT(
173145
idx_t n,

0 commit comments

Comments
 (0)